URLSession设置POST请求却发送GET,原因是什么?
你遇到的情况确实挺闹心——明明代码里明确设置了POST方法,但实际发送的却是GET,还收到了服务器的错误提示:
{"message":"Method "GET" not allowed.","code":"method_not_allowed"}
结合你的代码和Charles的观测结果,我整理了几个最可能的原因:
1. JSON编码失败导致请求体为空,服务器降级处理
看你的代码里,参数编码逻辑是这样的:
if let parameters = parameters { do { let postParams = try JSONEncoder().encode(parameters) let postData = postParams request.httpBody = postData } catch { print("error") } }
如果JSONEncoder()编码参数时抛出错误(比如参数类型不符合Codable要求、存在无法序列化的内容),你只是打印了"error"但没终止请求流程。这时候request.httpBody会保持为nil,有些服务器在接收没有请求体的"POST"请求时,会默认把它当作GET请求处理。
排查方法:检查控制台是否打印了"error",如果有,说明编码失败,需要修复参数的Codable实现或参数内容。
2. 自定义set(headers:)方法修改了请求方法
你调用了request.set(headers: headers)这个自定义扩展方法,如果这个方法内部存在修改httpMethod的逻辑,就会覆盖你之前设置的POST。比如有些扩展可能会根据特定header字段调整请求方法,或者不小心写错了赋值逻辑。
排查方法:查看set(headers:)方法的实现,确认它没有修改httpMethod属性。
3. 服务器端重定向导致请求方法被转换
很多服务器会做重定向处理(比如HTTP转HTTPS、路径重定向等),部分重定向规则会把POST请求转换为GET请求。你可以在Charles里查看完整请求链路,看看有没有3xx状态码的重定向响应,后续请求是不是变成了GET。
排查方法:在Charles的请求列表里,逐个检查请求的状态码和方法,确认是否是重定向导致的方法变更。
4. URL本身存在异常
如果你的请求URL包含查询参数(比如https://example.com/api?param=123),虽然POST请求带查询参数是允许的,但有些服务器或代理的特殊配置可能会把这类请求当作GET处理。另外也要确认URL是否正确,有没有拼写错误导致请求到了不支持POST的路径。
排查方法:检查请求URL的格式,去掉不必要的查询参数后再测试。
另外,你的代码里有个小拼写错误:let methodString = mehtod.rawValue里的mehtod应该是method,虽然你现在没用到这个变量,但如果后续打算用它来设置httpMethod,这个错误会导致问题,建议提前修正。
内容的提问来源于stack exchange,提问作者BergP

