[Web API] Web API 2 深入系列(2) 消息管道
目录
-
HttpMessageHandler
-
Web Host模式处理过程
-
Self Host模式处理过程
HttpMessageHandler
Web API处理管道由一系列HttpMessageHandler组成
public abstract class HttpMessageHandler : IDisposable
{
protected internal abstract Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
protected virtual void Dispose(bool disposing)
public void Dispose()
}
而一般在管道中,我们使用DelegatingHandler
public abstract class DelegatingHandler : HttpMessageHandler
{
public HttpMessageHandler InnerHandler { get; set; }
protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return this.innerHandler.SendAsync(request, cancellationToken);
}
}
头部是HttpServer
public class HttpServer : DelegatingHandler
{
public HttpMessageHandler Dispatcher { get; }
public HttpConfiguration Configuration { get; }
protected virtual void Initialize()
{
this.InnerHandler = HttpClientFactory.CreatePipeline(this._dispatcher, (IEnumerable<DelegatingHandler>) this._configuration.MessageHandlers);
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
this.EnsureInitialized();
return await base.SendAsync(request, cancellationToken);
}
}
其中Dispatcher就是管道的尾部
默认为HttpRoutingDispatcher
public class HttpRoutingDispatcher : HttpMessageHandler
{
public HttpConfiguration Configuration { get; }
private readonly HttpMessageInvoker _defaultInvoker = new HttpControllerDispatcher(configuration);
public HttpRoutingDispatcher(HttpConfiguration configuration, HttpMessageHandler defaultHandler)
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//1. Routing
IHttpRouteData routeData = request.GetRouteData();
if (routeData == null)
{
routeData = this._configuration.Routes.GetRouteData(request);
if (routeData != null)
request.SetRouteData(routeData);
}
//2. Dispatcher
this._defaultInvoker.SendAsync(request, cancellationToken);
}
}
实现Dispatcher(选择IHttpController)的对象默认为HttpControllerDispatcher
public class HttpControllerDispatcher : HttpMessageHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpControllerDescriptor controllerDescriptor = this.ControllerSelector.SelectController(request);
IHttpController controller = controllerDescriptor.CreateController(request);
return await controller.ExecuteAsync(controllerContext, cancellationToken);
}
}
验证管道
public class DemoController : ApiController
{
public IEnumerable<string> Get()
{
var cfg = new HttpConfiguration();
cfg.MessageHandlers.Add(new Handler1());
cfg.MessageHandlers.Add(new Handler1());
cfg.MessageHandlers.Add(new Handler1());
var server = new MyServer(cfg);
server.Initialize();//生成HttpMessageHandler链
return GetHandlers(server);
}
private IEnumerable<string> GetHandlers(MyServer server)
{
DelegatingHandler next = server;
yield return next.ToString();
while (next.InnerHandler != null)
{
yield return next.InnerHandler.ToString();
next = next.InnerHandler as DelegatingHandler;
if (next == null)
break;
}
}
}
class MyServer : HttpServer
{
public MyServer(HttpConfiguration cfg) : base(cfg) { }
public new void Initialize()//暴露Initialize方法
{
base.Initialize();
}
}
class Handler1 : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
浏览器中请求:
Web Host模式处理过程
上节我们说到HttpControllerHandler为Web Host下的处理程序.
public class HttpControllerHandler : HttpTaskAsyncHandler
{
private readonly HttpMessageInvoker _server = GlobalConfiguration.DefaultServer;
public override Task ProcessRequestAsync(HttpContext context)
{
response = await this._server.SendAsync(request, cancellationToken);
await response.Content.CopyToAsync(context.Response.OutputStream);
}
}
从上面的代码中我们看到
-
HttpControllerHandler实现的是异步HttpControllerHandler接口
-
在ProcessRequestAsync方法中 通过GlobalConfiguration.DefaultServer 启动了WebAPI管道
Self Host模式处理过程
Self Host目前可以说分为2种
- OWIN
- HttpBinding
本节重点说明一下传统方式的HttpBinding,WebAPI使用的Message为HttpMessage
通过Nuget可以非常方便的操作
Install-Package Microsoft.AspNet.WebApi.SelfHost
using (var server = new HttpSelfHostServer(new HttpSelfHostConfiguration("http://localhost:10000")))
{
server.Configuration.Routes.MapHttpRoute("default", "{controller}");
server.OpenAsync();
Console.Read();
}
接下来我们将定义一个HttpSelfHostServer来实现SelfHost
API是不是相比SelfHost更方便?
using (var server = new MyHttpSelfHostServer("http://localhost:10000"))
{
server.Configuration.Routes.MapHttpRoute("default", "{controller}");
server.OpenAsync();
Console.Read();
}
再看看我们具体的MyHttpSelfHostServer如何实现
public class MyHttpSelfHostServer : HttpServer
{
private string _url;
public MyHttpSelfHostServer(string url)
{
_url = url;
}
public async void OpenAsync()
{
var binding = new HttpBinding();
var listener = binding.BuildChannelListener<IReplyChannel>(new Uri(_url));
listener.Open();//开启监听
var reply = listener.AcceptChannel();
reply.Open();//开启通信通道
while (true)
{
var request = reply.ReceiveRequest();//接受到请求
//获取HttpRequestMessage
var method = request.RequestMessage.GetType().GetMethod("GetHttpRequestMessage");
var requestMessage = method.Invoke(request.RequestMessage, new object[] { true }) as HttpRequestMessage;
var response = await base.SendAsync(requestMessage, new CancellationTokenSource().Token);
request.Reply(CreateMessage(response));//回复消息
}
}
Message CreateMessage(HttpResponseMessage response)
{
var type = Type.GetType("System.Web.Http.SelfHost.Channels.HttpMessage,System.Web.Http.SelfHost");
return (Message)Activator.CreateInstance(type, response);
}
}
最后我们来请求一下地址:http://localhost:10000/Demo
备注:
-
文章中的代码并非完整,一般是经过自己精简后的.
-
本篇内容使用MarkDown语法编辑
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。