Search code examples
swiftapialamofirepostman

Calling an API with HTTP Header and Body with Alamofire


I'm trying to recreate a POST request that already works in Postman in Swift 3 with Alamofire 4, but i'm always getting a Status Code 400 "Bad Request". I am out of ideas about what I'm doing wrong here.

This is the request in Postman, additionally there is a username and password in the Body in JSON format: Working Postman Call

Reading the Docs for Alamofire, I thought this should be the correct Swift code:

func login(as username: String, withPassword password: String) {

    let url = "https://api2.drive-now.com/login"

    let parameters: Parameters = [
        "username" : username,
        "password" : password
    ]

    let loginHeaders: HTTPHeaders = [
        "Accept" : "application/json;v=1.6",
        "Accept-Encoding" : "gzip, deflate, sdch",
        "Accept-Language" : "de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4",
        "Connection" : "keep-alive",
        "Host" : "api2.drive-now.com",
        "Origin" : "https://de.drive-now.com",
        "X-Api-Key" : "adf51226795afbc4e7575ccc124face7",
        "X-Language" : "de",
        "Content-Type" : "application/json"
    ]

    Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: loginHeaders).responseJSON { response in
        print("Request: \(response.request)")    // original URL request
        print("Response: \(response.response)")  // HTTP URL response
        print("Data: \(response.data)")          // server data
        print("Result: \(response.result)")      // result of response serialization

        if let JSON = response.result.value {
            print("JSON: \(JSON)")
        }
    }

}

My console output is:

Request: Optional(https://api2.drive-now.com/login)
Response: Optional(<NSHTTPURLResponse: 0x6000000266a0> { URL: https://api2.drive-now.com/login } { status code: 400, headers {
Connection = close;
"Content-Length" = 181;
"Content-Type" = "text/html";
Date = "Tue, 13 Dec 2016 22:12:46 GMT";
Server = "nginx/1.4.6 (Ubuntu)";
} })
Data: Optional(181 bytes)
Result: FAILURE

Is there a custom session manager maybe that I have to implement? Or do you know of any debugging methods I could use here?


Solution

  • A friend accustomed to the API did help me resolve the issue: it was a default header field that seems to be added by Alamofire to every call. The API didn't accept calls with a "User-Agent" set (don't ask me why).

    To help others who might have the same problem, I share the steps I went through to find and resolve the issue:

    1. I made Alamofire.request(...) into a variable named postage (you can call it however you like, of course)
    2. I added debugPrint(postage) to the end of the login-function
    3. The output showed the additional header field
    4. I constructed a custom SessionManager like below

      var headers = Alamofire.SessionManager.defaultHTTPHeaders
      headers.removeValue(forKey: "User-Agent")
      
      let configuration = URLSessionConfiguration.default
      configuration.httpAdditionalHeaders = headers
      
      api = Alamofire.SessionManager(configuration: configuration)