分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 技术分享

DotNetCore深入了解之二HttpContext类

发布时间:2023-09-06 02:06责任编辑:熊小新关键词:暂无标签

当KestrelServer启动时,会绑定相应的IP地址,同时在绑定时将加入HttpConnectionMiddleware作为终端连接的中间件。

 1 public async Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken) 2 { 3 ????try 4 ????{ 5 ????????... 6 ?7 ????????async Task OnBind(ListenOptions endpoint) 8 ????????{ 9 ????????????// Add the HTTP middleware as the terminal connection middleware10 ????????????endpoint.UseHttpServer(endpoint.ConnectionAdapters, ServiceContext, application, endpoint.Protocols);11 12 ????????????var connectionDelegate = endpoint.Build();13 14 ????????????// Add the connection limit middleware15 ????????????if (Options.Limits.MaxConcurrentConnections.HasValue)16 ????????????{17 ????????????????connectionDelegate = new ConnectionLimitMiddleware(connectionDelegate, Options.Limits.MaxConcurrentConnections.Value, Trace).OnConnectionAsync;18 ????????????}19 20 ????????????var connectionDispatcher = new ConnectionDispatcher(ServiceContext, connectionDelegate);21 ????????????var transport = _transportFactory.Create(endpoint, connectionDispatcher);22 ????????????_transports.Add(transport);23 24 ????????????await transport.BindAsync().ConfigureAwait(false);25 ????????}26 27 ????????await AddressBinder.BindAsync(_serverAddresses, Options, Trace, OnBind).ConfigureAwait(false);28 ????}29 30 ????...31 }
View Code
1 public static IConnectionBuilder UseHttpServer<TContext>(this IConnectionBuilder builder, IList<IConnectionAdapter> adapters, ServiceContext serviceContext, IHttpApplication<TContext> application, HttpProtocols protocols)2 {3 ????var middleware = new HttpConnectionMiddleware<TContext>(adapters, serviceContext, application, protocols);4 ????return builder.Use(next =>5 ????{6 ????????return middleware.OnConnectionAsync;7 ????});8 }
View Code

当请求抵达此中间件时,在其OnConnectionAsync方法里会创建HttpConnection对象,并通过该对象处理请求

 1 public async Task OnConnectionAsync(ConnectionContext connectionContext) 2 { 3 ????... 4 ?5 ????var connection = new HttpConnection(httpConnectionContext); 6 ????_serviceContext.ConnectionManager.AddConnection(httpConnectionId, connection); 7 ?8 ????try 9 ????{10 ????????var processingTask = connection.ProcessRequestsAsync(_application);11 12 ????????...13 ????}14 ????...15 }
View Code

ProcessRequestsAsync方法内部会根据HTTP协议的不同创建Http1Connection或者Http2Connection对象,一般为Http1Connection。

 1 public async Task ProcessRequestsAsync<TContext>(IHttpApplication<TContext> httpApplication) 2 { 3 ????try 4 ????{ 5 ????????... 6 ?7 ????????lock (_protocolSelectionLock) 8 ????????{ 9 ????????????// Ensure that the connection hasn‘t already been stopped.10 ????????????if (_protocolSelectionState == ProtocolSelectionState.Initializing)11 ????????????{12 ????????????????switch (SelectProtocol())13 ????????????????{14 ????????????????????case HttpProtocols.Http1:15 ????????????????????????// _http1Connection must be initialized before adding the connection to the connection manager16 ????????????????????????requestProcessor = _http1Connection = CreateHttp1Connection(_adaptedTransport, application);17 ????????????????????????_protocolSelectionState = ProtocolSelectionState.Selected;18 ????????????????????????break;19 ????????????????????case HttpProtocols.Http2:20 ????????????????????????// _http2Connection must be initialized before yielding control to the transport thread,21 ????????????????????????// to prevent a race condition where _http2Connection.Abort() is called just as22 ????????????????????????// _http2Connection is about to be initialized.23 ????????????????????????requestProcessor = CreateHttp2Connection(_adaptedTransport, application);24 ????????????????????????_protocolSelectionState = ProtocolSelectionState.Selected;25 ????????????????????????break;26 ????????????????????case HttpProtocols.None:27 ????????????????????????// An error was already logged in SelectProtocol(), but we should close the connection.28 ????????????????????????Abort(ex: null);29 ????????????????????????break;30 ????????????????????default:31 ????????????????????????// SelectProtocol() only returns Http1, Http2 or None.32 ????????????????????????throw new NotSupportedException($"{nameof(SelectProtocol)} returned something other than Http1, Http2 or None.");33 ????????????????}34 35 ????????????????_requestProcessor = requestProcessor;36 ????????????}37 ????????}38 39 ????????if (requestProcessor != null)40 ????????{41 ????????????await requestProcessor.ProcessRequestsAsync(httpApplication);42 ????????}43 44 ????????await adaptedPipelineTask;45 ????????await _socketClosedTcs.Task;46 ????}47 ????...48 }
View Code

Http1Connection父类HttpProtocol里的ProcessRequests方法会创建一个Context对象,但这还不是最终要找到的HttpContext。

 1 private async Task ProcessRequests<TContext>(IHttpApplication<TContext> application) 2 { 3 ????// Keep-alive is default for HTTP/1.1 and HTTP/2; parsing and errors will change its value 4 ????_keepAlive = true; 5 ?6 ????while (_keepAlive) 7 ????{ 8 ????????... 9 10 ????????var httpContext = application.CreateContext(this);11 12 ????????try13 ????????{14 ????????????KestrelEventSource.Log.RequestStart(this);15 16 ????????????// Run the application code for this request17 ????????????await application.ProcessRequestAsync(httpContext);18 19 ????????????if (_ioCompleted == 0)20 ????????????{21 ????????????????VerifyResponseContentLength();22 ????????????}23 ????????}24 ????????...25 ????}26 }
View Code

在HostingApplication类中会看到HttpContext原来是由HttpContextFactory工厂类生成的。

 1 public Context CreateContext(IFeatureCollection contextFeatures) 2 { 3 ????var context = new Context(); 4 ????var httpContext = _httpContextFactory.Create(contextFeatures); 5 ?6 ????_diagnostics.BeginRequest(httpContext, ref context); 7 ?8 ????context.HttpContext = httpContext; 9 ????return context;10 }
View Code

HttpContextFactory类才是最后的一站。

 1 public HttpContext Create(IFeatureCollection featureCollection) 2 { 3 ????if (featureCollection == null) 4 ????{ 5 ????????throw new ArgumentNullException(nameof(featureCollection)); 6 ????} 7 ?8 ????var httpContext = new DefaultHttpContext(featureCollection); 9 ????if (_httpContextAccessor != null)10 ????{11 ????????_httpContextAccessor.HttpContext = httpContext;12 ????}13 14 ????var formFeature = new FormFeature(httpContext.Request, _formOptions);15 ????featureCollection.Set<IFormFeature>(formFeature);16 17 ????return httpContext;18 }
View Code

生成的HttpContext对象最终传递到IHttpApplication的ProcessRequestAsync方法。之后的事情便是WebHost与HostingApplication的工作了。

请求(Request),响应(Response),会话(Session)这些与HTTP接触时最常见到的名词,都出现在HttpContext对象中。说明在处理HTTP请求时,若是需要获取这些相关信息,完全可以通过调用其属性而得到。

通过传递一个上下文环境参数,以协助获取各环节处理过程中所需的信息,在各种框架中是十分常见的作法。ASP.NET Core里的用法并无特别的创新,但其实用性还是毋庸置疑的。如果想要构建自己的框架时,不妨多参考下ASP.NET Core里的代码,毕竟它已是一个较成熟的产品,其中有许多值得借鉴的地方。

DotNetCore深入了解之二HttpContext类

原文地址:https://www.cnblogs.com/lizhizhang/p/9383852.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved