/// <summary> /// 对请求数据进行包装,转换为合适的请求类型,并返回对应的负载类型 /// </summary> /// <param name="data">要发送的数据</param> /// <param name="contentType">对应的负载类型</param> /// <param name="extraRequestInfo">额外的请求数据</param> /// <returns>经过包装的 <see cref="HttpRequestContent"/> 对象</returns> public virtual HttpRequestContent WrapRequestContent(object data, ContentType?contentType, ExtraRequestInfo extraRequestInfo) { if (data == null) { return(null); } var type = contentType ?? GetPreferContentType(data.GetType()) ?? Setting.DefaultRequestContentType; var ea = new RequestWrapRequestContentEventArgs(this, data, extraRequestInfo) { ContentType = type }; ea.RequestContent = Setting.ContentPayloadBuilder.WrapRequestContent(data, ea); GlobalEvents.OnBeforeRequestWrapRequestContent(this, ea); OnBeforeWrapRequestContent(this, ea); var content = ea.RequestContent; contentType = ea.ContentType; if (content == null) { if (data is HttpRequestContent) { content = data as HttpRequestContent; } else if (data is string) { content = new RequestStringContent(data as string, type); } else if (data is Stream) { content = new RequestCopyStreamContent(data as Stream, type); } else if (data is byte[]) { content = new RequestByteBufferContent(data as byte[], contentType: type); } else if (data is IDictionary <string, string> && type != ContentType.Json) { content = new RequestFormDataContent(data as IDictionary <string, string>, type); } else if (data is XmlDocument || data is XmlNode || data is System.Xml.Linq.XDocument) { content = new RequestXmlContent(data, contentType ?? ContentType.Xml); } //object else if (contentType == ContentType.Json) { content = new RequestJsonContent(data); } else if (contentType == ContentType.Xml) { content = new RequestXmlContent(data, type); } else { content = new RequestObjectContent <object>(data, type); } } //全局事件 GlobalEvents.OnRequestWrapRequestContent(this, ea); //实例事件 OnRequestWrapRequestContent(this, ea); content = HttpHandler.WrapRequestContent(this, content, data, contentType); return(content); }
/// <summary> /// 创建网络请求 /// </summary> /// <param name="uri">请求地址</param> /// <param name="method">方法</param> /// <param name="data">写入的数据</param> /// <param name="refer">引用页</param> /// <param name="saveToFile">保存文件地址</param> /// <param name="streamInvoker">流读取对象,仅当返回结果为流时可用</param> /// <param name="async"></param> /// <param name="result"></param> /// <param name="isXhr"></param> /// <param name="contextData">关联的上下文数据</param> /// <param name="headers">额外的要发出去的标头</param> /// <param name="contentType">设置当发送对象类型时,设置发送类型</param> /// <param name="allowAutoRedirect">设置当服务器发送3xx代码时是否自动跟踪跳转</param> /// <param name="targetStream">要写入的目标流</param> /// <param name="extra">额外的请求数据</param> /// <typeparam name="TResult">结果类型</typeparam> /// <returns></returns> public HttpContext <TResult> Create <TResult>( string method, Uri uri, string refer = null, object data = null, TResult result = default(TResult), string saveToFile = null, EventHandler <ResponseStreamContent.RequireProcessStreamEventArgs> streamInvoker = null, bool async = false, bool?isXhr = null, Dictionary <string, object> contextData = null, WebHeaderCollection headers = null, ContentType?contentType = null, bool?allowAutoRedirect = null, Stream targetStream = null, ExtraRequestInfo extra = null ) where TResult : class { if (string.IsNullOrEmpty(method)) { throw new ArgumentException($"{nameof(method)} is null or empty.", nameof(method)); } if (uri == null) { throw new ArgumentNullException(nameof(uri), $"{nameof(uri)} is null."); } if (typeof(TResult) == typeof(object)) { throw new InvalidOperationException("context type cannot be object."); } contextData = contextData ?? new Dictionary <string, object>(); method = method.ToUpper(); var resultType = typeof(TResult); if (streamInvoker != null && typeof(Stream) == resultType) { throw new InvalidOperationException("非流结果时不可设置流操作"); } var referUri = Setting.ResolveReferUri ? ResolveUri(HttpRequestHeader.Referer, refer, contextData) : null; var request = new HttpRequestMessage(uri, method) { Referer = referUri?.OriginalString ?? refer }; if (data != null) { request.RequestData = WrapRequestContent(data, contentType, extra); } else if (request.AllowRequestBody) { request.RequestData = new RequestByteBufferContent(new byte[0]); } request.Async = async; var ctx = HttpHandler.GetContext <TResult>(this, request); Setting.InitializeHttpContext(ctx); //自动设置格式 if (request.ExceptType == null) { request.ExceptType = GetPreferedResponseType(ctx, streamInvoker, result, targetStream, saveToFile); } request.ExtraRequestInfo = extra; if (isXhr != null) { request.AppendAjaxHeader = isXhr.Value; } ctx.ContextData = contextData; request.Headers = headers; request.AllowAutoRedirect = allowAutoRedirect ?? Setting.AllowAutoDirect; return(ctx); }
/// <summary> /// 获得对应的数据处理类 /// </summary> /// <param name="ctx"></param> /// <param name="streamInvoker"></param> /// <param name="result"></param> /// <param name="targetStream">目标流</param> /// <param name="saveToFilePath">希望保存到的目标文件路径</param> /// <param name="extraRequestInfo">额外的请求数据信息</param> /// <typeparam name="T"></typeparam> /// <returns></returns> public virtual HttpResponseContent GetPreferedResponseType <T>(HttpContext ctx, EventHandler <ResponseStreamContent.RequireProcessStreamEventArgs> streamInvoker = null, T result = default(T), Stream targetStream = null, string saveToFilePath = null, ExtraRequestInfo extraRequestInfo = null) { var resultType = typeof(T); var ea = new GetPreferedResponseTypeEventArgs <T>(this, ctx, result, saveToFilePath, streamInvoker, targetStream, extraRequestInfo); ea.ResponseContent = Setting.ContentPayloadBuilder.GetResponseContent(result, ea); GlobalEvents.OnBeforeRequestGetPreferedResponseType(this, ea); OnBeforeRequestGetPreferedResponseType(this, ea); var content = ea.ResponseContent; if (content == null) { if (!saveToFilePath.IsNullOrEmpty()) { content = new ResponseFileContent(ctx, this, saveToFilePath); } else if (resultType != typeof(object)) { if (resultType == typeof(string)) { content = new ResponseStringContent(ctx, this); } else if (resultType == typeof(byte[])) { content = new ResponseBinaryContent(ctx, this); } else if (resultType == typeof(Image)) { content = new ResponseImageContent(ctx, this); } else if (resultType == typeof(XmlDocument)) { content = new ResponseXmlContent(ctx, this, (XmlDocument)(object)result); } else if (resultType == typeof(EventHandler <ResponseStreamContent.RequireProcessStreamEventArgs>)) { var r = new ResponseStreamContent(ctx, this); if (streamInvoker != null) { r.RequireProcessStream += streamInvoker; } content = r; } else if (resultType == typeof(Stream)) { content = new ResponseCopyStreamContent(ctx, this, targetStream ?? new MemoryStream()); } else { content = new ResponseObjectContent <T>(ctx, this) { ObjectInternal = result } }; } else { content = null; //为null,等待请求自动判断 } ea.ResponseContent = content; } //Global events GlobalEvents.OnRequestGetPreferedResponseType(this, ea); //instance events OnRequestGetPreferedResponseType(this, ea); //http handler HttpHandler.GetPreferedResponseType <T>(this, ctx, content, streamInvoker, result, targetStream); return(content); }
/// <summary> /// 自定义处理Cookies。仅在启用非标准cookeis解析的时候起效 /// </summary> /// <param name="context"></param> /// <returns></returns> public virtual bool ProcessCookies(HttpContext context) { return(HttpHandler.ProcessCookies(context, this)); }
/// <summary> /// 创建 <see cref="HttpClient" /> 的新实例(HttpClient) /// </summary> public HttpClient(HttpSetting setting = null, HttpHandler handler = null, CookieContainer cookieContainer = null) { Setting = setting ?? new HttpSetting(); CookieContainer = cookieContainer ?? new CookieContainer(4096, 100, 4096); HttpHandler = handler ?? new HttpHandler(); }
/// <summary> /// 创建 <see cref="HttpClient" /> 的新实例(HttpClient) /// </summary> public HttpClient(HttpSetting setting, HttpHandler handler = null, CookieContainer cookieContainer = null) { Setting = setting; CookieContainer = cookieContainer ?? new CookieContainer(); HttpHandler = handler ?? new HttpHandler(); }
/// <summary> /// 创建网络请求 /// </summary> /// <param name="uri">请求地址</param> /// <param name="method">方法</param> /// <param name="requestData">写入的数据</param> /// <param name="refer">引用页</param> /// <param name="messageCallback">消息处理句柄</param> /// <param name="saveToFile">保存文件地址</param> /// <param name="streamInvoker">流读取对象,仅当返回结果为流时可用</param> /// <typeparam name="TResult">结果类型</typeparam> /// <returns></returns> public HttpContext <TResult> Create <TResult>(Uri uri, HttpMethod?method = null, object requestData = null, Uri refer = null, Action <HttpRequestMessage> messageCallback = null, string saveToFile = null, Action <Stream> streamInvoker = null, bool async = false) { var resultType = typeof(TResult); if (method == null) { method = HttpMethod.GET; if (requestData != null) { method = HttpMethod.POST; } } if (streamInvoker != null && typeof(Stream) == resultType) { throw new InvalidOperationException("非流结果时不可设置流操作"); } var request = new HttpRequestMessage(uri, method.Value) { ReferUri = refer, Encoding = Setting.StringEncoding }; if (requestData != null) { if (requestData is HttpRequestContent) { request.RequestData = requestData as HttpRequestContent; } else if (requestData is string) { request.RequestData = new RequestStringContent(requestData as string); } else if (requestData is Stream) { request.RequestData = new RequestCopyStreamContent(requestData as Stream); } else if (requestData is byte[]) { request.RequestData = new RequestByteBufferContent(requestData as byte[]); } else if (requestData is IDictionary <string, string> ) { request.RequestData = new RequestFormDataContent(requestData as IDictionary <string, string>); } else { request.RequestData = new RequestObjectContent <object>(requestData); } } else if (method == HttpMethod.POST) { request.RequestData = new RequestByteBufferContent(new byte[0]); } request.Async = async; if (messageCallback != null) { messageCallback(request); } var ctx = HttpHandler.GetContext <TResult>(this, request); //自动设置格式 if (request.ExceptType == null) { if (!saveToFile.IsNullOrEmpty()) { request.ExceptType = new ResponseFileContent(ctx, this, saveToFile); } else { if (resultType != typeof(object)) { if (resultType == typeof(string)) { request.ExceptType = new ResponseStringContent(ctx, this); } else if (resultType == typeof(byte[])) { request.ExceptType = new ResponseBinaryContent(ctx, this); } else if (resultType == typeof(Image)) { request.ExceptType = new ResponseImageContent(ctx, this); } else if (resultType == typeof(XmlDocument)) { request.ExceptType = new ResponseXmlContent(ctx, this); } else if (resultType == typeof(Stream)) { var r = new ResponseStreamContent(ctx, this); request.ExceptType = r; if (streamInvoker != null) { r.RequireProcessStream += (s, e) => streamInvoker(e.Stream); } } else { request.ExceptType = new ResponseObjectContent <TResult>(ctx, this); } } } } return(ctx); }