HttpClient发起POST请求时出现请求头异常、无请求体且实际发送OPTIONS请求的问题排查与解决
最近我碰到个挺头疼的问题:我用HttpClient写了一段POST请求代码,想从API获取数据,代码是这样的:
_httpClient.DefaultRequestHeaders.Accept.Clear(); _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var content = new StringContent(JsonConvert.SerializeObject(parameters), UTF8Encoding.UTF8, "application/json"); var response = await _httpClient.PostAsync(uri, content);
结果用Fiddler调试时,捕获到的原始请求居然是OPTIONS方法,完全不是我要的POST:
OPTIONS https://localhost:7052/v1/users/login HTTP/1.1
Host: localhost:7052
Connection: keep-alive
Accept: /
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin: https://localhost:7063
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Sec-Fetch-Dest: empty
Referer: https://localhost:7063/
Accept-Encoding: gzip, deflate, br
Accept-Language: pl,en;q=0.9,en-GB;q=0.8,en-US;q=0.7
而我预期的正确请求应该是这样的POST请求:
POST https://localhost:7052/v1/users/login HTTP/1.1
Host: localhost:7052
Connection: keep-alive
Content-Length: 50
Pragma: no-cache
Cache-Control: no-cache
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Microsoft Edge";v="100"
accept: application/json
Content-Type: application/json
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44
sec-ch-ua-platform: "Windows"
Origin: https://localhost:7052
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://localhost:7052/swagger/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: pl,en;q=0.9,en-GB;q=0.8,en-US;q=0.7
{ "username": "string", "password": "string" }
我纠结了好久,总觉得是不是哪里的配置漏了。后来在Panagiotis Kanavos的指引下,才发现问题根源是CORS配置错误——因为我的前端页面运行在https://localhost:7063,而API在https://localhost:7052,属于跨域请求,浏览器会先发送OPTIONS预检请求确认API是否允许该跨域请求,但我的API没有正确配置CORS策略,导致后续的POST请求无法正常触发。
找到问题后,我在Minimal API项目里添加了正确的CORS配置,代码如下:
builder.Services.AddCors(options => options.AddDefaultPolicy(builder => builder .AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod()));
这里要特别注意:一定要确保这段配置代码在app.UseCors();之前执行,否则CORS策略不会生效。配置完成后,问题就解决了,POST请求终于能正常发送了。
内容的提问来源于stack exchange,提问作者Adlorem

