无需密码自动登录,系统用户名shiyanlou,密码shiyanlou
本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面上的程序:
-
LX终端(LXTerminal): Linux命令行终端,打开后会进入Bash环境,可以使用Linux命令
-
Firefox:浏览器,可以用在需要前端界面的课程里,只需要打开环境里写的HTML/JS页面即可
-
GVim:非常好用的编辑器,最简单的用法可以参考课程Vim编辑器
使用GVim编辑器输入实验所需的代码及文件,使用LX终端(LXTerminal)运行所需命令进行操作。
完成实验后可以点击桌面上方的“实验截图”保存并分享实验结果到微博,向好友展示自己的学习进度。实验楼提供后台系统截图,可以真实有效证明您已经完成了实验。
实验记录页面可以在“我的主页”中查看,其中含有每次实验的截图及笔记,以及每次实验的有效学习时间(指的是在实验桌面内操作的时间,如果没有操作,系统会记录为发呆时间)。这些都是您学习的真实性证明。
本课程中的所有源码可以通过以下方式下载:
https://github.com/pobing/sinatra-blog-api.git
大家有学习过程中有任何问题,或有任何纰漏欢迎通过下面的邮箱地址咨询和反馈:
cn.jdongATgmail.com
现在大的应用程序分为前后端,前端有 web 端、移动端等。 为了满足不同的前端和后端通信,后端得提供一套标准的API方便与前端通信。
而 RESTful API是目前比较成熟的一套互联网应用程序的API设计理论。
本项目基于Ruby 的 sinatra 框架实现一个简单的 Blog Restful API 应用,提供基本的增删改查接口。
sudo apt-get install ruby-dev
sudo apt-get install libsqlite3-dev
sudo gem install bundler
mkdir sinatra-blog-api
cd sinatra-blog-api
cat > Gemfile
source 'https://ruby.taobao.org/'
gem 'rake'
gem 'sinatra'
gem 'sinatra-contrib'
gem 'sinatra-activerecord'
gem 'sqlite3'
[Ctrl-D]
安装gem 包,执行下面命令
bundle install
根据网络安装时长会有不同,完成后终端如下显示:
当终端 显示 Bundle complete!
字样时说明安装成功
创建数据库配置文件:
mkdir config && cd config
cat > database.yml
development:
adapter: sqlite3
database: blog_development
[Ctrl-D]
为了执行rake 任务,我们先要创建 Rakefile 文件,并添加如下代码
cat > Rakefile
require 'sinatra/activerecord'
require 'sinatra/activerecord/rake'
[Ctrl-D]
创建文章(posts)数据表,结构如下:
posts # 文章表
id: int # 文章唯一标识,主键
title: string #文章标题
body: text #文章内容
created_at: datetime #文章创建时间
updated_at: datetime #文章结束时间
生成数据迁移文件
bundle exec rake db:create_migration NAME=create_posts
项目根目录下会生成 db/migrate/yyyymmddhhmmss_create_posts.rb
用 vim 编辑器打开改文件,添加如下内容保存
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :body
t.timestamps
end
end
end
然后执行迁移:
bundle exec rake db:migrate
本项目是实现一个 Blog 的 API,我们需要实现以下接口:
GET /posts #列出所有文章
POST /posts #新建一篇文章
GET /posts/:id #获取某个指定的文章
PUT /posts/:id #更新某个指定文章(需提供该文章全部信息,不提供的则被更新为空)
PATCH /posts/:id #更新某个指定文章的信息(提供该文章部分信息,只更新提供的信息)
DELETE /posts/:id #删除某篇文章
本接口中会用到一些简单的 HTTP 状态码,
200 OK: 服务器成功返回用户请求的数据
201 CREATED : 用户新建数据成功
404 NOT FOUND: 用户发出的请求针对的是不存在的记录
422 Unprocesable entity: 发生一个验证错误
500 INTERNAL SERVER ERROR: 服务器发生错误
有兴趣的同学可以 到此 查看更多的状态码信息
项目根目录下执行
mkdir models
cat > models/post.rb
class Post < ActiveRecord::Base
end
[Ctrl-D]
首先创建项目主文件:
touch app.rb
至此我们的目录结构应该是这样:
├── app.rb
├── config
│ └── database.yml
├── db
│ ├── migrate
│ │ └── 20150225142442_create_posts.rb
│ └── schema.rb
├── Gemfile
├── Gemfile.lock
├── models
│ └── post.rb
└── Rakefile
Rakefile 引用 app.rb 文件, 编辑后的 Rakefile 文件如下:
require 'sinatra/activerecord'
require 'sinatra/activerecord/rake'
require './app.rb'
接口实现,粘贴以下代码到 app.rb 文件中:
#encoding: utf-8
require 'sinatra'
require 'sinatra/activerecord'
require 'sinatra/contrib'
require './models/post'
# 获取全部文章列表
get '/posts' do
posts = Post.all
json posts
end
# 创建文章
post '/posts' do
post = Post.new(title: params[:title], body: params[:body])
if post.save
status 201
json post
else
status 422
json message: 'save fail'
end
end
# 获取某篇文章
get '/posts/:id' do
post = Post.find_by_id(params[:id])
if post
json post
else
status 404
json message: 'not found'
end
end
# 修改某篇文章,修改全部内容
put '/posts/:id' do
post = Post.find_by_id(params[:id])
if post.update_attributes(title: params[:title], body: params[:body])
json post
else
status 422
json message: 'update fail'
end
end
# 修改某篇文章,修改部分内容
patch '/posts/:id' do
post = Post.find_by_id(params[:id])
unless post
status 404
return json message: 'not found'
end
post.title = params[:title] if params[:title]
post.body = params[:body] if params[:body]
if post.save
json post
else
status 422
json message: 'update fail'
end
end
# 删除某篇文章
delete '/posts/:id' do
post = Post.find_by_id(params[:id])
if post && post.delete
status 204
else
status 422
json message: 'delete fail'
end
end
完成以上步骤后,我们就可以运行项目了,终端执行:
bundle exec ruby app.rb
服务成功启动后,终端会如下显示了:
== Sinatra/1.4.5 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.3.1 codename Triple Espresso)
>> Maximum connections set to 1024
>> Listening on localhost:4567, CTRL+C to stop
然后打开firefox 浏览器,地址栏输入下面命令,便可看到项目正常运行:
http://localhost:4567/posts
我们用 curl 进行测试API,当然大家也可以在浏览器使用插件进行调试, 推荐 chrome 下的 POSTMAN
首先我们请求文章列表接口:
curl -i -X GET http://localhost:4567/posts
调用成功后会如下显示:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 2
X-Content-Type-Options: nosniff
Connection: keep-alive
Server: thin 1.3.1 codename Triple Espresso
[]%
我们看见除了返回 header 头 信息外,只返回了一个空数组,这是我们还没创建文章呢,
接下来我们创建一篇文章,调用创建文章接口,终端输入:
curl -X POST --data "title=My first post&body=This is post body." http://localhost:4567/posts
成功时 http 状态码 201,并且返回创建好的数据,如下所示:
HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 144
X-Content-Type-Options: nosniff
Connection: keep-alive
Server: thin 1.3.1 codename Triple Espresso
{"id":1,"title":"My first post","body":"This is post body.","created_at":"2015-02-26T13:31:08.287Z","updated_at":"2015-02-26T13:31:08.287Z"}%
然后我们重新调用文章列表接口:
curl -i -X GET http://localhost:4567/posts
调用成功后会如下显示:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 142
X-Content-Type-Options: nosniff
Connection: keep-alive
Server: thin 1.3.1 codename Triple Espresso
[{"id":1,"title":"My first post","body":"This is post body.","created_at":"2015-02-26T13:59:00.000Z","updated_at":"2015-02-26T13:59:00.000Z"}]%
返回了我们刚才创建的文章信息,我们现在只获取我们刚才创建的文章信息,终端输入:
curl -i -X GET http://localhost:4567/posts/1 # 1 为 文章id
请求成功后终端如下显示:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 140
X-Content-Type-Options: nosniff
Connection: keep-alive
Server: thin 1.3.1 codename Triple Espresso
{"id":1,"title":"My first post","body":"This is post body.","created_at":"2015-02-26T13:59:00.000Z","updated_at":"2015-02-26T13:59:00.000Z"}%
如果我们请求一个不存在的文章,API 会怎么返回呢,我们尝试请求 id 为 2 的文章, 终端输入:
curl -i -X GET http://localhost:4567/posts/2
请求成功后终端如下显示:
HTTP/1.1 404
Content-Type: application/json
Content-Length: 23
X-Content-Type-Options: nosniff
Connection: keep-alive
Server: thin 1.3.1 codename Triple Espresso
{"message":"not found"}%
我们发现返回了 404 的 http 状态码,‘not found’ 的 message,因为我们确实 id 为2 的文章不存在。
接下来我们要更新文章信息,更新我们提供了 PUT 和 PATCH 这两个接口,两者的区别见接口描述部分
我们先测试 PUT 更新请求,终端输入:
curl -i -X PUT --data "title=Update title content&body=Update body content." http://localhost:4567/posts/1
请求成功后终端如下显示:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 140
X-Content-Type-Options: nosniff
Connection: keep-alive
Server: thin 1.3.1 codename Triple Espresso
{"id":1,"title":"Update title content","body":"Update body content.","created_at":"2015-02-26T01:41:11.000Z","updated_at":"2015-02-26T13:33:11.058Z"}%
测试 PATCH 更新请求 ,终端输入:
curl -i -X PATCH --data "title=Only chage title" http://localhost:4567/posts/1
请求成功后终端如下显示:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 140
X-Content-Type-Options: nosniff
Connection: keep-alive
Server: thin 1.3.1 codename Triple Espresso
{"id":1,"title":"Only chage title","body":"Update body content.","created_at":"2015-02-26T01:41:11.000Z","updated_at":"2015-02-26T13:34:15.462Z"}%
测试删除某篇文章的请求,终端输入:
curl -i -X DELETE http://localhost:4567/posts/1
请求成功后终端如下显示:
HTTP/1.1 204 No Content
X-Content-Type-Options: nosniff
Connection: close
Server: thin 1.3.1 codename Triple Espresso
我们看到终端返回了 204 的 http 状态码,body 没有返回任何内容,我们重新访问下文章列表测试下看有没有删除成功,终端输入:
curl -i -X GET http://localhost:4567/posts
调用成功后会如下显示:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 2
X-Content-Type-Options: nosniff
Connection: keep-alive
Server: thin 1.3.1 codename Triple Espresso
[]%
看到 返回的 body 内容为空数组,说明我们删除成功!
到此我们的API接口全部测试完毕,本次的项目也就完成了,当然本项目只是一个简单的 Restful API 了。 当然一个设计优良的 Restful API 还有好多,有机会我们继续学习,希望这次的课程对大家有所帮助!