ある種類の操作としてページ付けに基づく顧客の要求を処理したり、別の種類の操作として演算子よりも大きいまたは小さい要求を要求したりできる残りのサービスのURLを設計するのは少し難しいです。例えば:
ページネーション:
GET /customers/0/100
これにより、ページ0で100人の顧客が取得されます。
より大きい/より小さい:
また、nより大きいIDを持つ顧客を取得するためのURL設計も必要です(たとえば、716としましょう)。どのようにURLに「より大きい」または「より小さい」を組み込みますか。 ">"と "<"はURLでは違法であることを覚えておく必要があります。このURLのデザインは奇妙に見えます:
GET /customers/greaterthan/716
GET /customers/lessthan/716
上記で指定されたページ分割パターンと競合する範囲を使用することはできず、どのような場合でも適切な解決策ではありません。例:
GET /customers/716/999999999999
GET /customers/0/716
私は明白な何かを見逃していると確信しています-誰かがより良い解決策を持っていますか?
Pagination、greaterthanおよびlessthan 、クエリパラメータのように聞こえます。これらのパラメータを使用してリソースをクエリしているからです。だからあなたは次のようなことをするべきです:
/ customers?page = 1、または
/ customers?page = 1&gt = 716、または
/ customers?page = 1&gt = 716&lt = 819
ページのサイズを制限することもできます。
/ customers?page = 1&gt = 716&lt = 819&maxpagesize = 1
ここで、gtは(xml-escapingと同じ)およびltは「より小さい」を表します。
複数のパラメーターがあり、各パラメーターにいくつかの条件を適用する必要がある場合は、JSONオブジェクトをパラメーターに渡すことをお勧めします。
id
とpage
の条件を実行するとします。
/customers?id={"lt": 100, "gt": 30}&page={"start": 1, "size": 10}
Id(s)less than100およびgreater than30のページ1およびページ番号10 。
したがって、他のパラメータに別の条件を適用したい場合は、次のようにして実行できます。
/customers?id={"lt": 100, "gt": 30}&children={"lt": 5, "gt": 2}&page={"start": 1, "size": 10}
このクエリは、Id(s)less than100およびgreater than30、子より小5およびより大2 ページ番号1、ページサイズ10。
RESTful APIの設計に関するこのドキュメントを読むことを強くお勧めします: http://blog.luisrei.com/articles/rest.html
RESTは、HTTPに固有であると見なすべきではないアーキテクチャスタイルです。 URIのパターンは、アーキテクチャーをRESTfulにするものではありません。
そうは言っても、おそらくこれらのクエリが文字列の最後にクエリパラメータとして来るようにURIを作成したいと思うでしょう。
/customers?min=0&max=76
@ジュリオ・ファーマン:
まあ、問題は複数のパラメーターを取得したときに始まります。 「18歳以上60歳未満の子供が2人以上いる顧客」のクエリ文字列を想像してみてください。
次のように、任意のクエリパラメータを定義できます。
/customers?min-age=19&max-age=59&min-children=3
私の例では、minとmaxは整数であり、包括的です。必要に応じて変更できます。 URIに含まれるものはすべて、リソース識別子の一部を意味します。私の個人的な見解では、?
の後の部分は、SQLクエリのWHERE
部分の句に相当します(ここには表示されていないORDER BY
およびLIMIT
)。
SELECT * FROM customers WHERE age>=19 AND age<=59 AND children>=3
編集:min-
およびmax-
接頭辞の代わりに、>
、<
(およびおそらく!
)をパラメーターの最後の文字として許可できます名前なので、min-age
の代わりにage>
というパラメーターがあり、クエリ文字列の値と組み合わせると、最終的にage>=19
のようになります:-)
明らかに、このトリックは、比較に等号が含まれている場合にのみ使用できます。
サーバーログを取得するとし、データが次のようになっているとします。
{
"protocol": "http",
"Host": "example.domain.com",
"path": "/apis/classified/server/logs",
"method": "GET",
"ip": "::ffff:127.0.0.1",
"time": 1483066346338,
"usingTime": 12,
"status": 200,
"headers": {
"user-agent": "Mozilla/5.0 Chrome"
}
}
そして、あなたはこのようにクエリしたいのですが、
protocol
は'http'
と等しい。Host
は'example.domain.com'
と等しい、または'example.domain.me'
と等しくない。path
は'/apis/classified/server/logs'
と等しい、または/*classified\/server*/
が好きです。method
は'DELETE'
と等しい、または'GET'
と等しくない、または['POST', 'PUT', 'DELETE']
内。ip
は'127.0.0.1'
と等しい、または'127.0.0.1'
と等しくない。usingTime
は3500
より大きいか、1500
以上で3500
以下です。status
は404
と等しいか、200
と等しくないか、400
以上で500未満です。headers.user-agent
は/*chrome*/i
が好きです。ここでは、ルートは次のようになります。
/apis/classified/server/logs?path=/apis/classfied
/apis/classified/server/logs?path.regex=*classfied*
/apis/classified/server/logs?method.ne=GET
/apis/classified/server/logs?method=POST&method=PATCH&method=PUT
/apis/classified/server/logs?usingTime.gte=1500&usingTime.lte=2500
/apis/classified/server/logs?headers.user-agent.regex=*chrome*
サーバーとしてexpress.jsを使用している場合、req.queryは次のように構成されます。
{"path": "/apis/classfied"}
{"path": {"regex": "*classfied*"}}
{"method": "DELETE"}
{"method": ["GET","POST","PUT"]}
{"usingTime": {"gte": "1500","lte": "2500"}}
(lte:より小さいか等しい){"status": {"ne": "200"}}}
(ne:等しくない){"path": {"regex": "*classfied*"}}
{"headers": {"user-agent": {"regex": "*chrome*", "flag": "i"}}}
そして、たくさんのif-elseを使用して、マングースクエリメソッド、またはSQL文字列を構成します。
ここに私がそれをしている方法があります。
たとえば、数値であるフィールドageがあるとします。
これはURLがどのようになるかです
等しい:/ filter/age = 5
より大きい:/ filter/age [gt] = 5
以上:/ filter/age [gte] = 5
未満:/ filter/age [lt] = 5
以下である:/ filter/age [lte] = 5
等しくない:/ filter/age [ne] = 5
次に、これらの引数をバックエンドに渡すと、キーを解析して、年齢に基づいて正しいフィルターに変換するスクリプトがあります[INSERT_OPERATOR_HERE]
私はそれを範囲として実装し、どちらかが開いている場合は、埋めないでください。
GET /customers/16-
GET /customers/-716
すべての顧客を要求する場合、すべてを追加するのではなく、空のままにしてください
GET /customers
または、必要な場合-番号/コードにサインインし、次のように使用します。
GET /customers/16/
GET /customers//716
GET /customers/16/716
スラッシュが数字の一部である場合は、スラッシュをエスケープできます。
この質問がC#に関連しているかどうかはわかりません。しかし、サーバー側でクエリにlinqを使用している場合は、別の提案があります。
GET /customers?filter=CustomerNo>=16 AND CustomerNo<=716
次に、サーバー側で:
using System.Linq.Dynamic;
var filteredCustomers = myCustomerTable.Where(filter);
これは、すべての中で最も柔軟なソリューションになるはずだと思います。
2017年1月19日に警告が追加されましたDynamic Linqにコードインジェクションエクスプロイトが存在することが気付きました。上記の例では、クライアントがサーバーでコード実行を開始できる可能性が開かれています。
一部のRESTベースの標準は、この問題への適切なアプローチを提供します。例: https://www.hl7.org/fhir/stu3/search.html
あなたの問題はそのように解決できます:GET /customers?id=ge500&id=lt1000
また、業界レベルの標準よりはるかに相互運用性の高い OData もあります。そして、それはこのスタイルを提案します:GET /customers?$filter=id ge 500 and id lt 1000