OSS.Http项目对于.Net Standard标准库的支持已经迁移完毕,OSS开源系列两个最底层的类库已经具有跨运行时支持的能力。因为OSS.Http类库是几年前我参照RestSharp的思路,完成的一个轻量型Http请求框架。由于时间较久底层使用的仍是HttpWebRequest,此次基本上是彻底重构,这篇文章主要包含 1. HttpClient的介绍,2. 重构的思路, 3. 容易遇到的问题。ios
一. httpclient的基本介绍git
HttpClient应该是在.net framework4.5版本左右引用的新功能,在此以前经常使用的是HttpWebRequest,相比较而言,前者更加的简单清晰,最重要的是彻底支持.net standard API,这也是我选择它的重要缘由。github
HttpClient在结构上作了很大的调整,而且是彻底异步的实现,能够说从底层上完成了异步的支持,这里先介绍对应的几个主要类:web
1. HtttpRequestMessagejson
请求的基本信息,请求地址,请求动做等,此值是在HttpClient发起请求的方法中当参数传入,与他对应的是响应 HttpResponseMessagecookie
2. HttpContent框架
请求的内容体,主要包含请求的具体内容,contenttype,contentlenght等,是HtttpRequestMessage的一个属性,这两个都包含Headers属性,可是范围分别不同,这个是很容易混淆出错的地方,我给作了简单分类:异步
HttpRequestMessage的头部(HttpRequestHeaders )主要是请求的属性,如Accept,UserAgent,AcceptEncoding等http连接的基本属性。函数
HttpContent的头部(HttpContentHeaders)主要是当前请求内容的属性,主要有:Allow,Content-Encoding,Content-Length,Content-Type ,Expires ,Last-Modified 等,详见官方类库。spa
HttpContent 系统提供了几个默认实现,主要以下几个:
3. HttpMessageHandler
此类主要做用是请求内容处理动做等的定义,如是否支持重定向,是否可使用cookie,代理Proxy等,偏向于系统的设置,能够此值经过HttpClient构造函数传入其中,系统默认的提供的子类为 HttpClientHandler。
4. HttpClient
具体的请求实现调用实现,完整实现了POST,GET,Delete等Http请求方法,全部的方法最终调用的是SendAsync方法。
上边的四个主要类,构成了HttpClient请求的主要实现,若是你只是简单的使用,那么只须要关心HttpClient便可,以下:
其实在它内部已经默认实现了HttpRequestMessage和HttpClientHandler的赋值。
虽然简单介绍,可是基本上能够看出,HttpClient的实现作了很是明确的分工,不是再像之前全部的设置都集中在webrequest中。分工的明确最直接的优点是HttpClient实现了多请求共用,参见博文:
The default HttpClient is the simplest way in which you can start sending requests. A single HttpClient can be used to send as many HTTP requests as you want concurrently so in many scenarios you can just create one HttpClient and then use that for all your requests.
也就是当你系统中要发起不一样的请求时,能够共用一个HttpClient,而不用像HttpWebReqest基本每次请求都须要从新定义一个对象,以减小资源的消耗。
二. 重构OSS.Http
回到正题,重构咱们的当前代码模块,如我所说,因为.Net Standard下彻底不提供httpWebRequest的支持,直接致使了我作出从新实现的决定,由于之前httpWebRequest的简陋,因此我基本上作了很大的封装框架,上层彻底不须要接触具体的底层实现,基本上实现了RestSharp的核心,有兴趣的同窗能够参考代码 OSS.Http 下Old分支。
重构以前因为对HttpClient不是十分了解,本想延续已有框架流程,转换实现。不过随着对Client文档的查看研究,发现不少封装已经彻底不须要,流程也发生了变化,因此删除不少原来框架下的东西,从新整理出最终的实现。
固然如今的HttpClient自己实现已经足够简单清晰,不过在不少状况下直接调用POST,GET等方法,会减小部分代码的重用,像在OSS.Social项目中,底层我只须要实现一个RestCommon方法,便可达到全局请求控制,调用方只须要提供Url,HttpMothed,Parameter便可。
这里我画了一个简单的流程图做为呈现:
流程基本没有太大的出入,代码在Github,文件的结构以下:
Mos文件下: Enum.cs 枚举类,FileParameter.cs 文件参数类,FormParameter Form表单参数类 ,OsHttpRequest 请求参数类,
OsRest.cs 是当前封装类的主要实现,同时为了保证HttpClient自己功能通用,OsRest继承自HttpClient,同时提供了RestSend方法,在这个方法中完成流程的实现并最终调用SendAsync方法执行请求。
RestUtil.cs 辅助类,完成了全局OsRest(HttpClient)的共用,并定义了一个默认HttpClientHandler实现,正常直接调用这个类就能够了。
流程中的执行用户自定义设置,能够在OSHttpRequest中的RequestSet委托属性中设置,例如能够设置访问类型是json:
三. 容易遇到的问题
虽然整个重构后的代码已经很少了,可是应该仍是有些问题能够给你们分享下
1. Header赋值问题,请参见我第一部分,必定要分清不一样Headers,不然就可能给你报不正确的值错误
2. 能够发现上边的流程图中有个“是不是Get”的判断,由于若是是Get请求,Content是不能赋值的,就像在HttpWebReqest中,若是get请求调用了GetRequestStream方法,会有“没法发送具备此谓词类型的内容正文”的异常错误。固然若是你使用的是OSS.Http做为请求,那么就没有这个问题了。
3. 和上传文件同时上传的表单参数,与单独的表单参数提交,是不同的,请注意处理,不懂得参见OsRest类便可,已经作了处理。
若是你还有其余问题,或者对后续的更新感兴趣,请关注公众号(OSSCoder):