HTTPメソッド と RESTful(RESTful設計、RESTful Webサービス)と Rails 5 におけるアクション

今さらなまとめです。

HTTPメソッド と RESTful(RESTful設計、RESTful Webサービス)

HTTPメソッド(概要)

HTTPメソッド(と PATCHメソッド)の具体例

GET

  • リソースの取得
  • 読み込み(READ from CRUD)
  • べき等である
  • 安全である

POST

  • 子リソースの取得、リソースへのデータ追加、そのほかの処理
  • 作成(CREATE from CRUD)
  • べき等ではない
  • 安全ではない

PUT

  • リソースの更新、リソースの作成
  • 更新(UPDATE from CRUD)
  • べき等である
  • 安全ではない

DELETE

  • リソースの削除
  • 削除(DELETE from CRUD)
  • べき等である
  • 安全ではない

HEAD

  • リソースのヘッダ(メタデータ)の取得

OPTIONS

  • リソースがサポートしているメソッドの取得

TRACE

  • 自分宛にリクエストメッセージを返す試験(ループバック試験)

CONNECT

  • プロキシ動作のトンネル接続への変更

PATCH

  • リソースの更新
  • 更新(UPDATE from CRUD)
  • べき等ではない
  • 安全ではない
  • Rails の設計上、Rails 4 以降は更新を行うメソッドは PUT ではなく PATCH になった

主要5メソッドを表形式で見てみる

メソッド名 目的 CRUD べき等性 安全性
GET リソースの取得 READ べき等である 安全である
POST 子リソースの取得、リソースへのデータ追加、そのほかの処理 CREATE べき等ではない 安全ではない
PUT リソースの更新、リソースの作成 UPDATE べき等である 安全ではない
DELETE リソースの削除 DELETE べき等である 安全ではない
PATCH リソースの更新 UPDATE べき等ではない 安全ではない

POST メソッドで他のメソッドを代替する方法

特に GET と POST しか使えない Webブラウザ(の時代)での方法

1. X-HTTP-Method-Override を用いる方法

単純にリクエストヘッダに以下のように X-HTTP-Method-Override: PUT などと含めるだけ。

POST /foobar HTTP/1.1
Host: foo.bar
Content-Type: application/xml; charset=utf-8
X-HTTP-Method-Override: PUT

<body>hogehoge</body>

2. form に _method パラメータ を用いる方法

POST メソッドで送るフォームの中に、以下の HTML を忍び込ませる。具体的な挙動は送信されるリクエストヘッダを見ると分かる。しかしこの方法はリクエストヘッダの特性上、Content-Type: application/x-www-form-urlencoded がヘッダに含まれないと使えない。

<input type="hidden" id="_method" name="_method" value="PUT>

PATCHメソッドは「HTTPの仕様」ではない

HTTPの仕様以外で定義しているメソッドは、IANAのHypertext Transfer Protocol (HTTP) Method Registry[4]で管理されている。WebDavで使用するものや、 RFC 5789 のPATCHメソッドなどがある。

「安全ではない」とはどういうことか

「操作対象のリソースを変化させない」ということ。

「べき等性」と「安全性」はメソッドで保証されるものではない

「べき等性」と「安全性」は、その HTTPメソッド を用いたときにそういう設計をするべき、ということであり、その HTTPメソッド を使えば必ずそうなるというものではない。

リソースの作成に POST を使うか PUT を使うか

原則として POST を使う方向で設計をする。

Webブラウザ実装状況

  • (追記予定)

Ruby on Rails 5 のアクションにおける HTTPメソッド や RESTful

7つのアクション とその HTTPメソッド

  1. index
    • GET
  2. show
    • GET
  3. new
    • GET
  4. edit
    • GET
  5. create
    • POST
  6. update
    • PATCH (PUT)
  7. destroy
    • DELETE

7つのアクションのコントローラ例(Scaffold による)

class FriendsController < ApplicationController
  # GET /friends
  # GET /friends.json
  def index
    @friends = Friend.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @friends }
    end
  end

  # GET /friends/1
  # GET /friends/1.json
  def show
    @friend = Friend.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @friend }
    end
  end

  # GET /friends/new
  # GET /friends/new.json
  def new
    @friend = Friend.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @friend }
    end
  end

  # GET /friends/1/edit
  def edit
    @friend = Friend.find(params[:id])
  end

  # POST /friends
  # POST /friends.json
  def create
    @friend = Friend.new(params[:friend])

    respond_to do |format|
      if @friend.save
        format.html { redirect_to @friend, notice: 'Friend was successfully created.' }
        format.json { render json: @friend, status: :created, location: @friend }
      else
        format.html { render action: "new" }
        format.json { render json: @friend.errors, status: :unprocessable_entity }
      end
    end
  end

  # PUT /friends/1
  # PUT /friends/1.json
  def update
    @friend = Friend.find(params[:id])

    respond_to do |format|
      if @friend.update_attributes(params[:friend])
        format.html { redirect_to @friend, notice: 'Friend was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @friend.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /friends/1
  # DELETE /friends/1.json
  def destroy
    @friend = Friend.find(params[:id])
    @friend.destroy

    respond_to do |format|
      format.html { redirect_to friends_url }
      format.json { head :no_content }
    end
  end
end

参考(大感謝)

Powered by はてなブログ