I am logging in a user with intentionally invalid credentials and trying to send back the error response from the server ("Unable to login")
How to access this response in my request so I can display the message to the user?
Right now I can print the response object (see below) in Xcode but I don’t see the error message I am trying to access from the server ( "unable to login" ) in this object??
What am I doing wrong?
Javascript Express router code
router.post(`/api/user/login`, async (req, res,) => {
console.log(req.body)
try {
const user = await User.findByCredentials(req.body.email, req.body.password)
const token = await user.generateAuthToken()
res.send({user, token})
} catch (err) {
const message = err.message // err.message -> "unable to login"
res.status(400).send({message}) // HOW DO I ACCESS THIS MESSAGE IN MY REQUEST?
}
})
Swift API Request
static func loginUser (user: UserLogIn, completion: @escaping(Result <LoginResponse,
NetworkError>) -> Void) {
let user = user
guard let url = URL(string: Ref.API_ROOT + Ref.LOGIN) else { return }
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
do {
let encoder = JSONEncoder()
urlRequest.httpBody = try encoder.encode(user)
let dataTask = URLSession.shared.dataTask(with: urlRequest) { data, response, error in
guard let jsonData = data, error == nil else {
if let error = error as NSError?, error.domain == NSURLErrorDomain {
completion(.failure(.networkError("(error.localizedDescription)")))
}
return
}
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
print(response!)
completion(.failure(.loginError("Domain Error")))
return
}
do {
let response = try JSONDecoder().decode(LoginResponse.self, from: jsonData)
completion(.success(response))
} catch {
completion(.failure(.urlBuildError("Url build error")))
}
}
dataTask.resume()
} catch {
completion(.failure(.unableToComplete("Unable to complete")))
}
}
Response Object :
Why is my error response "unable to login" not in here?
<NSHTTPURLResponse: 0x623453d12134> { URL: http://localhost:3000/api/user/login } { Status Code:
400, Headers {
Connection = (
"keep-alive"
);
"Content-Length" = (
30
);
"Content-Type" = (
"application/json; charset=utf-8"
);
Date = (
"Wed, 14 Apr 2021 15:38:42 GMT"
);
Etag = (
"W/"1e-J0jWW/rGxsghjubfgt2iegw3A""
);
"Keep-Alive" = (
"timeout=5"
);
"X-Powered-By" = (
Express
);
} }
2
Answers
Response Object : Why is my error response "unable to login" not in here?
Because you have added the response in a
guard let
and your function is returning from there itself, and as it is not able to go ahead it never reaches to the decoding part.Here, when the
statusCode
is not200
then it goes in theelse
part, inside which you are printing theresponse
and then, in the next line, you have youcompletionHandler
and thenreturn
, so it returns from there only.If you want to see your message, you have decode the data in the
else
part like this:Here response is
URLResponse
and not the response you are expecting, please go through thedataTaskMethod
and know what it is:https://developer.apple.com/documentation/foundation/urlsession/1410330-datatask
For URLSession,
HTTPURLResponse
class contains only the metadata associated with the HTTP response (documentation) therefore, the logged response seems correct.In your case, I believe
res.status(400).send({message})
sends the message object in HTTP response’s body. Therefore, to parse that data,You probably would have to do some decoding since you’re sending an object for the error message on node.js. Refer to the Apple docs on Debugging HTTP Server-Side Errors for more information.