Ad

Swift HTTP Post Request Returns HTML Of Site Instead Of JSON Response

- 1 answer

I am trying to reach a site that should take the username and password given and return a JSON which contains information stating whether or not the login data provided was valid or not. However, all I'm getting back is the site's HTML code instead of a response. I've tried the request with the same parameters on https://www.hurl.it/ and have gotten the correct response so that does not seem to be the issue.

I use the following code:

private func uploadToAPI(username: String, password: String) {

guard let url = URL(string: "http://api.foo.com/login.php"),
  let encodedUsername = username.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics),
  let encodedPassword = password.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics) else {

  self.loginButton.isLoading = false
  return
}

let httpBodyParameters = ["user": encodedUsername, "password": encodedPassword, "client": "ios", "version": "5"]

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: httpBodyParameters, options: JSONSerialization.WritingOptions.prettyPrinted)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")

URLSession.shared.dataTask(with: request) { (data, response, error) in

  if let response = response {
    print(response.mimeType) // Prints "text/html"
  }

  if let data = data {
    print(try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)) // Prints nil
    print(String(data: data, encoding: String.Encoding.utf8)) // Prints the site's HTML
  }

}.resume()

 }

I fail to see where the issue is. I've also tried not setting the HTTP headers but that makes no difference. Anyone got any ideas?

Ad

Answer

It seems like not setting the HTTP header fields and using a string literal instead of a Dictionary as HTTP body data did it for me.

For anyone interested this is the code that now receives the expected response:

  guard let url = URL(string: "http://api.foo.com/login.php?"),
      let encodedUsername = username.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics),
      let encodedPassword = password.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics) else {
        if let delegate = self.delegate {
          delegate.viewModelDidRejectLogin(self)
        }
        return
    }

    let httpBodyString = "user=\(encodedUsername)&password=\(encodedPassword)&client=ios&version=5"

    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.httpBody = httpBodyString.data(using: String.Encoding.utf8)

    URLSession.shared.dataTask(with: request) { (data, response, error) in

      guard let data = data, error == nil else {
        print(error)
        return
      }

      do {
        if let json = try JSONSerialization.jsonObject(with: data) as? [String : AnyObject] {
          self.readLoginResponse(json)
        }
      } catch {
        print(error)
      }

    }.resume()
Ad
source: stackoverflow.com
Ad