.../articles/

Rails APIモードのルーティングにおけるformatの扱い方

RailsでAPIモードを使う場合のルーティング、特にformatの設定について見直してみました。

Railsのルーティング

Railsのルーティングについては公式ドキュメントを参考にすることができ、その他にも「Rails ルーティング」のように検索すればたくさんの情報が見つかります。

APIモードを使う場合でも書き方は同じなので困ることはないのですが、あらためて format の扱いが気になったので調べてみました。

以降の内容は基本的にJSONを扱うAPIサーバーを実装する前提とし、動作確認は以下のバージョンで行いました。

  • ruby: 2.7.1
  • rails: 6.0.3.3

ルーティングでformatを設定する

ベースとして以下のようなルーティングを定義します。

Rails.application.routes.draw do
  namespace :v1 do
    resources :users
  end
end
# rails routesの出力結果(一部省略)
# v1_users GET    /v1/users(.:format)     v1/users#index
#          POST   /v1/users(.:format)     v1/users#create
# v1_user  GET    /v1/users/:id(.:format) v1/users#show
#          PATCH  /v1/users/:id(.:format) v1/users#update
#          PUT    /v1/users/:id(.:format) v1/users#update
#          DELETE /v1/users/:id(.:format) v1/users#destroy

また v1/users#show は以下のように定義されているとします。

    def show
      render json: User.find(params[:id])
    end

このとき3つのパターンでリクエストした結果を以下に示します。
(ヘッダ情報は一部省略しています)

# パターン1
$ curl -i localhost:3000/v1/users/1
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":1,"email":"email"}

# パターン2
$ curl -i localhost:3000/v1/users/1.json
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":1,"email":"email"}

# パターン3
$ curl -i localhost:3000/v1/users/1.html
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":1,"email":"email"}

パターン1とパターン2は違和感がないように見えますが、パターン3では .html とリクエストしているにも関わらずJSONのレスポンスを返しています。
アクションで render json: としているので、formatによらずコントローラーはJSONを返すという挙動になっています。

formatを指定(defaultスコープ)

ルーティングを namespace :v1, default: { format: 'json' } do と変更。

Rails.application.routes.draw do
  namespace :v1, default: { format: 'json' } do
    resources :users
  end
end

同様に3つのパターンでリクエストした結果は指定しない場合と変わりませんでした。
ただし head メソッドを使ってレスポンスを返す場合はヘッダが変わりました。

# パターン1
$ curl -i localhost:3000/v1/users/1
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":1,"email":"email"}

# パターン2
$ curl -i localhost:3000/v1/users/1.json
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":1,"email":"email"}

# パターン3
$ curl -i localhost:3000/v1/users/1.html
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":1,"email":"email"}

formatを指定

ルーティングを namespace :v1, format: 'json' do と変更。

Rails.application.routes.draw do
  namespace :v1, format: 'json' do
    resources :users
  end
end

同様に3つのパターンでリクエストした結果、パターン3ではRoutingErrorが発生し404となりました。

# パターン1
$ curl -i localhost:3000/v1/users/1
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":1,"email":"email"}

# パターン2
$ curl -i localhost:3000/v1/users/1.json
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":1,"email":"email"}

# パターン3
$ curl -i localhost:3000/v1/users/1.html
HTTP/1.1 404 Not Found

# RoutingErrorが発生

結局どれにすればいいのか?

参考にさせていただいた以下の記事にも書かれていますが、JSONを扱うAPIであれば本記事で最後に紹介した format: 'json' とするのが良いように思いました。

例のように .html やその他のフォーマットを意図せず(あるいは悪意を持って)リクエストされたときに404を返すほうが挙動として望ましい気がします。

例外的に他のフォーマットを許容したい場合は、個別のルーティングにもブロックにも format を設定することで上書きが可能です。
または /json|yaml/ のような正規表現も可能なようです。

.../articles/

Articles

記事

AWS AmplifyにmonorepoのNext.js(App Router)をデプロイする

AWS AmplifyにmonorepoのNext.js(App Router)をデプロイする

monorepo管理しているNext.jsをAmplifyにデプロイしようとした際にいくつか躓く内容があったのでまとめておきます。

リモートワーク・オンライン会議でも、スムーズに制作を進めるために大切なこと[資料編]

リモートワーク・オンライン会議でも、スムーズに制作を進めるために大切なこと[資料編]

コロナ禍の影響により、リモートワークの導入をおこなっている制作会社も多く、実際に弊社でも導入しています。

売れるECサイトデザインを作るために。参考にしたいおしゃれな事例の探し方。

売れるECサイトデザインを作るために。参考にしたいおしゃれな事例の探し方。

売れるECサイトのデザインは、「この形式」という決まりはありません。ECサイトで売り上げを上げるなら、しっかりとしたコンセプトと、コンセプトを決定するまでのリサーチが必要です。

制作会社の考える、業務効率化ツールのおすすめ。個人でも使いやすいサービスなど。

制作会社の考える、業務効率化ツールのおすすめ。個人でも使いやすいサービスなど。

新型コロナウイルス感染拡大の影響で、リモートワークが主流になり、弊社でも週のほとんどは各自宅で作業をしています。

Figmaでデザインのコミット履歴を残せるプラグイン【Thought Recorder】をリリースしました

Figmaでデザインのコミット履歴を残せるプラグイン【Thought Recorder】をリリースしました

Figmaを利用するWebデザイナーの助けになれると嬉しいです。使い方は本記事をご覧ください。

ECの構築方法、おすすめのECサービス。

ECの構築方法、おすすめのECサービス。

ファッションや家電、スーパーの買い物でさえもECサイトを利用することが当たり前になりました。加えて新型コロナウイルスの影響もあり、弊社にも「どんなプラットフォームを利用したら良いか」「どれくらいコストがかかるのか」などECに関するさまざまなご相談を頂きます。

FastAPIのスキーマクラスをOpenAPIから生成する方法

FastAPIのスキーマクラスをOpenAPIから生成する方法

PythonでAPIを構築する要件があり、フレームワークに比較的モダンなFastAPIを採用しました。FastAPIはバックエンドの開発を行えば自動でOepnApi定義を生成する機能が備わっていますが、今回はこれを使わず、事前に用意したOepnApi定義からFastAPIで利用するスキーマクラスを生成する方法を紹介します。

Laravel 日本一解りやすい全文検索のマイグレーション記載方法解説

Laravel 日本一解りやすい全文検索のマイグレーション記載方法解説

Laravel + MySQLで全文検索を実装する

とあるPythonのソースで sys.path.append としたく無かった話

とあるPythonのソースで sys.path.append としたく無かった話

とあるプロジェクトのとあるソースコードのレビューをしてた時、「ソースコードの参照がうまくいってなかったので修正しました」とレビュー依頼がきました。 ディレクトリ構造 ``` module L __init__.py L main.py L tests L __init__.py L test_main.py ``` ソースコード ``` python tests/test_main.py sys.path.append(os.path.abspath("..")) from main import fuga ``` 今まで案件でPythonに触れる機会も結構ありましたが、なんとなく使ってきた部分も多く、この書き方が良いのか悪いのか判別できなかったので、改めてPythonのモジュールのインポートに関して調べてみたのでブログにしました。普段PHPを書いている事が多くPythonに関して何も分からないので初心者向けの内容になっていると思います。

GiFT1号目新卒デザイナーの2021年振り返り

GiFT1号目新卒デザイナーの2021年振り返り

いつの間に、年末ですね。入社してもう、9ヶ月も立っていたようです。2021年の振り返りを記事にしました。

すべての記事

お問い合わせ