ç°¡å㪠API ãµã¼ãã¼ã Ruby ã§ä½ããã¨æã£ã¦ Rails ãã大ãããããã Sinatra ããªã¼ã¨æã£ã¦ãã Grape ã¨ããã®ããã£ãã®ã§è©¦ãã¦ã¿ã¦ãã
èªåç¨ã®ã¡ã¢ãªã®ã§ãã¡ããã¨ç¥ããã人㯠https://github.com/ruby-grape/grape/blob/master/README.md ãèªã¿ã¾ãããã
åºæ¬
Gemfile ãä½ã£ã¦ã
source 'https://rubygems.org' gem 'grape'
bundle install
ãã¦ã
api.rb ã¨ããååã§ãã¡ã¤ã«ãä½ã£ã¦(ååã¯ãªãã§ããã)ã
require 'grape' class API < Grape::API get :hoge do 'GET' end post :hoge do 'POST' end put :hoge do 'PUT' end delete :hoge do 'DELETE' end end
config.ru ãä½ã£ã¦ã
require_relative 'api' run API
rackup --port 10080
ã³ãã³ãã§å®è¡ã1
ãããªæãã
~% curl -X GET -D- -d '' http://127.0.0.1:10080/hoge HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 3 Server: WEBrick/1.6.0 (Ruby/2.7.0/2019-12-25) Date: Mon, 24 Feb 2020 13:31:00 GMT Connection: Keep-Alive GET ~% curl -X POST -D- -d '' http://127.0.0.1:10080/hoge HTTP/1.1 201 Created Content-Type: text/plain Content-Length: 4 Server: WEBrick/1.6.0 (Ruby/2.7.0/2019-12-25) Date: Mon, 24 Feb 2020 13:31:06 GMT Connection: Keep-Alive POST ~% curl -X PUT -D- -d '' http://127.0.0.1:10080/hoge HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 3 Server: WEBrick/1.6.0 (Ruby/2.7.0/2019-12-25) Date: Mon, 24 Feb 2020 13:31:08 GMT Connection: Keep-Alive PUT ~% curl -X DELETE -D- -d '' http://127.0.0.1:10080/hoge HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 6 Server: WEBrick/1.6.0 (Ruby/2.7.0/2019-12-25) Date: Mon, 24 Feb 2020 13:31:12 GMT Connection: Keep-Alive DELETE
ã¡ã½ãããªã¼ãã¼ã©ã¤ã
_method=DELETE
ã¤ã㦠POST ãã¦ã DELETE ã¨è¦ãªãã¦ãããªããã©ã
~% curl -X POST -d '_method=DELETE' http://127.0.0.1:10080/hoge POST
config.ru 㧠Rack::MethodOverride
ã使ç¨ããããã«ãã¦ããã¨ã
require_relative 'api' use Rack::MethodOverride run API
DELETE ã¨è¦ãªãã¦ãããã
~% curl -X POST -d '_method=DELETE' http://127.0.0.1:10080/hoge DELETE
ãã¼ã ã¹ãã¼ã¹
namespace
ã使ã£ã¦ãããªé¢¨ã«ãæ¸ããã
require 'grape' class API < Grape::API namespace :hoge do get do 'GET' end post do 'POST' end put do 'PUT' end delete do 'DELETE' end end end
ãªã¯ã¨ã¹ã
ãªã¯ã¨ã¹ãã®ããã㯠headers
ããã©ã¡ã¼ã¿ã¯ params
㧠Hash ã¨ãã¦ã¢ã¯ã»ã¹ã§ããã
class API < Grape::API get :hoge do headers.inspect + "\n" + params.inspect + "\n" end end
~% curl 'http://127.0.0.1:10080/hoge?a=123&b=xyz' {"Host"=>"127.0.0.1:10080", "User-Agent"=>"curl/7.65.3", "Accept"=>"*/*", "Version"=>"HTTP/1.1"} {"a"=>"123", "b"=>"xyz"}
ãã©ã¡ã¼ã¿ã¯ params
ã§å®ç¾©ãã¦ããã¨ããªãã¼ã·ã§ã³ï¼å¤æãã¦ãããã
ãã¹ä¸ã« :èå¥å
ã§å«ãããã¨ãã§ããã
class API < Grape::API params do requires :id, type: Integer requires :s, type: String optional :p, type: Date end get 'hoge/:id' do params end end
~% curl 'http://127.0.0.1:10080/hoge/' 404 Not Found ~% curl 'http://127.0.0.1:10080/hoge/abc' id is invalid, s is missing ~% curl 'http://127.0.0.1:10080/hoge/123' s is missing ~% curl 'http://127.0.0.1:10080/hoge/123?s=hoge' {"s"=>"hoge", "id"=>123} ~% curl 'http://127.0.0.1:10080/hoge/123?s=hoge&p=abc' p is invalid ~% curl 'http://127.0.0.1:10080/hoge/123?s=hoge&p=2020-02-25' {"s"=>"hoge", "p"=>Tue, 25 Feb 2020, "id"=>123}
æ£è¦è¡¨ç¾ã®æå®ãå¯ã
class API < Grape::API params do optional :ipv4, type: String, regexp: /\A\d+\.\d+\.\d+\.\d+\z/ end get 'hoge' do params[:ipv4] end end
ãã ãã.
ãå«ããã©ã¡ã¼ã¿ã¯ãã¹ä¸ã«ã¯æå®ã§ããªãã
class API < Grape::API params do requires :ipv4, type: String, regexp: /\A\d+\.\d+\.\d+\.\d+\z/ end get 'hoge/:ipv4' do params[:ipv4] end end
~% curl 'http://127.0.0.1:10080/hoge/1.2.3.4' 404 Not Found
ãã¹ä¸ã®ãã©ã¡ã¼ã¿ã®æ£è¦è¡¨ç¾ãæå®ããã°OKããã®å ´å㯠\A
ã \z
ã¯ä¸è¦ãããã
class API < Grape::API get 'hoge/:ipv4', requirements: {ipv4: /\d+\.\d+\.\d+\.\d+/ } do params[:ipv4] end end
~% curl 'http://127.0.0.1:10080/hoge/1.2.3.4' 1.2.3.4
ã¬ã¹ãã³ã¹
ãããã¯ãè©ä¾¡ããçµæã®ãªãã¸ã§ã¯ããã¬ã¹ãã³ã¹ãã¼ã¿ã«ãªãã
class API < Grape::API get :hoge do {abc: 123, xyz: 789} end end
~% curl -D- http://127.0.0.1:10080/hoge HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 25 Server: WEBrick/1.6.0 (Ruby/2.7.0/2019-12-25) Date: Mon, 24 Feb 2020 14:04:34 GMT Connection: Keep-Alive {:abc=>123, :xyz=>"hoge"}
ãªã¯ã¨ã¹ãã®æ¡å¼µå㧠Content-Type ãæå®ãããã¨ã§ããã£ã½ãèªåå¤æãã¦ãããã
~% curl -D- http://127.0.0.1:10080/hoge.txt HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 25 Server: WEBrick/1.6.0 (Ruby/2.7.0/2019-12-25) Date: Mon, 24 Feb 2020 14:04:36 GMT Connection: Keep-Alive {:abc=>123, :xyz=>"hoge"} ~% curl -D- http://127.0.0.1:10080/hoge.json HTTP/1.1 200 OK Content-Type: application/json Content-Length: 24 Server: WEBrick/1.6.0 (Ruby/2.7.0/2019-12-25) Date: Mon, 24 Feb 2020 14:04:38 GMT Connection: Keep-Alive {"abc":123,"xyz":"hoge"} ~% curl -D- http://127.0.0.1:10080/hoge.xml HTTP/1.1 200 OK Content-Type: application/xml Content-Length: 104 Server: WEBrick/1.6.0 (Ruby/2.7.0/2019-12-25) Date: Mon, 24 Feb 2020 14:04:40 GMT Connection: Keep-Alive <?xml version="1.0" encoding="UTF-8"?> <hash> <abc type="integer">123</abc> <xyz>hoge</xyz> </hash>
ã¬ã¹ãã³ã¹ã¹ãã¼ã¿ã¹ã¯ status
ã§æå®ããã
class API < Grape::API get :hoge do status 400 'ãªããããããã' end end
~% curl -D- http://127.0.0.1:10080/hoge HTTP/1.1 400 Bad Request Content-Type: text/plain Content-Length: 24 Server: WEBrick/1.6.0 (Ruby/2.7.0/2019-12-25) Date: Mon, 24 Feb 2020 14:14:50 GMT Connection: Keep-Alive ãªããããããã
ãã¼ã¸ã§ãã³ã°
ãã¼ã¸ã§ãã³ã°ãã§ããã®ãç¹å¾´ãããã
require 'grape' class API1 < Grape::API version 'v1' get :hoge do 'Version 1' end end
require 'grape' class API2 < Grape::API version 'v2' get :hoge do 'Version 2' end end
require_relative 'api1' require_relative 'api2' use Rack::MethodOverride run Rack::Cascade.new [API1, API2]
ãããªæãã«ãã¨ãã¨ãURLä¸ã®ãã¹ã§ãã¼ã¸ã§ã³ãæå®ã§ããããã«ãªãã
~% curl http://127.0.0.1:10080/v1/hoge Version 1 ~% curl http://127.0.0.1:10080/v2/hoge Version 2
ããã©ã«ãã¯ãã¹ã ãã©ãã¯ã¨ãªãã©ã¡ã¼ã¿ã§æå®ããããã«ãããã¨ãã§ããã¿ããã
ããã¥ã¡ã³ã
grape-swagger ã¨ããã®ã使ã㨠Swagger/OpenAPI çã«ãã¾ããã¨ãã£ã¦ããããããããã®ãã¡èª¿ã¹ãã
ãªãã¨ãªããããããªã®ã§ã¡ãã£ã¨ä½¿ã£ã¦ã¿ããããªã¼ã£ã¨ã
-
--port 10080
ãã¤ãã¦ããã®ã¯ãããã©ã«ãã® 9292 ã 㨠Emacs ã® edit server ã¨è¢«ãããã↩