WebAPIでX-HTTP-Method-OverrideのDelegatingHandlerを実装する方法

REST Web APIをパブリックドメインにデプロイすると、HTTP動詞のサポートに関連する問題が発生する場合があります。この点に関する2つの課題は、古いWebブラウザーでのHTTP動詞のサポートの制限(つまり、HTTPGETとHTTPPOSTのみをサポート)と、HTTPGETでもHTTPPOSTでもないトラフィックをブロックする攻撃的なファイアウォールです。このような場合、アプリケーションはPUTまたはDELETEをどのようにサポートしますか?ここで、X-HTTP-Method-OverrideHTTPヘッダーが役に立ちます。

X-HTTP-Method-Override HTTPヘッダーは、ハッキングと多少似ています。JavaScriptまたはXMLHttpRequestHTTPPOST呼び出しを使用してWebブラウザーからオブジェクトを介してWebAPIを呼び出すときに、PUTまたはDELETEのいずれかの値でヘッダーを追加できます。次に、委任ハンドラーに、呼び出されるHTTPメソッドをインターセプトさせ、適切なアクションを実行させることができます。

この記事では、要求/応答パイプラインの前で委任ハンドラーを使用して、アプリケーションに有効なメッセージを送信するように要求を変更する方法、またはクライアントに有効な応答を返送するように応答を変更する方法について説明します。

HTTP動詞と委任ハンドラー

クライアント、Webブラウザー、またはWebアプリケーションの前面にあるファイアウォールによって課せられた制限のために、HTTP動詞GETおよびPOSTのみの使用に制限されている場合は、PUTおよびDELETEをサポートするための回避策を実装する必要があります。この回避策には、通常、HTTPPOST呼び出し内で使用する動詞を指定するリクエストにX-HTTP-Method-OverrideHTTPヘッダーを追加することが含まれます。さらに、ヘッダーをチェックし、ヘッダーが存在する場合は、呼び出したいHTTPメソッドを呼び出す委任ハンドラーがアプリケーションに必要です。

実装に飛び込む前に、委任ハンドラーとは何か、そしてなぜここでそれを使用するのかを簡単に見てみましょう。委任ハンドラーおよびその他のメッセージハンドラーは、要求処理パイプラインの早い段階で実行されます。これらは、HTTP要求を受け入れ、HTTP応答を返すクラスです。委任ハンドラーはHttpModules、ASP.Netの場合と同様です。ただし、とは異なりHttpModules、委任ハンドラーはチェーン化できます。1つの委任ハンドラーが別の委任ハンドラーを参照できます。ハンドラーの委任について詳しくは、前回の記事「WebAPIでメッセージハンドラーを操作する方法」を参照してください。

WebAPIコントローラーを作成する

次のようなWebAPIコントローラーがあるとします。

パブリッククラスAuthorsController:ApiController

    {{

        // GET:api / authors

        public IEnumerable Get()

        {{

            新しい文字列を返す[] {“ Joydip”、“ Kanjilal”};

        }

        // GET:api / authors / 1

        パブリック文字列Get(int id)

        {{

            「JoydipKanjilal」を返します。

        }

        // POST api / author

        public void Post([FromBody] Author value){}

        // PUT api / author / 1

        public void Put(int id、[FromBody] Author value){}

        // api / author / 1を削除します

        public void Delete(int id){}

    }

X-HTTP-Method-OverrideのDelegatingHandlerを作成します

それでは、X-HTTP-Method-Overrideハンドラーを実装しましょう。これはメッセージハンドラであるため、通常どおりDelegatingHandlerクラスを拡張する必要があります。

パブリッククラスCustomMessageHandler:DelegatingHandler

    {{

        読み取り専用string [] httpMethodsList = {“ DELETE”、“ HEAD”、“ PUT”};

        const string httpMethodOverrideheader;

        保護されたオーバーライドタスクSendAsync(HttpRequestMessageリクエスト、CancellationToken cancelToken)

        {{

            if(request.Method == HttpMethod.Post && request.Headers.Contains(httpMethodOverrideheader))

            {{               

                var httpMethod = request.Headers.GetValues(httpMethodOverrideheader).FirstOrDefault();

                if(httpMethodsList.Contains(httpMethod、StringComparer.InvariantCultureIgnoreCase))

                {{                  

                    request.Method = new HttpMethod(httpMethod);

                }

            }

            base.SendAsync(request、cancelToken);を返します。

        }

    }

コードは非常に自明です。X-HTTP-Method-Overrideヘッダーを持つHTTPPOSTをチェックします。ヘッダーがメソッドのリストにある場合、リクエストメソッドが変更されます。

DelegatingHandlerを登録します

次のステップは、ハンドラーを登録することです。これを行うには、以下のコードスニペットに示すように、この新しいハンドラーをWebApiConfigクラスのMessageHandlersコレクションに追加します。

public static void Register(HttpConfiguration config)

{{

    config.MessageHandlers.Add(new CustomMessageHandler());

     // WebAPIルート

    config.MapHttpAttributeRoutes();

     config.Routes.MapHttpRoute(

        名前:「DefaultApi」、

        routeTemplate:「api / {controller} / {id}」、

        デフォルト:new {id = RouteParameter.Optional}

    );

}

または、Application_Start次に示すように、Global.asax.csファイルのイベントハンドラーを使用して委任ハンドラーを登録することもできます。

protected void Application_Start(object sender、EventArgs e)

        {{

            RegisterRoutes(RouteTable.Routes);

            GlobalConfiguration.Configuration.MessageHandlers.Add(new CustomMessageHandler());

        }

サーバー側で行う必要があるのはこれだけです。クライアント側、つまりWebブラウザーから、以下のコードスニペットに示すようにオーバーライドヘッダーを必ず追加する必要があります。

$ .ajax({

  url:「// localhost:9820 / api / Authors / 1」、

  タイプ:「POST」、

  データ:JSON.stringify(authorData)、

  ヘッダー:{

      「content-Type」:「application / json」、

      「x-HTTP-Method-Override」:「PUT」}、

})

前のコードスニペットでわかるように、実行する必要があるのは、要求ヘッダーで呼び出すHTTPメソッドを指定するX-HTTP-Method-Override : DELETEか(または)X-HTTP-Method-Override : PUT、リソースに対してPOST呼び出しを行うことだけです。