クロスドメイン制約 を 回避 する クライアント & サーバー 実装 を 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 の フォロー」 お願いします!!
