在项目开发过程中,我们经常会访问第三方接口,如我们需要接入的第三方接口是Web API,这时候我们就需要使用HttpHelper调用远程接口了。示例中的HttpHelper类使用Log4Net记录了每次调用的请求内容和响应内容的日志,并且每条日志都带上了链路ID和标识,这样方便我们在排查问题时能快速的找到当时的请求和响应内容,进而定位分析问题。大家在使用的时候如不需要记录日志,删除掉即可。
HttpHelper类代码如下:
public class HttpHelper : IDisposable | |
{ | |
private bool _disposable = false; | |
/// <summary> | |
/// 请求编码格式默认utf-8; | |
/// </summary> | |
public Encoding HtmlEncoding = Encoding.UTF8; | |
/// <summary> | |
/// 请求时间 | |
/// </summary> | |
public int Timeout = 5000; | |
public CookieContainer Cookies = null; | |
/// <summary> | |
/// 是否记录Cookies | |
/// </summary> | |
public bool IsRecordCookie = false; | |
public string ContentType = "application/x-www-form-urlencoded"; | |
public string AcceptLanguage = "en-US, en; q=0.8, zh-Hans-CN; q=0.5, zh-Hans; q=0.3"; | |
public string KeepAlive = "Keep-Alive"; | |
public string Accept = "*/*"; | |
private const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240"; | |
private static ILogger Logger = Log4NetLoggerFactory.Instance.Create("remote.info"); | |
public HttpHelper() | |
{ | |
//允许最大连接数,突破Http协议的并发连接数限制 | |
ServicePointManager.DefaultConnectionLimit = 512; | |
} | |
/// <summary> | |
/// 上传图片 | |
/// </summary> | |
/// <param name="url"></param> | |
/// <param name="bArr"></param> | |
/// <param name="fileName"></param> | |
/// <returns></returns> | |
public HttpRequestEntity RequestFile(string url, byte[] bArr, string fileName = "") | |
{ | |
var result = new HttpRequestEntity { IsSuccess = 0 }; | |
//后续需要再放开,启用时需增加日志收集 | |
//if (string.IsNullOrEmpty(url)) | |
// throw new ArgumentNullException("请求Url不能为空值"); | |
//if (bArr == null || bArr.Length <= 0) | |
// throw new AccessViolationException("缺少输入数据"); | |
//Stream requestStream = null; | |
//StreamReader streamReader = null; | |
//HttpWebResponse response = null; | |
//HttpWebRequest request = null; | |
//try | |
//{ | |
// request = WebRequest.Create(url) as HttpWebRequest; | |
// request.AllowAutoRedirect = true; | |
// request.Method = "POST"; | |
// string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线 | |
// request.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary; | |
// byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n"); | |
// byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); | |
// if (string.IsNullOrEmpty(fileName)) | |
// fileName = DateTime.Now.ToString("yyyyMMddHHmmss"); | |
// //请求头部信息 | |
// StringBuilder sbHeader = new StringBuilder(string.Format("Content-Disposition:form-data;name=\"file\";filename=\"{0}\"\r\nContent-Type:application/octet-stream\r\n\r\n", fileName)); | |
// byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString()); | |
// request.Headers.Add("auth", fileName); | |
// Stream postStream = request.GetRequestStream(); | |
// postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length); | |
// postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length); | |
// postStream.Write(bArr, 0, bArr.Length); | |
// postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); | |
// postStream.Close(); | |
// response = request.GetResponse() as HttpWebResponse; | |
// requestStream = response.GetResponseStream(); | |
// if (response.StatusCode == HttpStatusCode.OK) | |
// { | |
// result.IsSuccess = 0; | |
// if (requestStream != null) | |
// { | |
// streamReader = new StreamReader(requestStream, HtmlEncoding); | |
// result.ResponseContent = streamReader.ReadToEnd(); | |
// } | |
// } | |
//} | |
//catch (Exception ex) | |
//{ | |
// result.IsSuccess = 1; | |
// result.ResponseContent = ex.Message; | |
//} | |
//finally | |
//{ | |
// if (requestStream != null) | |
// { | |
// requestStream.Close(); | |
// requestStream.Dispose(); | |
// } | |
// if (streamReader != null) | |
// { | |
// streamReader.Close(); | |
// streamReader.Dispose(); | |
// } | |
// request.Abort(); | |
// if (response != null) | |
// response.Close(); | |
//} | |
return result; | |
} | |
/// <summary> | |
/// 基本请求方法 | |
/// </summary> | |
/// <param name="requestType">HTTP请求类型</param> | |
/// <param name="url">请求的URL</param> | |
/// <param name="requestData">请求参数</param> | |
/// <param name="traceID">链路ID,方便查询日志</param> | |
/// <param name="markType">请求标识,方便查询日志</param> | |
/// <returns></returns> | |
private HttpRequestEntity BaseRequest(RequestType requestType, string url, string requestData, string traceID,string markType) | |
{ | |
var result = new HttpRequestEntity { IsSuccess = 0 }; | |
if (string.IsNullOrEmpty(url)) | |
throw new ArgumentNullException("请求Url不能为空值"); | |
Stopwatch stopwatch = new Stopwatch(); | |
stopwatch.Start(); | |
Dictionary<string, object> resultLog = new Dictionary<string, object>();//log对象 | |
resultLog.Add("logType", "remote"); | |
resultLog.Add("traceID", traceID); | |
resultLog.Add("localIp", IpHelper.LocalIp); | |
resultLog.Add("markType", markType); | |
resultLog.Add("url", url); | |
resultLog.Add("requestContent", HttpUtility.UrlDecode(requestData, Encoding.UTF8)); | |
resultLog.Add("createTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); | |
StackTrace ss = new StackTrace(true); | |
System.Reflection.MethodBase mb = ss.GetFrame(2).GetMethod();//0表示当前栈空间,1表示上一级的栈空间,依次类推 | |
resultLog.Add("className", mb.DeclaringType.FullName); | |
resultLog.Add("methodName", mb.Name); | |
HttpStatusCode statusCode = HttpStatusCode.OK; | |
if (IsRecordCookie) | |
Cookies = new CookieContainer(); | |
Stream requestStream = null; | |
StreamReader streamReader = null; | |
HttpWebRequest webRe = null; | |
HttpWebResponse webPos = null; | |
try | |
{ | |
if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) | |
{ | |
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); | |
webRe = WebRequest.Create(url) as HttpWebRequest; | |
webRe.ProtocolVersion = HttpVersion.Version10; | |
} | |
else | |
{ | |
webRe = (HttpWebRequest)WebRequest.Create(url); | |
} | |
webRe.Headers.Add("Accept-Language", AcceptLanguage); | |
webRe.Headers.Add("Keep-Alive", KeepAlive); | |
webRe.UserAgent = UserAgent; | |
webRe.Accept = Accept; | |
webRe.Timeout = Timeout; | |
webRe.ReadWriteTimeout = Timeout; | |
webRe.CookieContainer = Cookies; | |
if (requestType == RequestType.Post) | |
{ | |
webRe.ContentType = string.Format("{0}; {1}", ContentType, HtmlEncoding.BodyName); | |
byte[] datas = HtmlEncoding.GetBytes(requestData); | |
webRe.Method = "POST"; | |
webRe.ContentLength = datas.Length; | |
webRe.MaximumResponseHeadersLength = -1; | |
requestStream = webRe.GetRequestStream(); | |
requestStream.Write(datas, 0, datas.Length); | |
requestStream.Flush(); | |
requestStream.Close(); | |
} | |
else | |
webRe.Method = "GET"; | |
webPos = (HttpWebResponse)webRe.GetResponse(); | |
resultLog.Add("requestType", webRe.Method); | |
statusCode = webPos.StatusCode; | |
result.ResponseLength = webPos.ContentLength; | |
result.ResponseEncodingName = webPos.ContentEncoding; | |
requestStream = webPos.GetResponseStream(); | |
if (webPos.StatusCode == HttpStatusCode.OK) | |
{ | |
result.IsSuccess = 0; | |
if (requestStream != null) | |
{ | |
streamReader = new StreamReader(requestStream, HtmlEncoding); | |
result.ResponseContent = streamReader.ReadToEnd(); | |
} | |
} | |
} | |
catch (Exception ex) | |
{ | |
result.IsSuccess = 1; | |
result.ResponseContent = ex.Message; | |
} | |
finally | |
{ | |
if (requestStream != null) | |
{ | |
requestStream.Close(); | |
requestStream.Dispose(); | |
} | |
if (streamReader != null) | |
{ | |
streamReader.Close(); | |
streamReader.Dispose(); | |
} | |
webRe.Abort(); | |
if (webPos != null) | |
webPos.Close(); | |
} | |
if (result.IsSuccess == 1) | |
{ | |
resultLog.Add("status", HttpStatusCode.InternalServerError); | |
resultLog.Add("success", false); | |
resultLog.Add("responseContent", result.ResponseContent); | |
stopwatch.Stop(); | |
resultLog.Add("elapseTime", stopwatch.Elapsed.TotalMilliseconds); | |
string log = JsonConvert.SerializeObject(resultLog); | |
Logger.Info(log); | |
Logger.Error(log); | |
} | |
else | |
{ | |
resultLog.Add("status", statusCode); | |
resultLog.Add("success", true); | |
resultLog.Add("responseContent", result.ResponseContent); | |
stopwatch.Stop(); | |
resultLog.Add("elapseTime", stopwatch.Elapsed.TotalMilliseconds); | |
string log = JsonConvert.SerializeObject(resultLog); | |
Logger.Info(log); | |
} | |
return result; | |
} | |
private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) | |
{ | |
return true; //总是接受 | |
} | |
/// <summary> | |
/// Get请求 | |
/// </summary> | |
/// <param name="url">请求地址</param> | |
/// <param name="traceID">链路ID,方便查询日志</param> | |
/// <param name="markType">请求标识,方便查询日志</param> | |
/// <returns></returns> | |
public HttpRequestEntity Request(string url, string traceID, string markType) | |
{ | |
return BaseRequest(RequestType.Get, url, string.Empty, traceID, markType); | |
} | |
/// <summary> | |
/// Post请求 | |
/// </summary> | |
/// <param name="url">请求地址Url</param> | |
/// <param name="requestData">请求内容参数</param> | |
/// <param name="traceID">链路ID,方便查询日志</param> | |
/// <param name="markType">请求标识,方便查询日志</param> | |
/// <returns></returns> | |
public HttpRequestEntity Request(string url, string requestData, string traceID, string markType) | |
{ | |
return BaseRequest(RequestType.Post, url, requestData, traceID, markType); | |
} | |
~HttpHelper() | |
{ | |
Dispose(false); | |
} | |
public void Dispose() | |
{ | |
Dispose(true); | |
GC.SuppressFinalize(this); | |
} | |
protected virtual void Dispose(bool disposing) | |
{ | |
if (this._disposable) | |
return; | |
if (disposing) | |
{ | |
} | |
_disposable = true; | |
} | |
} | |
/// <summary> | |
/// HttpHelper请求方式 | |
/// </summary> | |
public enum RequestType | |
{ | |
/// <summary> | |
/// Get请求 | |
/// </summary> | |
Get, | |
/// <summary> | |
/// Post请求 | |
/// </summary> | |
Post | |
} | |
/// <summary> | |
/// HttpHelper请求时返回实体 | |
/// </summary> | |
public class HttpRequestEntity | |
{ | |
/// <summary> | |
/// 请求是否成功 0-成功(返回Http状态码200) 1-失败(出现异常) | |
/// </summary> | |
public int IsSuccess { get; set; } | |
/// <summary> | |
/// 请求返回内容 | |
/// </summary> | |
public string ResponseContent { get; set; } | |
/// <summary> | |
/// 请求返回内容长度 | |
/// </summary> | |
public long ResponseLength { get; set; } | |
/// <summary> | |
/// 请求返回编码类型 | |
/// </summary> | |
public string ResponseEncodingName { get; set; } | |
} |
调用示例如下:
HttpHelper helper = new HttpHelper(); | |
HttpRequestEntity response = helper.Request("需要访问的URL", "请求需要的参数", "访问链路ID", "访问标识"); | |
if (response.IsSuccess != 0) | |
{ | |
//程序处理异常,请重试! | |
} | |
else | |
{ | |
//请求响应成功 | |
} |