パラメータとクエリ文字列の使用に関するREST API設計の最適プラクティス

2019/05/27 09:00

APIについては、どこにパラメータを入力するか?REST APIでのパラメータとクエリ文字列の使用に関する最適プラクティス

API設計の際のゴールは、ユーザーに提供されるサービスに対し、ある程度のパワーを込めることです。HTTP動詞とリソースURLが基本的な相互作用を及ぼす一方、しばしば追加機能の提供が重要な場合があります。さもないと、システムは作業するには扱い難くなってしまいます。

その一例がページネーションです。データベースに何百万もあれば、ひとつひとつを一回の応答で全てクライアントに送信することなど出来ません。

これを成し遂げる方法にパラメータ化があります。

パラメータ化とは?

一般的に言えば、パラメータ化とはリクエストに対してのある種の設定です。

プログラミング言語では、関数から戻り値を求めることが出来ますが、その関数がパラメータを受け入れない場合、この戻り値に直接作用させることは出来ません。

以下のRoy Fieldingからの引用にも示すように、API、特にREST APIのような処理状態を把握しないAPIについても同様のことが起こります。

REST相互作用の全ては処理状態が把握されません。つまり、各要求には、それに先行し得る要求とは別に、コネクターの要求理解に必要な全情報が含まれています。

HTTPには要求にパラメータを追加する多くの方法があります。クエリ文字列、 POST、PUT、PATCHリクエスト、およびそのヘッダなどがそれに該当します。それぞれに独自のユースケースとルールがあります。

故にパラメータをどこに入力するかを決める前に考える必要があり、そしていかに適切な場所に入力するかをチェックしなければなりません。

制約を極力少なくして全データを取り込む最も簡単な方法は、全データを本体に取り入れることです。 弊社自身もそのように機能した多くのAPIを見て来ました。 全終了点でPOSTを使用すれば全パラメータは本体に入ります。特に何十年にも渡り成長し、ますます多くのパラメータを蓄積したレガシーAPIに対しては、このような処置を施さなければなりません。大量のデータはクエリ文字列に収まり切れません。

たいていの場合はこうしたケースですが、API設計におけるエッジケースに思いを巡らしてみたいと思います。前もって正しい質問をすれば、早めにそのような結果に至らず防ぐことも出来ます。

どのようなパラメータを追加すべきか?

最初に自身に問う質問は、どのようなパラメータを追加すべきか?だ。

恐らくそれはHTTP仕様で既に標準化されているヘッダフィールドのパラメータです。

多くの標準化された分野があり、時には他所でこの情報を加えることにより、わざわざ一からやり直す事ともなります。難しく捉えようと言うのではありません。例えば、GraphQLは、RESTの観点から見ればクレージーにも思えましたが、それでも機能します。しかし、既存のものを使用すればより簡単に済む場合もあります。

例えば、レスポンスが持っているフォーマットやメディアタイプの定義を可能にするAcceptヘッダがあります。これを使用してJSONやXMLが必要であることをAPIに伝えることが出来ます。これを使用すれば、バージョンやAPIのレスポンスを確認する事も可能です。

キャッシュバスターである文字列を使用する代わりに、APIがキャッシュ無しの動的レスポンスを送ることを防ぐ為に使用するキャッシュ制御ヘッダもあります(?cb = <RANDOM_STRING>)。

APIの承認の詳細によっては承認されたデータと承認されていないデータを要求するとサーバーからの応答が異なる可能性があるため、承認もパラメータと見なされる可能性もあります。この目的が故に、HTTPは承認ヘッダを定義します。

全デフォルトヘッダフィールドをチェックした後の次のステップは、パラメータ用のカスタムヘッダフィールドを作成するか、それをURLのクエリ文字列に入力するかの判断となります。

クエリ文字列はいつ使用すべきか?

追加したいパラメータがデフォルトのヘッダフィールドに属さず、機密でもないことが分かっていれば、クエリ文字列が適切な場所に入力されているかどうかが確認出来ます。

名前が示すように、歴史的に言えばクエリ文字列の使用はデータを問い質すことでした。サーバーにいくつかのキーワードを送信するために使用される<isindex> HTML要素があり、サーバーはそのキーワードに何らかの形で一致するページリストで応答します。

後にクエリ文字列は、ウェブフォームがGET要求を通じてデータをサーバーに送信するために再利用されるようになりました。

故にクエリ文字列使用に適した主たるユースケースとは、フィルタリングと、検索とページネーションという2つの特別なフィルタリングとなります。既にこの記事で取り上げられているので、ここで更なる詳述は控えます。

しかしウェブフォーム目的への再利用が示すように、様々な種類のパラメータにも使用可能です。RESTful APIは、本体でPOSTまたはPUTリクエストを使用してフォームデータをサーバーに送信します。因ってこれはユースケースでは無いものの、それでも他のパラメータの介在が可能です。

一例はネスト化した表現へのパラメータです。 デフォルトにより記事を平易な表現で返し、?withCommentsのクエリ文字列が終点に追加された場合、その記事のコメントはインラインで返される事となるので、1つの要求だけが必要となります。

そのようなパラメータはカスタムヘッダに入るか、或いはクエリ文字列は殆どの場合、開発者の経験に依存する事となります。

HTTPの仕様では、ヘッダフィールドは関数パラメータに似ているとも言われ、実際に使用したいパラメータとして考えられてはいますが、URLにクエリ文字列を追加することはすぐに可能であり、その為に顧客ヘッダを作成する事よりはもっと解り易いです。

こうしたフィールドは、プログラミング言語のメソッド呼び出しでのパラメータとは変形として同等の意味を成し、要求修飾子として機能します。

全終点で変わらないパラメータは、ヘッダに適合します。例えば、認証トークンはあらゆるリクエストに応じて送信されます。

非常に動的なパラメータ、特に少数または1つの終点に対してのみ有効なパラメータは、クエリ文字列に含める必要があります。例えば、フィルタパラメータは終点ごとに異なります。

ボーナス:配列とマップパラメータ

クエリ文字列内の配列パラメータについてはどうするか?これはかなり頻繁に生じる問題の1つでした。

例えば、検索したい複数の名前がある場合など。

解決策の1つは角括弧を利用することです。

/authors?name[]=kay&name[]=xing

しかしHTTP仕様はこう述べています。 

インターネットプロトコルのリテラルアドレス、バージョン6 [RFC3513]以降で識別されるホストは、IPリテラルを角括弧( "["と "]")で囲むことによって区別される。これが、URI構文で角括弧文字使用が許される唯一の場所だ。

HTTPサーバーと多くのクライアントはこの事実を気にはしていません。しかし、覚えておくべきでしょう。

お勧めの他の解決策には、単純に1つのパラメータ名を複数回使用することがあります。

/authors?name = kay&name = xing

これは有効な解決策ではあるが、開発者の経験則を衰えさせる事につながる可能性もあります。多くの場合、クライアントはURLに追加される前に単純な文字列変換を経たマップのようなデータ構造を使用するだけですが、これは以下に続く値をオーバーライドしてしまう可能性もあります。要求を送る前により複雑な変換が必要となります。

もう1つの方法は値を - 文字で区切ることです。URL内コード化されていなくても構いません。

/authors?name=kay,xing

地図のようなデータ構造に- 文字をコード化せずに使用する事も出来ます。

/articles?age.gt=21&age.lt=40

クエリ文字列全体をURLエンコードすることも可能であり、必要とする文字やフォーマットに使用する事も出来ます。こうする事で開発者の経験則をかなり減少させてしまう可能性もあることは覚えておいて戴きたい事です。

クエリ文字を使用しない時とは?

クエリ文字はURLの一部であり、クライアントとAPI間にいる全ての人がURLを読み取れます。因って、パスワードなどの機密データはクエリ文字に含めるべきではありません。

また、URL設計とその長さを真剣に考えない限り開発者の経験則は大きく損なわれます。確かに殆どのHTTPクライアントはURLに5桁の長さの文字を入れる事も出来ますが、斯様な種の文字列をデバッグすることはあまり好ましとは言えません。

如何なるものもリソースとして定義出来ます。故に時にはPOST終点を利用し、パラメータを多用する事も理には適ってはいます。こうして本体内の全データはAPIに送られます。

それはどうしてもデバッグ出来ないような長いクエリ文字列で多くのパラメータを送るリソースにGETリクエストを送信する代わりに、例えば検索リソースなどのリソースの作成として設計する事も出来ます。APIが要求を満たすための要件に応じて、これを使用し計算結果をキャッシュすることも可能です。

/search 終点に新たなリクエストをポストします。こうして本体の検索設定/パラメータを保持し、後に検索結果取得に使用可能な検索IDを取得します。

結論

全最適プラクティスと同様、APIデザイナーまたは設計者としての我々の仕事は、「ベストソリューション」としての1つのアプローチをフォローするのでは無く、いかに我々のAPIが使用されているかを知ることです。

容易に成就するユースケースが最も頻繁に使用されるべきであり、悪しき事になる事が本当に困難となるべきです。

故にAPIの使用パターンを当初から分析する事が常に重要です。データの入手が早ければ早いほど、設計が混乱した場合、速やかな変更の実行が可能となります。Moesifの分析サービスはそれを支援します。

Moesifは、2000を超える組織体で顧客の利用パターン計測に使用されている最先端のPI分析サービスです。

直進すれば把握するにも実行するにも簡単ではありますが、我々はそこから得られるものを見なければなりません。

ネスト化されたリソースによりURLはより読みやすくなりますが、それが過ぎると逆に長すぎて読みづらくなります。パラメータも同様です。 膨大なクエリ文字列に至る1つの終了点を自ら作成していると気づいたならば、そこから別のリソースを抽出し、パラメータは本体内に送った方が良いでしょう。

この記事は、著者の許可を得て翻訳しています。なお、原文はこちらです。

新着ピック  






















新着ニュース

LINE「OpenChat」、トークルーム検索機能の再開を延期 「検索精度を上げるため」

バーチャルタレントがスナックのママに--“場所を選ばない接客”の働き方

リザーブドインスタンス(RI)を間違わずに購入したい! それなら AWS CLI を活用してみよう。 -オペ部だより- | DevelopersIO

ローソン、「深夜に店員ゼロ」を実験へ QRコードで入店、セルフレジで決済 遠隔監視で万引き防止

銘菓「ニコンようかん」、ネット販売終了 「裏の主力製品がなくなる」と惜しむ声

WindowsでAWS CDK(C#)の開発環境を整えてみた | DevelopersIO

TC Tokyo超早割チケットは8月末まで!トヨタの自動運転開発子会社TRI-ADのCEOが登壇決定 | TechCrunch Japan

たこ焼きロボからマイクロモビリティまで竹芝埠頭にロボ集結 | TechCrunch Japan

家事代行のベアーズ、マンションにスタッフ常駐の新サービス「MAUCHI」開始

対象店舗でビットコイン決済するとTポイントを付与--bitFlyerとTポイントが業務提携

野村不動産アーバンネット、不動産売買支援システム「Kimar」を導入

Application Load BalancerのリスナールールによるIP制限 | DevelopersIO

Application Load Balancerのリ...

DevelopersIO / 3時間前


最短2日で物件売却のすむたすが直販を開始--「すむたす直販」が担う中古流通比率の引き上げ

ローソン、深夜時間帯を“無人化”する実証実験--横浜で半年ほど実施

Amazon VPC設計時に気をつけたい基本の5のこと | DevelopersIO

ソニー、学校向けプログラミング学習キット「KOOVベーシックキット」を9月に発売

「Zaif」元運営のテックビューロ、仮想通貨交換業を廃業へ

なぜβ版でスタート? 独自プランは? IIJに聞く「eSIM」戦略

Github ActionsのワークフローへCircleCIのワークフロー流用を試してみた | DevelopersIO

ブランドリセール「RECLO」のアクティブソナー、中国企業などから約36億円を調達

もっと見る
ログイン
会員登録
Register
記事をPICKする

会員登録すると、もっと便利に利用できます。