I am trying to send a request that should contain both URL parameters and request body in JSON. Backend doesn't recognize the request and returns 400 status code.
This is how I tried to solve the problem
enum MyRequestsRouter: URLRequestConvertible {
case RequestA(paramA: String, bodyInJsonString: String),
RequestB(paramB: String)
var baseURL: URL {
URL(string: "http://127.0.0.1:8080")!
}
var method: HTTPMethod {
switch self {
case .RequestA: return .post
case .RequestB: return .get
}
}
var path: String {
switch self {
case .RequestA: return "/api/a"
case .RequestB: return "/api/b"
}
}
var parameters: Parameters? {
switch self {
case .RequestA(let paramA, let bodyInJsonString):
return [
"paramA": paramA
]
case .RequestB(let paramB):
return ["paramB": paramB]
default:
return nil
}
}
func asURLRequest() throws -> URLRequest {
let url = baseURL.appendingPathComponent(path)
var request = URLRequest(url: url)
request.method = method
switch self {
case let .RequestA(paramA, bodyInJsonString):
// here I am specifying `paramA` value
request = try URLEncoding.default.encode(request, with: parameters)
// here body is already serialized to Json
request.httpBody = Data(bodyInJsonString.utf8)
request.setValue("application/json", "Content-Type")
case let .RequestB(paramB):
request = try URLEncoding.default.encode(request, with: parameters)
}
return request
}
}
And this is how I am making API call
let json: Data = try JSONEncoder().encode(notSerializedBodyObject)
let jsonString = String(data: json, encoding: .utf8)
AF.request(MyRequestsRouter.RequestA(paramA: "paramA", bodyInJsonString: jsonString!)).response { response in
print("Request: \(response.request)")
print("Response: \(response.response)")
print("Error: \(response.error)")
// etc
}
}
As you can see the request URL is supposed to be
http://127.0.0.1:8080/api/a?paramA=paramA
plus request body in JSON. But response is 400 Bad request.
How to properly configure Alomofire?
CodePudding user response:
Alamofire's URLEncoding
has an initializer that gets destination
as parameter. Based on documentation:
Destination
defining where the encoded query string will be applied..methodDependent
by default.
By default .methodDependent
case checks the HTTP method of the request and only on .get
, .head
and .delete
requests it encodes the passed parameters in the URL.
Given that fact, you never see paramA
in your request (not even in the body) because you override it in the following line:
// here body is already serialized to Json
request.httpBody = Data(bodyInJsonString.utf8)
So, instead of using the default URLEncoding
, you can simply call URLEncoding
's initializer directly passing as destination
the .queryString
case like this:
// here I am specifying `paramA` value
request = try URLEncoding(destination: .queryString).encode(request, with: parameters)
// here body is already serialized to Json
request.httpBody = Data(bodyInJsonString.utf8)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
That way you will have a request with paramA
in the URL and your JSON as a body.