diff --git a/OSS.Http.NET45.sln b/OSS.Http.NET45.sln index ec7db6a..812ef46 100644 --- a/OSS.Http.NET45.sln +++ b/OSS.Http.NET45.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OSS.Http.NET45", "OSS.Http\OSS.Http.NET45.csproj", "{5A831C5B-8D82-4A6A-A555-3E04847455D1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OS.Http.NET45.Tests", "Tests\OS.Http.NET45.Tests\OS.Http.NET45.Tests.csproj", "{F65B8EA8-36E8-42A2-A931-086F6ADA4836}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {5A831C5B-8D82-4A6A-A555-3E04847455D1}.Debug|Any CPU.Build.0 = Debug|Any CPU {5A831C5B-8D82-4A6A-A555-3E04847455D1}.Release|Any CPU.ActiveCfg = Release|Any CPU {5A831C5B-8D82-4A6A-A555-3E04847455D1}.Release|Any CPU.Build.0 = Release|Any CPU + {F65B8EA8-36E8-42A2-A931-086F6ADA4836}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F65B8EA8-36E8-42A2-A931-086F6ADA4836}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F65B8EA8-36E8-42A2-A931-086F6ADA4836}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F65B8EA8-36E8-42A2-A931-086F6ADA4836}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/OSS.Http/Connect/OsRest.cs b/OSS.Http/Connect/OsRest.cs index ee9ee10..1a8a4d0 100644 --- a/OSS.Http/Connect/OsRest.cs +++ b/OSS.Http/Connect/OsRest.cs @@ -1,8 +1,20 @@ -using System; +#region Copyright (C) 2016 Kevin (OSS开源系列) 公众号:osscoder + +/*************************************************************************** +*   文件功能描述:Http请求 == 主请求实体 +* +*   创建人: Kevin +* 创建人Email:1985088337@qq.com +* +*****************************************************************************/ + +#endregion +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; +using System.Net.Http.Headers; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -16,8 +28,10 @@ namespace OSS.Http.Connect public class OsRest:HttpClient { private const string _lineBreak = "\r\n"; - private static readonly Encoding _defaultEncoding = Encoding.UTF8; - + public Encoding Encoding { get; set; } = Encoding.UTF8; + //private static readonly Dictionary> _notCanAddContentHeaderDics + // =new Dictionary>(); + public OsRest():this(new HttpClientHandler(),true) { } @@ -61,11 +75,10 @@ namespace OSS.Http.Connect reqMsg.RequestUri = ConfigReqUriMsg(request); reqMsg.Method = new HttpMethod(request.HttpMothed.ToString()); - reqMsg.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); // 默认补充,如果头参数中已设置,后边会覆盖 - //ConfigReqHeadersMsg(reqMsg.Headers, request); // 添加头部信息 - request.HeaderSetting?.Invoke(reqMsg.Headers); ConfigReqContent(reqMsg,request); // 配置内容 + + request.RequestSet?.Invoke(reqMsg); return reqMsg; } @@ -85,8 +98,7 @@ namespace OSS.Http.Connect var queryPara = GetReqParameters(request, ParameterType.Query); urlAddress = queryPara.Aggregate(urlAddress, (current, p) => string.Concat(current, current.IndexOf("?", StringComparison.CurrentCultureIgnoreCase) < 0 ? "?" : "&", p.ToString())); - - + return new Uri(urlAddress); } @@ -98,25 +110,51 @@ namespace OSS.Http.Connect /// private void ConfigReqContent(HttpRequestMessage reqMsg, OsHttpRequest req) { - //var reqContent=new StreamContent(); var contentStream = new MemoryStream(); + reqMsg.Content = new StreamContent(contentStream); + reqMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); + if (req.HasFile) { string boundary = GetBoundary(); - WriteMultipartFormData(contentStream, req, boundary); + reqMsg.Content.Headers.ContentLength = WriteMultipartFormData(contentStream, req, boundary); } else { string data = GetNormalFormData(req); if (!string.IsNullOrEmpty(data)) { - var bytes = _defaultEncoding.GetBytes(data); - contentStream.Write(bytes, 0, bytes.Length); + var bytes = Encoding.GetBytes(data); + int length = bytes.Length; + contentStream.Write(bytes, 0, length); + reqMsg.Content.Headers.ContentLength = length; } } - reqMsg.Content = new StreamContent(contentStream); } + + + ///// + ///// 准备请求的 头部 数据 + ///// + ///// + ///// + //protected virtual void PrepareHeaders(HttpContentHeaders contentHeader, OsHttpRequest request) + //{ + // var headerParas = GetReqParameters(request, ParameterType.Header); + // foreach (var header in headerParas) + // { + // if (_notCanAddContentHeaderDics.ContainsKey(header.Name)) + // { + // _notCanAddContentHeaderDics[header.Name].Invoke(contentHeader, header.Value.ToString()); + // } + // else + // { + // contentHeader.Add(header.Name, header.Value.ToString()); + // } + + // } + //} #endregion @@ -155,25 +193,24 @@ namespace OSS.Http.Connect /// /// /// - private void WriteMultipartFormData(Stream webRequestStream, OsHttpRequest request, string boundary) + private int WriteMultipartFormData(Stream webRequestStream, OsHttpRequest request, string boundary) { var formparas =GetReqParameters(request,ParameterType.Form); - foreach (var param in formparas) - { - //写入form表单中的非文件数据 - WriteStringTo(webRequestStream, GetMultipartFormData(param, boundary)); - } + + int contentLength = formparas.Sum(param => WriteStringTo(webRequestStream, GetMultipartFormData(param, boundary))); + foreach (var file in request.FileParameterList) { //文件头 - WriteStringTo(webRequestStream, GetMultipartFileHeader(file, boundary)); + contentLength+= WriteStringTo(webRequestStream, GetMultipartFileHeader(file, boundary)); //文件内容 - file.Writer(webRequestStream); + contentLength += file.Writer(webRequestStream); //文件结尾 - WriteStringTo(webRequestStream, _lineBreak); + contentLength += WriteStringTo(webRequestStream, _lineBreak); } //写入整个请求的底部信息 - WriteStringTo(webRequestStream, GetMultipartFooter(boundary)); + contentLength += WriteStringTo(webRequestStream, GetMultipartFooter(boundary)); + return contentLength; } /// @@ -246,12 +283,35 @@ namespace OSS.Http.Connect /// /// /// - private static void WriteStringTo(Stream stream, string toWrite) + /// 写入的字节数量 + private int WriteStringTo(Stream stream, string toWrite) { - var bytes = _defaultEncoding.GetBytes(toWrite); + var bytes = Encoding.GetBytes(toWrite); stream.Write(bytes, 0, bytes.Length); + return bytes.Length; } + //protected static void AddStaticHeaderDictionary() + //{ + // _notCanAddContentHeaderDics.Add("Accept", (r, v) => r.Accept = v); + // _notCanAddContentHeaderDics.Add("Content-Type", (r, v) => r.ContentType = v); + // _notCanAddContentHeaderDics.Add("Date", (r, v) => + // { + // DateTime parsed; + // if (DateTime.TryParse(v, out parsed)) + // { + // r.Date = parsed; + // } + // }); + // _notCanAddContentHeaderDics.Add("Host", (r, v) => r.Host = v); + // _notCanAddContentHeaderDics.Add("Connection", (r, v) => r.Connection = v); + // _notCanAddContentHeaderDics.Add("Content-Length", (r, v) => r.ContentLength = Convert.ToInt64(v)); + // _notCanAddContentHeaderDics.Add("Expect", (r, v) => r.Expect = v); + // _notCanAddContentHeaderDics.Add("If-Modified-Since", (r, v) => r. = Convert.ToDateTime(v)); + // _notCanAddContentHeaderDics.Add("Referer", (r, v) => r.Referer = v); + // _notCanAddContentHeaderDics.Add("Transfer-Encoding", (r, v) => { r.TransferEncoding = v; r.SendChunked = true; }); + // _notCanAddContentHeaderDics.Add("User-Agent", (r, v) => r.UserAgent = v); + //} private static List GetReqParameters(OsHttpRequest request,ParameterType type) { diff --git a/OSS.Http/Enum.cs b/OSS.Http/Enum.cs index d21782a..4500adf 100644 --- a/OSS.Http/Enum.cs +++ b/OSS.Http/Enum.cs @@ -1,4 +1,15 @@ - +#region Copyright (C) 2016 Kevin (OSS开源系列) 公众号:osscoder + +/*************************************************************************** +*   文件功能描述:Http请求公用枚举 +* +*   创建人: Kevin +* 创建人Email:1985088337@qq.com +* +*****************************************************************************/ + +#endregion + namespace OSS.Http { /// @@ -6,33 +17,28 @@ namespace OSS.Http /// public enum HttpMothed { - /// - /// 防止没有设置默认值,根据此值判断 - /// - None, - /// /// Get /// - GET = 10, + GET = 0, /// /// post /// - POST = 20, + POST = 10, /// /// PUT /// - PUT = 30, + PUT = 20, /// /// DELETE /// - DELETE = 40, - HEAD=50, - OPTIONS=60, - TRACE=70 + DELETE = 30, + HEAD=40, + OPTIONS=50, + TRACE=60 } @@ -81,17 +87,17 @@ namespace OSS.Http /// form表单数据 /// Form, - /// - /// 地址中的值 - /// - UrlSegment, ///// - ///// 头部参数 + ///// 地址中的值 ///// - //Header, + //UrlSegment, /// - /// cookie + /// 头部参数 /// - Cookie + Header, + ///// + ///// cookie + ///// + //Cookie } } diff --git a/OSS.Http/HttpUtil.cs b/OSS.Http/HttpUtil.cs index 629a7c1..9699d4b 100644 --- a/OSS.Http/HttpUtil.cs +++ b/OSS.Http/HttpUtil.cs @@ -1,4 +1,18 @@ -using System; +#region Copyright (C) 2016 Kevin (OSS开源系列) 公众号:osscoder + +/*************************************************************************** +*   文件功能描述:Http请求辅助类 +* +*   创建人: Kevin +* 创建人Email:1985088337@qq.com +* +* 修改日期:2017-2-12 +* 修改内容:迁移至HttpClient框架下 +* +*****************************************************************************/ + +#endregion + using System.Net.Http; using System.Threading.Tasks; using OSS.Http.Connect; @@ -11,24 +25,25 @@ namespace OSS.Http /// public static class HttpUtil { - private static HttpClientHandler m_Handler; private static OsRest m_Client ; + private static HttpMessageHandler m_MessageHandler; - public static Action SetHandler { get; set; } - + public static HttpMessageHandler MessageHandler + { + get { return m_MessageHandler ?? (m_MessageHandler = GetClientHandler()); } + set { m_MessageHandler = value; } + } /// /// 同步的请求方式 /// /// 请求的参数 /// 自定义的Response结果 - public static Task ExecuteSync(this OsHttpRequest request,HttpCompletionOption completionOption=HttpCompletionOption.ResponseContentRead) + public static Task SendRest(this OsHttpRequest request,HttpCompletionOption completionOption=HttpCompletionOption.ResponseContentRead) { if (m_Client==null) { - m_Handler=new HttpClientHandler(); - ConfigClientHandler(m_Handler); - m_Client=new OsRest(m_Handler); + m_Client=new OsRest(MessageHandler); } return m_Client.RestSend(request, completionOption); } @@ -37,12 +52,15 @@ namespace OSS.Http /// 配置请求处理类 /// /// - public static void ConfigClientHandler(HttpClientHandler reqHandler) + private static HttpClientHandler GetClientHandler() { + var reqHandler = new HttpClientHandler(); + reqHandler.AllowAutoRedirect = true; reqHandler.MaxAutomaticRedirections = 5; reqHandler.UseCookies = true; - SetHandler?.Invoke(reqHandler); + + return reqHandler; } diff --git a/OSS.Http/Models/FileParameter.cs b/OSS.Http/Models/FileParameter.cs index 29cb51a..4612215 100644 --- a/OSS.Http/Models/FileParameter.cs +++ b/OSS.Http/Models/FileParameter.cs @@ -1,4 +1,15 @@ -using System; +#region Copyright (C) 2016 Kevin (OSS开源系列) 公众号:osscoder + +/*************************************************************************** +*   文件功能描述:Http请求 == 文件参数 +* +*   创建人: Kevin +* 创建人Email:1985088337@qq.com +* +*****************************************************************************/ + +#endregion +using System; using System.IO; namespace OSS.Http.Models @@ -15,16 +26,19 @@ namespace OSS.Http.Models public FileParameter(string name, Stream fileStream, string filename, string contentType) { this.Writer = s => - { - var buffer=new byte[1024]; + { + var buffer = new byte[1024]; + var byteCount=0; using (fileStream) { int readCount = 0; while ((readCount= fileStream.Read(buffer, 0, buffer.Length))!=0) { s.Write(buffer,0,readCount); + byteCount += readCount; } } + return byteCount; }; this.FileName = filename; this.ContentType = contentType; @@ -36,8 +50,9 @@ namespace OSS.Http.Models public string Name; /// /// 读写操作流 + /// 返回的是写入的字节流长度 /// - public Action Writer; + public Func Writer; /// /// 文件名称 /// diff --git a/OSS.Http/Models/HttpRequest.cs b/OSS.Http/Models/HttpRequest.cs index 587500d..e22c991 100644 --- a/OSS.Http/Models/HttpRequest.cs +++ b/OSS.Http/Models/HttpRequest.cs @@ -1,4 +1,14 @@ - +#region Copyright (C) 2016 Kevin (OSS开源系列) 公众号:osscoder + +/*************************************************************************** +*   文件功能描述:Http请求 == 请求实体 +* +*   创建人: Kevin +* 创建人Email:1985088337@qq.com +* +*****************************************************************************/ + +#endregion using System; using System.Collections.Generic; using System.Linq; @@ -8,7 +18,7 @@ using System.Net.Http.Headers; namespace OSS.Http.Models { /// - /// + /// 请求实体 /// public class OsHttpRequest { @@ -45,14 +55,10 @@ namespace OSS.Http.Models //public bool UseCookies { get; set; } /// - /// 头部属性自定义设置 + /// reqMessage 设置方法 + /// 如果当前的设置不能满足需求,可以通过这里再次设置 /// - public Action HeaderSetting { get; set; } - - /// - /// HttpClientHandler 自定义属性设置 - /// - public Action HandlerSetting { get; set; } + public Action RequestSet { get; set; } #region 请求的内容参数 diff --git a/OSS.Http/Models/Parameter.cs b/OSS.Http/Models/Parameter.cs index ea0a5c7..d5f6130 100644 --- a/OSS.Http/Models/Parameter.cs +++ b/OSS.Http/Models/Parameter.cs @@ -1,4 +1,16 @@ -using System; +#region Copyright (C) 2016 Kevin (OSS开源系列) 公众号:osscoder + +/*************************************************************************** +*   文件功能描述:Http请求 == 参数实体 +* +*   创建人: Kevin +* 创建人Email:1985088337@qq.com +* +*****************************************************************************/ + +#endregion + +using System; namespace OSS.Http.Models { diff --git a/OSS.Http/OSS.Http.NET45.project.lock.json b/OSS.Http/OSS.Http.NET45.project.lock.json new file mode 100644 index 0000000..b547a8a --- /dev/null +++ b/OSS.Http/OSS.Http.NET45.project.lock.json @@ -0,0 +1,15 @@ +{ + "locked": false, + "version": 2, + "targets": { + ".NETFramework,Version=v4.5": {}, + ".NETFramework,Version=v4.5/win": {} + }, + "libraries": {}, + "projectFileDependencyGroups": { + "": [], + ".NETFramework,Version=v4.5": [] + }, + "tools": {}, + "projectFileToolGroups": {} +} \ No newline at end of file diff --git a/Tests/OS.Http.NET45.Tests/App.config b/Tests/OS.Http.NET45.Tests/App.config new file mode 100644 index 0000000..b50c74f --- /dev/null +++ b/Tests/OS.Http.NET45.Tests/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Tests/OS.Http.NET45.Tests/OS.Http.NET45.Tests.csproj b/Tests/OS.Http.NET45.Tests/OS.Http.NET45.Tests.csproj new file mode 100644 index 0000000..f1a4eae --- /dev/null +++ b/Tests/OS.Http.NET45.Tests/OS.Http.NET45.Tests.csproj @@ -0,0 +1,66 @@ + + + + + Debug + AnyCPU + {F65B8EA8-36E8-42A2-A931-086F6ADA4836} + Exe + Properties + OS.Http.NET45.Tests + OS.Http.NET45.Tests + v4.6.2 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + {5a831c5b-8d82-4a6a-a555-3e04847455d1} + OSS.Http.NET45 + + + + + \ No newline at end of file diff --git a/Tests/OS.Http.NET45.Tests/Program.cs b/Tests/OS.Http.NET45.Tests/Program.cs new file mode 100644 index 0000000..3f23628 --- /dev/null +++ b/Tests/OS.Http.NET45.Tests/Program.cs @@ -0,0 +1,17 @@ +using OSS.Http; +using OSS.Http.Models; + +namespace OS.Http.NET45.Tests +{ + class Program + { + static void Main(string[] args) + { + var req=new OsHttpRequest(); + + req.AddressUrl = "http://www.baidu.com"; + + var result = req.SendRest(); + } + } +} diff --git a/Tests/OS.Http.NET45.Tests/Properties/AssemblyInfo.cs b/Tests/OS.Http.NET45.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9b4dc98 --- /dev/null +++ b/Tests/OS.Http.NET45.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("OS.Http.NET45.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OS.Http.NET45.Tests")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +//将 ComVisible 设置为 false 将使此程序集中的类型 +//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("f65b8ea8-36e8-42a2-a931-086f6ada4836")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")]