aliyun-net-sdk-dybaseapi/Dybaseapi/MNS/Runtime/Pipeline/HttpHandler/HttpHandler.cs (206 lines of code) (raw):

using System; using System.Globalization; using System.Text; using Aliyun.Acs.Dybaseapi.MNS.Runtime.Internal; using Aliyun.Acs.Dybaseapi.MNS.Runtime.Internal.Util; using Aliyun.Acs.Dybaseapi.MNS.Util; namespace Aliyun.Acs.Dybaseapi.MNS.Runtime.Pipeline.HttpHandler { /// <summary> /// The HTTP handler contains common logic for issuing an HTTP request that is /// independent of the underlying HTTP infrastructure. /// </summary> /// <typeparam name="TRequestContent"></typeparam> public class HttpHandler<TRequestContent> : PipelineHandler, IDisposable { private bool _disposed; private IHttpRequestFactory<TRequestContent> _requestFactory; /// <summary> /// The sender parameter used in any events raised by this handler. /// </summary> public object CallbackSender { get; private set; } /// <summary> /// The constructor for HttpHandler. /// </summary> /// <param name="requestFactory">The request factory used to create HTTP Requests.</param> /// <param name="callbackSender">The sender parameter used in any events raised by this handler.</param> public HttpHandler(IHttpRequestFactory<TRequestContent> requestFactory, object callbackSender) { _requestFactory = requestFactory; this.CallbackSender = callbackSender; } /// <summary> /// Issues an HTTP request for the current request context. /// </summary> /// <param name="executionContext">The execution context which contains both the /// requests and response context.</param> public override void InvokeSync(IExecutionContext executionContext) { IHttpRequest<TRequestContent> httpRequest = null; try { SetMetrics(executionContext.RequestContext); IRequest wrappedRequest = executionContext.RequestContext.Request; httpRequest = CreateWebRequest(executionContext.RequestContext); httpRequest.SetRequestHeaders(wrappedRequest.Headers); try { executionContext.RequestContext.Metrics.StartEvent(Metric.HttpRequestTime); // Send request body if present. if (wrappedRequest.HasRequestBody()) { var requestContent = httpRequest.GetRequestContent(); WriteContentToRequestBody(requestContent, httpRequest, executionContext.RequestContext); } executionContext.ResponseContext.HttpResponse = httpRequest.GetResponse(); } finally { executionContext.RequestContext.Metrics.StopEvent(Metric.HttpRequestTime); } } finally { if (httpRequest != null) httpRequest.Dispose(); } } /// <summary> /// Issues an HTTP request for the current request context. /// </summary> /// <param name="executionContext">The execution context which contains both the /// requests and response context.</param> /// <returns>IAsyncResult which represent an async operation.</returns> public override IAsyncResult InvokeAsync(IAsyncExecutionContext executionContext) { IHttpRequest<TRequestContent> httpRequest = null; try { SetMetrics(executionContext.RequestContext); httpRequest = CreateWebRequest(executionContext.RequestContext); executionContext.RuntimeState = httpRequest; IRequest wrappedRequest = executionContext.RequestContext.Request; if (executionContext.RequestContext.Retries == 0) { // First call, initialize an async result. executionContext.ResponseContext.AsyncResult = new RuntimeAsyncResult(executionContext.RequestContext.Callback, executionContext.RequestContext.State); } // Set request headers httpRequest.SetRequestHeaders(executionContext.RequestContext.Request.Headers); executionContext.RequestContext.Metrics.StartEvent(Metric.HttpRequestTime); if (wrappedRequest.HasRequestBody()) { // Send request body if present. httpRequest.BeginGetRequestContent(new AsyncCallback(GetRequestStreamCallback), executionContext); } else { // Get response if there is no response body to send. httpRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), executionContext); } return executionContext.ResponseContext.AsyncResult; } catch (Exception) { if (executionContext.ResponseContext.AsyncResult != null) { // An exception will be thrown back to the calling code. // Dispose AsyncResult as it will not be used further. executionContext.ResponseContext.AsyncResult.Dispose(); executionContext.ResponseContext.AsyncResult = null; } if (httpRequest != null) { httpRequest.Dispose(); } throw; } } private void GetRequestStreamCallback(IAsyncResult result) { IAsyncExecutionContext executionContext = null; IHttpRequest<TRequestContent> httpRequest = null; try { executionContext = result.AsyncState as IAsyncExecutionContext; httpRequest = executionContext.RuntimeState as IHttpRequest<TRequestContent>; var requestContent = httpRequest.EndGetRequestContent(result); WriteContentToRequestBody(requestContent, httpRequest, executionContext.RequestContext); //var requestStream = httpRequest.EndSetRequestBody(result); httpRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), executionContext); } catch(Exception exception) { httpRequest.Dispose(); // Capture the exception and invoke outer handlers to // process the exception. executionContext.ResponseContext.AsyncResult.Exception = exception; base.InvokeAsyncCallback(executionContext); } } private void GetResponseCallback(IAsyncResult result) { IAsyncExecutionContext executionContext = null; IHttpRequest<TRequestContent> httpRequest = null; try { executionContext = result.AsyncState as IAsyncExecutionContext; httpRequest = executionContext.RuntimeState as IHttpRequest<TRequestContent>; var httpResponse = httpRequest.EndGetResponse(result); executionContext.ResponseContext.HttpResponse = httpResponse; } catch (Exception exception) { // Capture the exception and invoke outer handlers to // process the exception. executionContext.ResponseContext.AsyncResult.Exception = exception; } finally { executionContext.RequestContext.Metrics.StopEvent(Metric.HttpRequestTime); httpRequest.Dispose(); base.InvokeAsyncCallback(executionContext); } } private static void SetMetrics(IRequestContext requestContext) { requestContext.Metrics.AddProperty(Metric.ServiceName, requestContext.Request.ServiceName); requestContext.Metrics.AddProperty(Metric.ServiceEndpoint, requestContext.Request.Endpoint); requestContext.Metrics.AddProperty(Metric.MethodName, requestContext.Request.RequestName); } /// <summary> /// Determines the content for request body and uses the HTTP request /// to write the content to the HTTP request body. /// </summary> /// <param name="requestContent">Content to be written.</param> /// <param name="httpRequest">The HTTP request.</param> /// <param name="requestContext">The request context.</param> private void WriteContentToRequestBody(TRequestContent requestContent, IHttpRequest<TRequestContent> httpRequest, IRequestContext requestContext) { IRequest wrappedRequest = requestContext.Request; if (wrappedRequest.ContentStream == null) { byte[] requestData = wrappedRequest.Content; requestContext.Metrics.AddProperty(Metric.RequestSize, requestData.Length); httpRequest.WriteToRequestBody(requestContent, requestData, requestContext.Request.Headers); } else { var originalStream = wrappedRequest.ContentStream; httpRequest.WriteToRequestBody(requestContent, originalStream, requestContext.Request.Headers, requestContext); } } /// <summary> /// Creates the HttpWebRequest and configures the end point, content, user agent and proxy settings. /// </summary> /// <param name="requestContext">The async request.</param> /// <returns>The web request that actually makes the call.</returns> protected virtual IHttpRequest<TRequestContent> CreateWebRequest(IRequestContext requestContext) { IRequest request = requestContext.Request; Uri url = AliyunServiceClient.ComposeUrl(request); var httpRequest = _requestFactory.CreateHttpRequest(url); httpRequest.ConfigureRequest(requestContext); httpRequest.Method = request.HttpMethod; if (request.MayContainRequestBody()) { if (request.Content == null && (request.ContentStream == null)) { string queryString = AliyunSDKUtils.GetParametersAsString(request.Parameters); request.Content = Encoding.UTF8.GetBytes(queryString); } if (request.Content!=null) { request.Headers[HttpHeader.ContentLengthHeader] = request.Content.Length.ToString(CultureInfo.InvariantCulture); } else if (request.ContentStream != null && !request.Headers.ContainsKey(HttpHeader.ContentLengthHeader)) { request.Headers[HttpHeader.ContentLengthHeader] = request.ContentStream.Length.ToString(CultureInfo.InvariantCulture); } } else if (request.UseQueryString && (request.HttpMethod == "POST" || request.HttpMethod == "PUT" || request.HttpMethod == "DELETE")) { request.Content = new Byte[0]; } return httpRequest; } /// <summary> /// Disposes the HTTP handler. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { if (_requestFactory != null) _requestFactory.Dispose(); _disposed = true; } } } }