1

私はしばらくの間バックエンドに取り組んできましたが、最近フロントエンドに少し取り組み始めたので、エンドツーエンドの REST 実装に近づきました。

さらに言えば、REST の重要な原則は、クライアントがリソース (HATEOAS、JsonApi など) を普遍的に処理する方法を理解できるように、REST を発見可能で一貫性のあるものにすることです。この Google の記事を読んでいて、次の点があります。

API が単純かつ直接的に HTTP を使用する場合、3 つまたは 4 つのことを文書化するだけで済みます。(また、API の使用方法を学ぶために多くのドキュメントを読む必要がある場合は、HTTP を統一 API として使用していない可能性があります。) HTTP API の 4 つの要素は次のとおりです。

  1. 限られた数の既知の固定 URL。これらは、データベース内のテーブルの名前に似ています。オプションの追加クレジットとして、すべての固定 URL を 1 つの URL から検出できるようにします。

そして後で....

また、優れた HTTP/REST API を設計する方法を理解している人も不足しています。残念ながら、エンティティ指向の HTTP/REST スタイルを採用しようとする API の多くの例を目にしますが、モデルに一貫して従わないため、すべての利点を実現できていません。いくつかの一般的な間違いは次のとおりです。

  1. URL ではなく「ローカル識別子」を使用して、エンティティ間の参照をエンコードします。リソースの URL を形成するために、API がクライアントに URI テンプレート内の変数を代入することを要求する場合、HTTP の統一インターフェースの価値の重要な部分がすでに失われています。クエリをエンコードする URL を構築することは、統一されたインターフェイスとしての HTTP の概念と互換性のある URI テンプレートの唯一の一般的な用途です。

私は両方に同意しますが、これをどのように達成できるかわかりません

シナリオは次のとおりです。

  • API エンドポイント:
    • GET openapi.json / wadl / whatever-discovery-mechanism
      /articles/
      /articles/$id - only for Option 2 below
      ... (maybe for each entity operation in case of exhaustive discovery like openapi,
           but I'd want to keep it minimal for now)
      
    • GET /articles
      {
          data: [
              {
                  title: "Article 1",
                  links: {
                      self: "/articles/1",
                      ...
                  }
              }
          ]
      }
      
    • GET /articles/$id
    • DELETE /articles/$id
    • ...
  • フロントエンド URL:
    • GET /site/articles- 記事のリスト/テーブルを表示するページ
    • GET /site/articles/1- その記事を編集するためのフォームがあるページ

に移動する/site/articlesと、フロントエンドは API エンドポイントを呼び出すことを認識します/articles。これは、Google が言及している「限定された固定 URL」の 1 つです。article エンティティで返されたリンクを指定して、削除/更新も行われます。クライアント側のナビゲーションにより、フロントエンドは に「リダイレクト」することもでき/site/articles/1ます。

注意が必要な部分は、ユーザーが直接ナビゲートするときです。URL 自体を構築する (または何らかの方法でそれを変換する) ことなく/site/articles/1、どのようにしてページが呼び出しを認識できるでしょうか?/articles/$id

これらは私が見るオプションです:

  1. URL の構築 (これは基本的に、上記の「よくある間違いその 1」です)
    // /site/articles/1
    const apiUrl = '/articles/' + location.pathname.split('/')[3]
    // /articles/1
    
  2. 発見リンクからの URL の構築 (以前のオプションのバリエーション、依然としてかなり悪い IMO)
    // /site/articles/1
    const apiUrl = api.endpoints.articles + location.pathname.split('/')[3] // or replace or whatever
    // /articles/1
    
  3. フロントエンド URL でのエンティティ「自己」リンクのエンコード
    // /site/articles/L2FydGljbGVzLzE=
    const apiUrl = atob(location.pathname.split('/')[3])
    // /articles/1
    
    これに関する私の懸念は次のとおりです。
    • それはちょっと醜いです
    • 安全でない(xsrf /オープンリダイレクト...)
    • とにかくフロントエンドにURLを構築するように強制します(それだけが理解します)
  4. エンティティ識別子(私が考えるように、これは「自己」リンクです)をエンコードし、それを調べて/articles、返されたリンクを呼び出します
    // /site/articles/L2FydGljbGVzLzE=
    const entityId = atob(location.pathname.split('/')[3])
    const apiUrl = api.get(api.endpoints.articles)
        .first(article => article.links.self === entityId)
        .links.self
    // /articles/1
    
    • 3よりさらに醜い。
    • 十分に安全
    • 一見無意味に見える...
4

1 に答える 1