ASP.NETで特定のリクエストに動的にHTTPヘッダを設定する方法
概要
全てのリクエストに対してHeaderを追加する場合は、Web.configに<customHeaders>を追加すれば済みます(下記)。しかし、リクエストに応じてヘッダを設定したい場合は使えないです。
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Viewを返すControllerでHeaderを追加すれば済む話ではありますが、いちいち追加するのはあまり綺麗でない上に静的に配信するファイルに対しては有効でないです。
今回は、Moduleを用いてリクエスト毎に実行されるイベントを作成することで用いて実現します。
Moduleとは
Moduleを使用すると、各要求の途中段階で処理を割り込ませることが可能です。これにより、要求に対して特定の動作をすることが可能です。
ソースコード
using System;
using System.Web;
using System.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace App.Modules
{
public class HTTPHeaderModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreSendRequestHeaders += AddHeaderFromURL;
}
/// <summary>
/// HeaderをURLに応じて追加する
/// </summary>
private void AddHeaderFromURL(object sender, EventArgs e)
{
HttpRequest request = (HttpRequest)sender.GetType().GetProperty("Request").GetValue(sender);
HttpResponse responce = (HttpResponse)sender.GetType().GetProperty("Response").GetValue(sender);
//リクエストのURL
var url = request.Url;
//リクエストの絶対パスの先頭が/apiだったら
if (Regex.IsMatch(url.AbsolutePath, "^/api", RegexOptions.IgnoreCase))
{
if (request.Headers.AllKeys.Contains("Origin"))
{
//リクエスト元(オリジン)のURL
Uri hostUrl = new Uri(request.Headers["Origin"]);
if (IsAllowedHost(hostUrl.Host))
{
//リクエストのオリジンを許可
responce.Headers.Add("Access-Control-Allow-Origin", hostUrl.GetLeftPart(UriPartial.Authority));
}
}
}
}
public void Dispose(){}
private bool IsAllowedHost(string host)
{
return Regex.IsMatch(host, ".*twitter\\.com", RegexOptions.IgnoreCase);
}
}
}
Web.config
<configuration>
<system.webServer>
<modules>
<add name="HTTPHeaderModule" type="App.Modules.HTTPHeaderModule" />
</modules>
</system.webServer>
</configuration>
やっていること
using System;
using System.Web;
using System.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace App.Modules
{
public class HTTPHeaderModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreSendRequestHeaders += AddHeaderFromURL;
}
/// <summary>
/// HeaderをURLに応じて追加する
/// </summary>
private void AddHeaderFromURL(object sender, EventArgs e)
{
HttpRequest request = (HttpRequest)sender.GetType().GetProperty("Request").GetValue(sender);
HttpResponse responce = (HttpResponse)sender.GetType().GetProperty("Response").GetValue(sender);
//リクエストのURL
var url = request.Url;
//リクエストの絶対パスの先頭が/apiだったら
if (Regex.IsMatch(url.AbsolutePath, "^/api", RegexOptions.IgnoreCase))
{
if (request.Headers.AllKeys.Contains("Origin"))
{
//リクエスト元(オリジン)のURL
Uri hostUrl = new Uri(request.Headers["Origin"]);
if (IsAllowedHost(hostUrl.Host))
{
//リクエストのオリジンを許可
responce.Headers.Add("Access-Control-Allow-Origin", hostUrl.GetLeftPart(UriPartial.Authority));
}
}
}
}
public void Dispose(){}
private bool IsAllowedHost(string host)
{
return Regex.IsMatch(host, ".*twitter\\.com", RegexOptions.IgnoreCase);
}
}
}
<configuration>
<system.webServer>
<modules>
<add name="HTTPHeaderModule" type="App.Modules.HTTPHeaderModule" />
</modules>
</system.webServer>
</configuration>
Initでヘッダ送信前に実行されるよう、AddHeaderFromURL関数を登録しています。
AddHeaderFromURL関数では、senderにリクエストやレスポンスが入ったオブジェクトが渡されるので、それをReflectionで取り出してあげています。(HttpContext.Currentにもリクエストやレスポンスが入っていて、それを用いても同様の動作をします。しかし、ApiControllerを用いてレスポンスを返す際にはnullになることがある 1 ようなので、senderから取得しています。)
分かりにくいですが、Reflectionで取り出したものも参照をコピーしてきているだけなので、これの中を変更してもsenderは変更されます。よって、特定の条件にマッチした場合、取り出したレスポンス内のheaderに追加しています。
Author And Source
この問題について(ASP.NETで特定のリクエストに動的にHTTPヘッダを設定する方法), 我々は、より多くの情報をここで見つけました https://qiita.com/keymoon/items/3e4a7d5d9af8663a2bbf著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .