Home > Blockchain >  make a POST request with json data
make a POST request with json data

Time:04-15

I have a problem on my code that I can't figure it out, I am making a POST request to a endpoint that is used for log-in and I am not receiving anything back, But when I send the same request to Postman I receive the valid data so the problem is at my code and truly I have no clue how to get this one fixed now friends.

The code:

func SignIn() {
    
    let json: [String: Any] = ["User": "test", "Password": "test123"]
    let jsonData = try? JSONSerialization.data(withJSONObject: json, options: .fragmentsAllowed)
    
    let url = URL(string: "https://testingkrupi/Signin")!
    
    var request = URLRequest(url: url)

    request.httpMethod = "POST"
    request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")
    request.httpBody = jsonData
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        
        guard let data = data, error == nil else {
            
            print(error?.localizedDescription ?? "No data")
            return
        }
        
        let responseJSON = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
        
        if let responseJSON = responseJSON as? [String: Any] {
            print(responseJSON)
        }
    }
    task.resume()
}

The request that must be send:

POST http://testingkrupi/Signin HTTP/1.1
User-Agent: Fiddler
Host: localhost
Content-Length: 59
Content-Type: application/json; charset=utf-8

{
    "User": "test",
    "Password": "test123"
}

The response I must get:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 14 Apr 2022 07:00:29 GMT
Content-Length: 351

{
  "StatusCode": 0,
  "Result": {
    "First": "test",
    "Last": "test123",
    "CompleteName": "test test123",
    "PhoneNumber": " 512 512321 125",
    "Email": "[email protected]",
    "IsConnectedToCustomer": true,
    "Token": "423tj32o3jg230g923gj023gijf2o02",
    "TokenExpireDate": "2020-05-14T09:00:29.2"
  }
}

CodePudding user response:

This answer is more about debugging skill you need to have in order to advance.

First, you need to find where lies the issue. You know it's in SignIn() (I guess).

Now, let's start by adding some informations to know what's happening, if you don't know (yet) how to use breakpoints, at least add logs to know what's happening:

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    print("HTTPResponse: \(response)")
    guard let data = data, error == nil else {
        print(error ?? "No data")
        return
    }
    
    let responseJSON = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
    
    if let responseJSON = responseJSON as? [String: Any] {
        print(responseJSON)
    } else {
        //Here you test nullability of responseJSON AND if it's a [String: Any], so what if it's not null, but not a [String: Any]?
        print("Response JSON is nil, or is not a [String: Any]")
    }
}

That should at least give you some feedbacks, which one is printed.

Now, let's continue:

Each time you do a try? (with the question mark), you are saying this: I know that the method can throw an error, and error which often has a good explanation on why it failed exactly, helping me into debugging it, but I decided to not care about it, I'll just ignore it.
That's the same as ignoring the Gas/Fuel tank empty warning on your car, don't complain later that it was beeping, but you just ignore it when the car will stop because there is no more gas/fuel.

You can use then a try! (with exclamation mark), which will show the error in console, but will make crash the app. At least you shouldn't miss it.

But, it's recommended for try to implement a proper do/try/catch:

do {
    let responseJSON = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
} catch {
    print("Error while calling JSONSerialization: \(error)")
    print("Got stringified response: \(String(data: data, encoding: .utf8) ?? "not utf8 stringifiable data")")
    //If you enter in the "not utf8 stringifiable data" output, then, check the data, maybe use hex representation, since not all data, like jpg data can be UTF8 interpreted as such, but that's another case.
}

For now, I don't know the output in console, but:

print("HTTPResponse: \(response)") might give you important info, usually if it's not a 200 HTTP code, and you'll have at least a "sure" print in console to ensure that the closure is correctly called.
print("Error while calling JSONSerialization: \(error)") & print("Got stringified response: \(String(data: data, encoding: .utf8) ?? "not utf8 stringifiable data")") should give you info on the real data you are receiving, and maybe why you are receiving that one.

Now, why I printed the "Stringified response" & HTTPResponse? Simply because developers often mistake what they should received with what they will receive, and ignore totally what they are in fact receiving. Don't be like that, read what you are receiving, and fix your issues. Simply reading the doc and even if you implement it correctly doesn't mean that you'll necessary succeed in first attempt, from an error on your implementation call, a server issue, an outdated doc, etc, everything can occurs.

Let's keep digging, you are using POSTMAN and it's working, did you know that POSTMAN can generate Swift URLSession Code '(and cURL too, which is often also useful)? It's not "beautiful Swift" code, but it's working one. Test that one, and if it's working, compare it with you own implementation. It can show a forgotten parameter, any silly mistake or misunderstanding of the API documentation.

Unrelated but:

You should start naming your methods with a lower case:

func SignIn()

->

func signIn()
let jsonData = try? JSONSerialization.data(withJSONObject: json, options: .fragmentsAllowed)

There is no need for .fragmentsAllowed here. You aren't using a String at top level, it's a Dictionary.

  • Related