我相信这是 FSharp.Data 库中的一个错误。查看它的source code on GitHub,我们可以提取我们感兴趣的代码,例如:
let values = [ "id", "2"; ]
let req = WebRequest.Create("https://..../CheckLoginServlet") :?> HttpWebRequest
req.Method <- HttpMethod.Post
req.UserAgent <- "Magic"
req.AutomaticDecompression <- DecompressionMethods.GZip ||| DecompressionMethods.Deflate
let cookieContainer = new CookieContainer()
req.CookieContainer <- cookieContainer
req.ContentType <- "application/x-www-form-urlencoded"
let bytes = [ for k, v in values -> Uri.EscapeDataString k + "=" + Uri.EscapeDataString v ]
|> String.concat "&"
|> HttpEncodings.PostDefaultEncoding.GetBytes
let f = fun () -> async {
do! writeBody req bytes
let req = customizeHttpRequest req
let! resp = Async.FromBeginEnd(req.BeginGetResponse , req.EndGetResponse)
let stream = resp.GetResponseStream()
return! toHttpResponse
}
f()
问题在于writeBody调用之前调用customizeHttpRequest,而它的代码是:
let writeBody (req:HttpWebRequest) (postBytes:byte[]) = async {
req.ContentLength <- int64 postBytes.Length
use! output = Async.FromBeginEnd(req.BeginGetRequestStream, req.EndGetRequestStream)
do! output.AsyncWrite(postBytes, 0, postBytes.Length)
output.Flush()
}
其中Async.FromBeginEnd(req.BeginGetRequestStream, req.EndGetRequestStream) 更改HttpWebRequest.m_RequestSubmitted 标志,然后由HttpWebRequest.Proxy 的属性设置器(如许多其他)检查。我的建议:
- 直接使用
HttpWebRequest 编写您自己的方法,
- 编译您自己的 FSharp.Data 版本,更改
do! writeBody req bytes 和 let req = customizeHttpRequest req 调用的顺序
- 通知库的贡献者对此进行修复
注意:这可以很容易地在 C# 示例程序中重现:
private static async void GetRequestStreamCallback(IAsyncResult ar)
{
HttpWebRequest req = (HttpWebRequest)ar.AsyncState;
Stream postStream = req.EndGetRequestStream(ar); // Here flag req.m_RequestSubmitted is true already
byte[] byteArray = Encoding.UTF8.GetBytes("id=1");
await postStream.WriteAsync(byteArray, 0, byteArray.Length);
postStream.Close();
req.Proxy = new WebProxy("localhost:8888", true);
allDone.WaitOne();
}
private static ManualResetEvent allDone = new ManualResetEvent(false);
static void Main(string[] args)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost:64343/api/products");
req.Method = "POST";
req.UserAgent = "Magic";
req.AutomaticDecompression = DecompressionMethods.GZip;
req.CookieContainer = new CookieContainer();
req.ContentType = "application/x-www-form-urlencoded";
var bytes = Encoding.UTF8.GetBytes("id=2");
req.ContentLength = bytes.Length;
req.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), req);
allDone.WaitOne();
}