冪等な更新処理の API エンドポイントでは PUT を使うとよさそう

結論

  • star や like を付与するような、冪等性を持つアクションのための API エンドポイントでも POST はよく使われる
  • が、HTTP メソッドの意図を考慮すると、冪等な更新処理の API エンドポイントにアクセスするときの HTTP メソッドは、POST より PUT がよりよさそう

何をやったか

Twitter の like や GitHub の star を付与するようなアクションを、API エンドポイントとしてどのように表現すればよいのかというのを考えていました。

データを編集する操作なので POST, PUT, PATCH のいずれかで、さらに新規に like を表すリソースを作ると考えると、POST か PUT かなと思いました。この二つのどちらがよさそうか、既存 Web サービスの公開 API を見ながら調べてみました。

調査結果

POST

Twitter や Instagram の like は POST でした。

Twitter だと、リソース favorites/create を POST で作成するエンドポイントとなっています。

POST https://api.twitter.com/1.1/favorites/create.json

データを編集するための HTTP メソッドには POST はよく使われます。今回のような操作でも POST が使われている場合が多いようです。ただ、POST は送信したデータを指定 URI に従属させることを意図しています*1。たとえば

POST /v1/users

users の配下に新しくユーザのリソースを作成するようなパターンです。

なので、Twitter の API のように、直接リソース favorite/create を URI で指定するのは、POST の本来の意図とは若干異なってくるのかなと感じました。

PUT

GitHub API v3 の star は PUT でした。

リポジトリに対する star では、PUT で user が持つ starred/:owner/:repo というリソースを作成するエンドポイントとなっています。

PUT /user/starred/:owner/:repo

また、Gist に対する star では、PUT で star を作成するエンドポイントとなっています。

PUT /gists/:id/star

PUT を使う場合の要件として

  • 冪等性を担保すべき*2
  • URI でリソースを直接指定すべき*3

があります。

よって、次の理由

  • 一般に star や like は一度付与したら何度付与しても増えたりしない(冪等な処理である)
  • リソース (:repostar) を URI 内で直接に指定している

から、今回のようなエンドポイントでは POST よりも適しているのかなと思いました。

参考資料

Web API: The Good Parts

Web API: The Good Parts

次の Qiita 記事がかなり参考になりました。

qiita.com

*1:『Web API: The Good Parts』2.3.2 節参照

*2:http://stackoverflow.com/questions/630453/put-vs-post-in-rest

*3:『Web API: The Good Parts』2.3.3 節参照

2016 年ふりかえり

2016 年をふりかえらないと 2017 年が始まらないので、ハイライトでふりかえります。

上半期と下半期で在籍していた会社が違うので、そのくくりで分けてます。

上半期

個人活動

2015 年の秋ぐらいから触っていた Ruby で引き続き遊んでいました。

読書メーターにある自分の読書記録を自分でハンドリングしたくて、スクレイピング用 gem を作ったりしてました。

github.com

スクレイピングは結構つらいということがわかりました。なんやかんやあって結局ブクログに移行しました。

blog.kymmt.com

また、hatenablog gem や、それを使ったブログ編集用ツールに pull request をいただきました。ありがとうございます!!!

blog.kymmt.com

ほかには、ひとりで Ruby を書いてるだけではなく外に出ないといかんと思い、Yokohama.rb に参加し始めました。なぜ横浜かというと、この当時は横浜市内に住んでいたからです。当たり前なのですが Ruby にとても詳しい方が多く、感動した覚えがあります。また、ここで id:kurotaky さんに出会うのが、この後の伏線になります。

blog.kymmt.com

毎回参加記事を書いていたら、レシピブック読書会まとめマン的役割を若干確立しつつある感じになっています。

インフラ周りに慣れるべく、独自ドメインを取って設定したり、Let's Encrypt で証明書取得して nginx のサーバ設定を書き換えたりもしていました。

blog.kymmt.com

blog.kymmt.com

業務

MS Word と Eclipse を 7:3 ぐらいで使っていた記憶があります。

転職活動

5 月ぐらいに本格的に転職しようという気持ちになって、Yokohama.rb で kurotaky さんから聞いていた GMO ペパボのペパランチョンを思い出し、参加させてもらいました。

pepabo.com

これきっかけでペパボがとてもよさそうという感想に至り、6 月下旬にカラーミーショップのエンジニアとして応募したところ、8 月頭に内定しました。人生なにがあるかわからないですね。

前職は 9 月末で退職、10 月からはペパボ所属となりました。

下半期

ペパボカレッジ

入社後 1 か月かけて、福岡でペパボカレッジという研修を受講しました。詳しくは同期の qkake とともに社のブログにまとめたのでご参照ください。

tech.pepabo.com

業務

カラーミーショップというネットショップ作成サービスを開発しているグループで、カート画面を新しくするプロジェクトに加わって開発作業しています。Rails, PHP, Angular などを使っています。実力的にまだまだで、日々反省点も多いです。粛々とできることを増やしていきたいという気持ち。

個人活動

hatenablog gem の 0.4.0, 0.5.0 をリリースしました。8 月に引き続き、pull request もいただけたので、ありがたかったです。

blog.kymmt.com

blog.kymmt.com

ペパボ福岡支社でペパボカレッジ受講中の 10 月に Fukuoka.rb に参加させていただきました。

blog.kymmt.com

社のアドベントカレンダーに参加して、業務で得た知識を膨らませてアウトプットしてみました。

blog.kymmt.com

所感

アウトプットしたり外に出ていったのが功を奏した 1 年だったように思います。まさか興味本位で Ruby を触りはじめたころに「1 年後に Ruby を書く仕事をやっている」とは思っていなかったというのが本当のところです。

仕事を通じて常に学びがあるのでとてもよいのですが、それで社内に活動が閉じがちになってしまうのももったいないという気持ちがあります。今年はこれまでより (気楽に || 雑に) エントリなりコード片なりをアウトプットしたいと思います。

あとは pull request をもらってばかりなので、使っているライブラリなどに contribute できる余地があれば、できるだけしたいですね。

Yokohama.rb Monthly Meetup #75 に参加した

2016-12-10(土)の Yokohama.rb Monthly Meetup #75 に参加しました。

yokohamarb.doorkeeper.jp

次の流れでした。

  • 前半は Ruby レシピブック読書会
  • 後半は LT

今回は、参加者の @Nabetani さんがすでにメモを書いてくださっています。僕もメモしておきます。

qiita.com

レシピブック

今回はレシピ 240 から 243 まで読みました。おもにシステム寄りの Ruby プログラミングについてでした。

レシピ 240

システムのダイナミックリンクライブラリを Ruby から呼ぶためのレシピです。

システムライブラリを呼ぶためのライブラリとして dl が紹介されていますが、これは Ruby 2.0 以降では deprecated になっており、2.2 以降では削除されています。かわりに fiddle を使うとよさそうです。

また、macOS 環境では libc の代わりに libSystem.B.dylib を使う必要があります。

stackoverflow.com

たとえば、次のような感じで標準 C ライブラリの関数としておなじみの strlen が呼べます。

require 'fiddle/import'
module LibSystem
  extend Fiddle::Importer
  dlload 'libSystem.B.dylib'
  extern 'int strlen(char*)'
end
p LibSystem.strlen('abc')  #=> 3

レシピ 242

Ruby 付属のベンチマークライブラリである benchmark についてです。

@igrep さんからベンチマークにより便利な benchmark-ips を紹介してもらいました。与えたブロックの 1 秒あたりの繰り返し回数 (iteration per second: ips) を測定する gem です。評価値が大きいほど評価がよいので、直感的という話などをしていました。

github.com

軽く使いたいなら Benchmark#measure を使っておくと楽そうです。次のように書けます。

require 'benchmark'
puts Benchmark.measure { 'a' * 1_000_000 }

レシピ 243

シェルのコマンドを Ruby から起動するためのレシピです。

@Nabetani さんも書いておられますが、Kernel.#open の引数に | (パイプ)をつけて | df -k のように文字列を渡すと、IO.popen と同じ動きになることにびっくりしました。つまり、任意のコマンドを実行できるということです。この仕様については、次のドキュメントの最初にも

ファイル名 file が `|' で始まる時には続く文字列をコマンドとして起動し、 コマンドの標準入出力に対してパイプラインを生成します

と明記してあります。

さらに、これは macOS でも Windows でも実行できることを、前回に引き続き @igrep さんに Windows 環境で実験してもらいました!

File.open にはこのような仕様がないので、ファイル操作にはこちらを使っておいたほうが、万一のコマンドインジェクションは防げるので安心ということだそうです。

LT

LT 一本目は、先月と話がかなり被るのですが、僕が 10 月に受けていた GMO ペパボの第二新卒向け研修「ペパボカレッジ」について、社のテックブログに書いたエントリをもとにご紹介しました。

LT 二本目は、@ryonext さんから、先日の Re:Invent で発表された AWS のサービス群について紹介がありました。AWS は VPS から人工知能まで幅広いですね……。

懇親会

もう 12 月なので、忘年会と銘打たれていた気がします。来年もよろしくお願いします!!1


次回は 2017-01-14(土)です。次のリンクから申し込めます。ぜひぜひ。

yokohamarb.doorkeeper.jp