クロスドメイン制約 を 回避 する クライアント & サーバー 実装 を XmlHttpRequest level2 の プリフライト を利用して実現します。
クロスドメイン通信 を実現するには "サーバー側" と "クライアント側" の2カ所に対して手を入れる必要があるかどうか考えます。 ここでは、"クライアント側" と "サーバー側" 両方に手を加えて クロスドメイン通信 を実現する方法を載せます。 具体的には、XmlHttpRequest level2 の プリフライト を利用して クロスドメイン通信 を行えるようにします。
想定する クロスドメイン通信 環境

サーバーA から HTML & JavaScript を受信し、足りない リソース を サーバーB から取得する環境を想定します。
GET はそのまま通信されますが、POST, PUT, DELETE は プリフライト (OPTIONS) が自動的に行われます。 つまり、自前で OPTIONS を実行しなくても勝手に実行されるので、自動的に行われる プリフライト通信 に正しい応答処理が行われるようにすれば良いことになります。
サーバー 実装
サーバー側では、"プリフライトの応答" と "サービスの実態" の 2つ を記述します。 サーバー側で確認、実装が必要なのでは以下に示す2ファイル(WebApiConfig.cs、CatalogController.cs)です。
以下にサーバー側で必要な実装の内容、手順を載せます。
- OPTIONS へのマッピング を確認。
/App_Start/WebApiConfig.cspublic static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); }
- プリフライト 用 の コード を 実装。
/Controllers/CatalogController.cs// OPTIONS api/catalog public void Options() { var response = HttpContext.Current.Response; response.AppendHeader("Access-Control-Allow-Origin", "http://www.example.com"); response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); response.AppendHeader("Access-Control-Allow-Headers", "X-PINGOTHER, application/json"); response.AppendHeader("Access-Control-Max-Age", "1728000"); }
- GET, POST 等 実態 コード を 実装。
(※ここでは POST を サンプルコード として掲載します。その他は、サーバー実装(全体) サンプルコードをご参照ください。)
/Controllers/CatalogController.cs// POST api/catalog public string Post([FromBody]string value) { var response = HttpContext.Current.Response; response.AppendHeader("Access-Control-Allow-Origin", "http://www.example.com"); return "success POST method !!"; }
namespace CrossOriginResourceSharing.Controllers { using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using System.Web; public class CatalogController : ApiController { // GET: api/catalog public IEnumerable<string> Get() { var response = HttpContext.Current.Response; response.AppendHeader("Access-Control-Allow-Origin", "http://www.example.com"); return new string[] { "val1", "val2" }; } // GET api/catalog/5 public string Get(int id) { var response = HttpContext.Current.Response; response.AppendHeader("Access-Control-Allow-Origin", "http://www.example.com"); return "value"; } // POST api/catalog public string Post([FromBody]string value) { var response = HttpContext.Current.Response; response.AppendHeader("Access-Control-Allow-Origin", "http://www.example.com"); return "success POST method !!"; } // PUT api/catalog/5 public string Put(int id, [FromBody]string value) { var response = HttpContext.Current.Response; response.AppendHeader("Access-Control-Allow-Origin", "http://www.example.com"); return "success PUT method !!"; } // DELETE api/catalog/5 public void Delete(int id) { var response = HttpContext.Current.Response; response.AppendHeader("Access-Control-Allow-Origin", "http://www.example.com"); } // OPTIONS api/catalog public void Options() { var response = HttpContext.Current.Response; response.AppendHeader("Access-Control-Allow-Origin", "http://www.example.com"); response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); response.AppendHeader("Access-Control-Allow-Headers", "X-PINGOTHER, application/json"); response.AppendHeader("Access-Control-Max-Age", "1728000"); } } }
クライアント 実装
クロスドメイン通信 は、実際に行う前に OPTION 通信で クロスドメイン通信 の許可を取った(プリフライト)のち、 はじめて クロスドメイン通信 ができるようになります。 この事前に行われる OPTION通信 は、自前で実装するのではなく、ブラウザの処理で自動的に処理されるようです。 つまり、以下のような処理の流れになります。
- クライアントからクロスドメイン通信を試みる
- ブラウザが自動で プリフライト (OPTION通信) を行う
- クロスドメイン通信ができそうなので、再度リクエストする
実装してみると、以下のような 単純な サンプルコード になります。 これだけで、OPTION と POST が行われます。
function () { $.ajax({ type: 'POST', url: 'http://service.example.com/Service/api/catalog' }).done(function (data, textStatus, jqXHR) { window.alert(JSON.stringify(data)); }).fail(function (jqXHR, textStatus, errorThrown) { window.alert(errorThrown); }); };
今回、以下のサイトを参考にしました。
- W3C - Cross-Origin Resource Sharing
- MSDN - XMLHttpRequest の拡張機能
- IEBlog - CORS for XHR in IE10
- MDN - HTTP access control (CORS)
最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!