HttpClient
本文将演示HttpClient的使用方法。
说明:
- 为了减少重复代码,本文只演示【同步】调用,例如:GetResult()
- 如果需要【异步】,请调用 Async 结尾的方法,例如:GetResultAsync()
简单的GET请求
HttpOption httpOption = new HttpOption {
Url = "http://www.fish-test.com/show-request2.aspx",
Data = new { id = 2, name = "abc" } // 这里的数据将会合并到URL中
};
string responseText = httpOption.GetResult();
Console.WriteLine(responseText);
或者
HttpOption httpOption = new HttpOption {
Url = "http://www.fish-test.com/show-request2.aspx?id=2&name=abc",
};
string responseText = httpOption.GetResult();
Console.WriteLine(responseText);
POST 表单数据
string responseText = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-request2.aspx",
Data = new { id = 2, name = "abc" }
}.GetResult();
Console.WriteLine(responseText);
POST JSON数据
string responseText = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-body.aspx",
Data = new { id = 2, name = "abc" },
Format = SerializeFormat.Json // 注意这里
}.GetResult();
Console.WriteLine(responseText);
POST XML数据
string responseText = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-body.aspx",
Data = new NameValue { Name = "abc", Value = "123" },
Format = SerializeFormat.Xml // 注意这里
}.GetResult();
Console.WriteLine(responseText);
POST 二进制数据
var data = new NameValue { Name = "abc", Value = "123" };
byte[] bytes = data.ToJson().ToUtf8Bytes();
string responseText = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-body.aspx",
Data = bytes,
Format = SerializeFormat.Binary // 注意这里
}.GetResult();
Console.WriteLine(responseText);
POST 数据流
var data = new NameValue { Name = "abc", Value = "123" };
byte[] bytes = data.ToJson().ToUtf8Bytes();
using( MemoryStream ms = new MemoryStream(bytes) ) {
string responseText = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-body.aspx",
UserAgent = "ClownFish.UnitTest",
Data = ms,
Format = SerializeFormat.Binary // 注意这里
}.GetResult();
Console.WriteLine(responseText);
}
POST 表单数据-含文件上传
string filename1 = "small_file.txt";
string filename2 = "small_file.bin";
string filename3 = "ClownFish.Log.config";
var result = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-request2.aspx",
Format = SerializeFormat.Multipart, // 文件上传模式
Data = new {
id = 22222222222,
name = "Fish Li",
// 如果 Data 属性包含 FileInfo 或者 HttpFile 类型的属性值,就认为是上传文件
file1 = new FileInfo(filename1),
file2 = new FileInfo(filename2),
file3 = new FileInfo(filename3),
}
}.GetResult<HttpResult<string>>();
Console.WriteLine(result.Result);
提交压缩数据
var data = new NameValue { Name = "abc", Value = new string('x', 2048) };
HttpOption httpOption = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-request2.aspx",
Data = data,
Format = SerializeFormat.Json,
AutoGzipUpload = true // 注意这里
};
string text = httpOption.GetResult();
Console.WriteLine(text);
直接根据请求文本发送请求
// 下面这段文本,可以从 Fiddler 或者一些浏览器的开发工具中获取
// 拿到这段文本,不需要做任何处理,直接调用 HttpOption.FromRawText 就可以了,就是这样简单!
string request = @"
POST http://www.fish-test.com/show-request2.aspx HTTP/1.1
Host: www.fish-test.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://www.fish-test.com/Pages/Demo/TestAutoFindAction.htm
Cookie: hasplmlang=_int_; LoginBy=productKey; PageStyle=Style2;
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
input=Fish+Li&Base64=%E8%BD%AC%E6%8D%A2%E6%88%90Base64%E7%BC%96%E7%A0%81
";
string responseText =
HttpOption.FromRawText(request) // 构建 HttpOption 实例
.GetResult(); // 发送请求
Console.WriteLine(responseText);
结合RawText和Data发送请求
// 可以从 Fiddler 抓到所需要请求头,去掉:数据部分
string request = @"
POST http://www.fish-test.com/show-request2.aspx HTTP/1.1
Host: www.fish-test.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Referer: http://www.fish-test.com/Pages/Demo/TestAutoFindAction.htm
Cookie: hasplmlang=_int_; LoginBy=productKey; PageStyle=Style2;
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
";
// 1,根据一段长文本 快速设置 URL, method, headers
HttpOption httpOption = HttpOption.FromRawText(request);
// 2,设置提交数据与格式
httpOption.Format = SerializeFormat.Form;
httpOption.Data = new { id = 2, name = "aaaa", time = DateTime.Now };
// 3,发送请求,获取结果
string result = httpOption.GetResult();
Console.WriteLine(result);
设置请求超时时间
string text = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-request.aspx",
Data = new { id = 2, name = "abc" },
Timeout = 3_000 // 3 秒超时
}.GetResult();
Console.WriteLine(text);
string text2 = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-request.aspx",
Data = new { id = 2, name = "abc" },
Timeout = 0 // 无限等待
}.GetResult();
发送时指定请求头
string text = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-request2.aspx",
Data = new { id = 2, name = "abc" },
Headers = new Dictionary<string, string>() {
{ "X-Requested-With", "XMLHttpRequest" },
{ "User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64)"} }
}.GetResult();
Console.WriteLine(text);
处理请求头与响应头
HttpResult<string> result = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/test-header.aspx",
Data = new { id = 2, name = "abc" },
Header = new { // 指定二个请求头,服务端会将它们合并
X_a = "a1", // 对应请求头:X-a: a1
X_b = "b2" // 对应请求头:X-b: b2
}
}.GetResult<HttpResult<string>>();
// 注意调用上面方法时指定的泛型参数
// 如果需要读取响应头,需要指定 HttpResult<T> 的类型参数
// 读取响应结果
string responseText = result.Result; // this is html
// 读取响应头
string header = result.Headers["X-add-result"];
Assert.AreEqual("a1b2", header);
Console.WriteLine(responseText);
发送请求时指定身份信息
string text = new HttpOption {
Url = "http://RabbitHost:15672/api/queues",
Credentials = new NetworkCredential("fishli", "1qaz7410"),
Timeout = 6_000,
}.GetResult();
Console.WriteLine(text);
发送当前进程的身份到服务端_服务端采用Windows身份认证
string text = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/show-request.aspx",
Data = new { id = 2, name = "abc" },
Credentials = CredentialCache.DefaultNetworkCredentials // 注意这里
}.GetResult();
Console.WriteLine(text);
发送HTTP请求_维护会话COOKIE
// 准备一个Cookie会话容器
CookieContainer cookieContainer = new CookieContainer();
HttpOption page1 = new HttpOption {
Url = "http://www.fish-test.com/user/page1.aspx",
};
// 没有登录,返回 403
int status = GetStatusCode(page1);
Assert.AreEqual(403, status);
// 登录
HttpOption login = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/user/login.aspx",
Data = new { name = "fish li", pwd = "abc" },
Cookie = cookieContainer // 接收cookie
};
string text = login.GetResult();
Console.WriteLine(text);
Assert.AreEqual("Login OK.", text);
// 再次访问,带上Cookie,就正常了
page1 = new HttpOption {
Url = "http://www.fish-test.com/user/page1.aspx",
Cookie = cookieContainer
};
int status2 = GetStatusCode(page1);
Assert.AreEqual(200, status2);
private static int GetStatusCode(HttpOption option)
{
try {
var xx = option.GetResult();
return 200;
}
catch( RemoteWebException remoteWebException ) {
return remoteWebException.StatusCode;
}
catch( WebException ex ) {
return (int)(ex.Response as HttpWebResponse).StatusCode;
}
catch( Exception ) {
return 500;
}
}
获取各种类型的结果
// 先构造一个HttpOption对象
HttpOption httpOption = new HttpOption {
Method = "POST",
Url = "http://www.fish-test.com/test1.aspx",
Header = new { X_a = "a1", X_b = "b2" },
Format = SerializeFormat.Form,
Data = new { id = 2, name = "abc" }
};
// 下面演示一些常见的获取结果的方式
// 1,以文本形式(含HTML)获取服务端的返回结果
string text = httpOption.GetResult();
// 2,以二进制形式获取服务端的返回结果
byte[] bin = httpOption.GetResult<byte[]>();
// 3,如果服务端返回 json / xml,可以直接通过反序列化得到强类型结果
Product product = httpOption.GetResult<Product>();
// 4,以文本形式获取服务端的返回结果,并需要访问响应头
HttpResult<string> httpResult1 = httpOption.GetResult<HttpResult<string>>();
string text2 = httpResult1.Result;
string header1 = httpResult1.Headers.Get("Content-Type"); // 读取响应头
// 5,以二进制形式获取服务端的返回结果,并需要访问响应头
HttpResult<byte[]> httpResult2 = httpOption.GetResult<HttpResult<byte[]>>();
byte[] bin2 = httpResult2.Result;
// 6,服务端返回 json / xml,结果反序列化,并需要访问响应头
HttpResult<Product> httpResult3 = httpOption.GetResult<HttpResult<Product>>();
Product product2 = httpResult3.Result;
// 7, 以Stream形式获取服务端的返回结果
// 注意:拿到结果后,请使用 using 包起来使用
Stream steram = httpOption.GetResult<Stream>();
// 8, 以HttpWebResponse形式获取服务端的返回结果
// 注意:拿到结果后,请使用 using 包起来使用
HttpWebResponse response = httpOption.GetResult<HttpWebResponse>();
仅仅发送请求,不需要读取结果
HttpOption httpOption = new HttpOption {
Url = "http://www.fish-test.com/show-request2.aspx",
};
httpOption.Send();
发送请求_启用重试功能
HttpOption httpOption = new HttpOption {
Url = "http://www.fish-test.com/show-request2.aspx",
};
// 创建默认的重试策略
// 当发生 “网络不通” 或者 “HTTP 502,503” 时,最大重试 7 次,每次间隔 1000 毫秒
Retry retry = HttpRetry.Create();
string html = httpOption.GetResult<string>(retry);
支持 unix-socket
例如调用 Docker API,curl 的命令是
curl --unix-socket /var/run/docker.sock http://localhost/v1.43/images/json
对应使用 HttpOption 的方式是:
HttpOption httpOption = new HttpOption {
Url = "http://localhost/v1.43/images/json",
UnixSocketEndPoint = "/var/run/docker.sock"
};
string json = httpOption.GetResult();
或者
string script = @"
GET http://localhost/v1.43/images/json HTTP/1.1
--unix-socket: /var/run/docker.sock
".Trim();
HttpOption httpOption = HttpOption.FromRawText(script);
string json = httpOption.GetResult();