リソースにGET
を実装する場合、リソースが見つからない場合は404
で応答するのが理にかなっています。 POST
およびPUT
動詞の場合、少し複雑です。
その場合に404
で応答するには、なんらかの飛行前チェックを行う必要があります。最初にデータベースでSELECT
を実行し、一致する行があるかどうかを確認します。ない場合は、404
で応答します。ただし、同時ユーザーのため、次のUPDATE
sqlコマンドがすべての行に影響するという保証はありません。
とにかくリクエストが正常に処理される保証がない場合でも、REST APIでリソースの飛行前チェックを実装することは良い方法ですか?
結局のところ、あなたの質問はHTTP動詞の一般的な誤用にルーツがあると思います。
RDBMでPUT
をUPDATE
と同等にすることは一般的ですが、実際には「UPSERT」に似ています(つまり、存在しない場合は更新または挿入)。
したがって、別の回答に関するコメントでRobert Harveyが指摘したように、一見すると、更新されているリソースの種類(またはその親)を理解している場合に、見つからない404を返すことは意味がありません。次のURIを検討してください。
https://domain.com/{root}/{parent}/{child}
したがって、上記の場合、存在しないPUT
またはroot
に対してparent
を実行しようとした場合に404を返すことは理にかなっており、これらが修正されている場合は、まともなフレームワークが何をするか。 child
が存在しない場合は、作成できます。ただし、いくつかの注意点があります。
さておき、クライアントが上記のようにPUT
でリソースを作成することを許可するとします。しかし、複数のユーザーが同じルート/親パスから作成できると仮定しましょう。あるユーザーが別の(関連のない)ユーザーが作成したリソースにPUT
しようとした場合はどうなりますか?ここには2つの可能性があります。それらは、新しいリソースを作成しようとするなどのエラーを発生させたか、意図的に何か悪いことを試みています。どちらの場合も、それを許可したくないので、403
(禁止)エラーを返すことができます。ただし、そのパスが存在するかどうかについての情報を提供したくない場合は、404
を返すこともできます。しかし、パスが存在しないときに201
のみを返すと、再び情報が漏洩します。これは、このようなシナリオで404
を使用できることを示唆しています。それはまた、そのようなスキームが良い考えであるかどうかに疑問を投げかけます。ユーザー/クライアント識別子をパスの一部にすると、そもそもそのような偶発的な衝突を回避できます。この方法で対処することは意味がないとは言えませんが、クライアントのエラーシナリオを区別することが難しくなる可能性があります。
PUT
を使用して独自のリソースを作成できないようにするにはどうすればよいですか?問題ありません。あなたがする必要はありません。仕様にPUT
が作成または更新できると記載されているからといって、それらがPUT
で送信するURIの作成を強制されるわけではありません。パスに対してPUT
を使用してどのURIを作成できるかに関するルールを作成でき、1つの有効なルールが「なし」であることは明らかです。そのために機能する可能性のあるいくつかのエラーコードは 400
または422
です。上記のシナリオでは、403
または404
も意味があるかもしれないという主張をしました。個人的には、ここでは404
を避け、「不正な入力」応答を使用して、PUT
でのリソースの作成を許可していないことを明確にします。
POST
についても少し混乱があります。これはINSERT
の概念と多少整合していますが、多くの人が見逃していると思う側面が1つあります。POST
リクエストのパスが、作成されるリソースを参照していないということです。親リソースのパスです。それはあなたがPOST
に
https://domain.com/{root}/{parent}
あなたは新しいリソースを作成することを求めています
https://domain.com/{root}/{parent}/{child}
識別子child
はサーバーによって作成されます(クライアントにリクエストのコンテンツでそれを指定させることができないということは何もありません)。
したがって、質問のコンテキストでは、子が存在しないときに404
を返すことは意味がありません。サーバーに子を作成するように要求していて、子をURIの一部にしてはならないからです。ただし、親リソースが存在しない場合、URIが存在しないリソースの子を作成するように要求するため、その場合は404
を返すことは完全に理にかなっています。
結論として、404
とPUT
およびPOST
を一緒に使用しないことをお勧めします。ここでは子エンティティが不足していることを示しています。違う。 404
を使用して、親パスが存在しないか、クライアントからアクセスできないことを示すことは意味があります。
エキスパートの間で、データベースでAPIが探しているオブジェクトが見つからなかったことを示すために404を使用することに対して大きな合意があると言っても安心です。
主な問題は、ウェブサーバーまたはクライアントの設定が間違っている場合や、ドメインを誤って入力した場合にも404が表示されることです。
2つ目は、リソースが見つからない場合に例外をスローしたくないことがよくありますが、htmlライブラリは404コードの受信時に例外をスローすることがよくあります。
ただし、この目的で404を使用する場合、「存在しないリソースに対する更新の試み」に対しても、実装は十分に簡単です。
おそらくより最適な「SQLを実行し、影響を受ける行数をチェックする」こともありますが、結果はより解釈しやすくなります。
404の代替(この部分は最初の文の説明が必要な人のみを対象としています)
基本的には、コードの設計に依存します。呼び出したメソッドが成功したかどうかをユーザーに確認させないようにします。これにより、明確でシンプルなコードを記述できます。
そう。回復できない場合の例外ですが、より重要なのは、例外をスローしないように設計されたメソッドです。
したがって、存在しない可能性のあるオブジェクトをロードしようとしている場合は、「存在しない」が例外的な状況ではなく、呼び出しの有効な結果であることを認識するメソッドを使用してください。
オブジェクトを更新しようとしている場合は、オブジェクトを開いている間に削除された場合のシステムの処理方法を考えてください。おそらく、まだ存在していないオブジェクトを作成することも、一致が一致しないセットを更新することもできます。
コードでは、get関数はnullを返し、更新は影響を受けた行数を返す場合があります。これらは、エラーコードではなく「null」または0として表すことができます。