Post a json patch in Swift 5 - swift

I'm testing an api call in Swift with Patch to update an object partially.
It worked well with Postman
PATCH http://localhost:5000/api/accounts/eca9c1b05fb24ca192afe370aa5a1965
[
{
"op": "add",
"path": "/firstname",
"value": "wakaka"
}
]
Here's my playground:
let urlString = "http://localhost:5000/api/accounts/eca9c1b05fb24ca192afe370aa5a1965"
let url = URL(string: urlString)
var request = URLRequest(url: url!)
// guard var request = request else { return nil }
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("gzip, deflate, br", forHTTPHeaderField: "Accept-Encoding")
request.httpMethod = "PATCH"
let jsonPatch = "[{\"op\" : \"add\", \"path\" : \"/firstname\", \"value\": \"my first name\"}]"
do {
let encodedResult = try JSONEncoder().encode(jsonPatch)
print(encodedResult.debugDescription)
request.httpBody = encodedResult
print(request.httpBody?.description)
} catch let error {
print(error.localizedDescription)
}
// decoding
URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
print("err: ",error.debugDescription)
return
}
// handling api's errors
if let res = response as? HTTPURLResponse {
print(res.statusCode)
switch res.statusCode {
case 400:
print("400")
// completion(.failure(ApiError.badRequest))
return
case 409:
print("409")
return
case 422:
print("422")
print(res.debugDescription)
return
default:
break
}
}
// OK
do {
let result = try JSONSerialization.jsonObject(with: data!, options: [])
print("json:", result)
} catch let jsonError {
print("error:", jsonError.localizedDescription)
}
}
.resume()
The result I got:
<NSHTTPURLResponse: 0x600000921320> { URL: http://localhost:5000/api/accounts/eca9c1b05fb24ca192afe370aa5a1965 } { Status Code: 422, Headers {
"Content-Length" = (
350
);
"Content-Type" = (
"application/problem+json; charset=utf-8"
);
Date = (
"Thu, 10 Jun 2021 15:59:29 GMT"
);
Server = (
Kestrel
);
} }
That weird when it returns 422 while my call on Postman works well. Thanks for any advice!

Related

Using Swift with URLSession works with GET and PUT, but it gives error 405 Method Not Allowed when I use POST

I develop an iOS app using Swift.
I use the following method below to access an login ENDPOINT with PUT method.
let loginData = LoginModel("myUser","myPassword")
var loginClassJson:Data?
do{
loginClassJson = try JSONEncoder().encode(loginData)
} catch {
fatalError("Unable To Convert in Json")
}
let completeUrl = URL(string: RESconstantes.URL_PRINCIPAL_TREINAGEDAVE + "/login" )!
var request = URLRequest(url: completeUrl)
let myConfig = URLSessionConfiguration.default
let base64LoginString = EndpointController.getBase64StringLoginWithUserAndPasswordV2()
myConfig.httpAdditionalHeaders = ["Authorization" : base64LoginString]
request.httpMethod = "PUT"
request.setValue("\(String(describing: loginClassJson!.count))", forHTTPHeaderField: "Content-Length")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = loginClassJson
let sessionDelegate = SessionDelegate()
let urlSession = URLSession(configuration: myConfig, delegate: sessionDelegate, delegateQueue: OperationQueue.main)
let task = urlSession.dataTask(with: request as URLRequest, completionHandler: {
(data, response, error) in
if let error = error{
print("errorX: ")
print(error)
return
}
if let data = data{
let returnData = String(data: data, encoding: String.Encoding.ascii)
print("dataX: ")
print(returnData)
}
if let response = response{
print("responseX: ")
print(response)
}
})
task.resume()
print("END")
This is my URLSessionDelegate class
class SessionDelegate:NSObject, URLSessionDelegate
{
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: #escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
// usado para fazer o bypass na autenticaĆ§Ć£o self-signed do certificado do servidor
// We've got a URLAuthenticationChallenge - we simply trust the HTTPS server and we proceed
print("start didReceive challenge 1")
if true {
print("didReceive challenge 2")
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}else{
completionHandler(.performDefaultHandling, nil)
}
}
It works perfectly for me, but now I try to create a code to access another ENDPOINT with POST method
let resDadoModel = ResDadoModel.getResenhaById(1)
let jsonRequestUploadResenha = ResDadoModel.createMockJsonObjectResenhaDados(resDadoModel)
let json: [String: Any] = jsonRequestUploadResenha
guard let jsonData:Data = try? JSONSerialization.data(withJSONObject: json) else {
print("guard jsonData error")
return
}
let completeUrl = URL(string: RESconstantes.URL_PRINCIPAL_TREINAGEDAVE + "/validaResenha" )!
var request = URLRequest(url: completeUrl)
let myConfig = URLSessionConfiguration.default
let base64LoginString = EndpointController.getBase64StringLoginWithUserAndPasswordV2()
myConfig.httpAdditionalHeaders = ["Authorization" : base64LoginString, "Content-Type":""]
request.httpMethod = "POST"
request.setValue("\(String(describing: jsonData.count))", forHTTPHeaderField: "Content-Length")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
let sessionDelegate = SessionDelegate()
let urlSession = URLSession(configuration: myConfig, delegate: sessionDelegate, delegateQueue: OperationQueue.main)
let task = urlSession.dataTask(with: request as URLRequest, completionHandler: {
(data, response, error) in
if let error = error{
print("errorX: ")
print(error)
return
}
if let data = data{
let returnData = String(data: data, encoding: String.Encoding.ascii)
print("dataX: ")
print(returnData)
}
if let response = response{
print("responseX: ")
print(response)
}
})
task.resume()
print("END")
But the code that I use to access the ENDPOINT called "validaResenha" is not working properly, I get a 405 method not allowed error.
I get the following response data
<NSHTTPURLResponse: 0x600002028560> { URL: https://my_url_endpoint/api/spservicos/v1/validaResenha } { Status Code: 405, Headers {
Allow = (
"POST, OPTIONS"
);
"Cache-Control" = (
"no-cache=\"set-cookie, set-cookie2\""
);
Connection = (
"Keep-Alive"
);
"Content-Language" = (
"en-US"
);
"Content-Length" = (
0
);
"Content-Type" = (
"text/plain"
);
Date = (
"Thu, 23 Dec 2021 23:16:21 GMT"
);
Expires = (
"Thu, 01 Dec 1994 16:00:00 GMT"
);
"Keep-Alive" = (
"timeout=10, max=100"
);
"Set-Cookie" = (
"LtpaToken2=L6DEf/sqCSjiI1rePW3wEWZo40oNAsxmNVBNTpIRm3FZZRSSgaqmUTDYdjTq2PNE4+FhiIOKw7Xzuta4+LpD3cUB8QKZQ/KVom/rFFQ50XNkpQezmgMlgsmDDgtodRxVU5eyo1P1NP6r/3M55eY4HkeD583kXQB3/+EH3dIryo0ii6Jn6PrxaspX5noEo0eSt+yF2AylLdU66fCcSMJw7LCrB8Tulna4xHe4Nb9i+O5z2mnTXoIgbozDGuXfS6Y20zPrsaN62Bx1X/nySf1luf1QMhrt6P4SPF6GVudm0s/Db9dS0b444kJA4kMSJ0NbZ2khMzV1zSg3eZY6xZg2kidV8Qczpe5bL2/DNrPQY/CrUo8wcdFE1ebfxDcVrjv3G+nH6uKOPWtbcHHx9Wp1gvHLxj3cJ5MP43AzxW/7GXPA7QlsmlquxW1Ck7OypsP2hrYCvCWubjGdM51cg8uqhIonI+uXRO6BlcXIsPOfpR+LbQfDNo+9vzXzB+CZKZmYnBX63ffWhX09Cr+Ua0a2Sw8mOcE5jXImlO49+ak0FHPkiiaSABzuOl6ALYg9J6LCxjm6MC9bKd7KbMPueJI/ugVeMyphQwss5AHxic8fVmo+7/XNRT6zr4I/01N8xFQsqrvx5+i2AhxWO1bdDKmpZQLPoTHMD7TPcFBkwDXLVqXPXkpkcGvg3mI8ssKOOlxwJT7/SETcqrCY5O8Yr505qdeZiNIj4kjKiLoLuNpE+ZI=; Path=/"
);
} }
Anyone has an idea why I was receiving a 405 error method not allowed? The POST method works for me if I use POSTMAN. It works if I use PUT or GET endpoints with Swift code, but it fails if I try to use endpoints with POST method in Swift.
I see something strange, the "Content-Type" is defined as text/plain in the response, but I set it as "application/json". I don't understand why the config was not being set.
If I call it via POSTMAN, it works, but for some reason I don't know why it not works when I use Swift.
--- EDIT ---
After #matt suggestion, I use Postman to generate the Swift code.
I copy and paste the Swift code to my project, this is the code:
var semaphore = DispatchSemaphore (value: 0)
let parameters = "{ \n \"token\":\"MY_TOKEN\",\n \"resenha\": {\n \"codAP\":\"353750303020001\",\n \"codPropriedade\":\"0\",\n \"cpfVeterinario\":\"01787568814\",\n \"coordGeoLat\": \"37.421565\",\n \"coordGeoLong\": \"-122.084\",\n \"cpfCnpjProdutor\": \"89058500810\",\n \"dataNascimentoAnimal\": \"01/08/1981\",\n \"fotos\": null,\n \"graficas\": null,\n \"id\": \"1\",\n \"idComposicaoPelagem\": \"50\",\n \"idCorOlhoDir\": \"39902\",\n \"idCorOlhoEsq\": \"39902\",\n \"idEspecie\": \"5\",\n \"idPelagem\": \"6\",\n \"idRaca\": \"34\",\n \"idResenhaAnterior\":\"0\",\n \"idSexo\": \"2501\",\n \"machoCastrado\": \"N\",\n \"microChipAnimal\": \"123456989012377\",\n \"microchipMae\": \"\",\n \"nomeAnimal\": \"MACADANIAS111\",\n \"numeroAssocRaca\": \"\",\n \"numeroPassaporte\": \"\",\n \"outrasCaracteristicas\": null,\n \"quantAnimaisEq\": \"05\",\n \"quantAnimaisAs\": \"0\",\n \"quantAnimaisMu\": \"02\",\n \"retifica\": false\n }\n}"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string: "https://MY_ENDPOINT/validaResenha")!,timeoutInterval: Double.infinity)
request.addValue("Basic THIS_IS_BASIC_AUTH_VALIDATION", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("JSESSIONID=0000_B1PZRSVcyzEkDUkMxvk9ig:18jgnbg8n; LtpaToken2=q9JsIHVBKPsCYKGRohXJAKnXED3HRXXGlaswzYpnPSLS0B+c/WbiW+QcUMwmw/8xcb7VL1bVvbUh0ZAvMR3TNcGudWUkg9f0z5K0n0P2pJ5Frte6trqVLhPoKuI5E7zwC3Yg+XCsPBNFy0aukkrWNiCWAqbyGI3nir6UuX5qLER4H+bEYfk4cFw58eHGSIN/FTVjH7WW7aEAfkYNXxWzSDnNVJDtihZVXw+oJSfe74Vz8Scv33cPPZH2W74KvKwj09FOo+EJsvFcC2aDUQclYqwuo91HIaIpqcYb17cSCX95xn9KHErlC48M1bU03txKaDVcmUrOCrveCs7pVPNCz066cil5bzjXeYlXDlmUw5MT45Zgg8EmaJ9gi+iC2zPCU+W088OGEriphXpto40ww3irTN9rtnhIppB5U+drRFW6u25UmDkAjx899TNzC/XsJqkRXn9GinQv6xiD+Axnv3AgudQZBGyeYcNNJDRfA+jzbr6HE1NuNSkxY6aP1OvCLGkNDSA16chO7f4IjjR9jkvDH2m3+ajxa7as1rVNK9R0HHcZJLExvOJn3sJ1LKDwMNPTDjKGPLuWOVwTPQL2pzIitLjkeyx8A2Qcqo5p8U/+aa11Z/x8WA0bQRscZLWMtEHE6WLnHFqBaylCAzARF0Y5cOI/TYCW2xd99ux2WaJnumVlskr2uNCWdwSMOp78gvmzdmonQUH0Ko/k4wa8HcJPyMV5NK52gArIyGmeKXo=", forHTTPHeaderField: "Cookie")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
semaphore.signal()
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
print("end")
But I got now a 401 error. For some reason the basic Auth is not being accepted by the code or by the server.
I checked the user and password and they are correct.
I find out the fix for my problem.
I was using "http://MY_ENDPOINT/validaResenha" in my constants file instead of using "https://MY_ENDPOINT/validaResenha".
After add the "s" to "http" letter (it becomes "https") everything starts to work for me.
The strange part is that GET and PUT methods works fine because of the redirect from HTTP to HTTPS, but in the case of POST calls, I got this error.
It's fixed now.
iOS block HTTP use HTTPS or add to your Info.plist file

How can I make a POST Request in Swift with parameters using URLSession

I have a post request that I want to make using URLSession.
The post request looks like this:
curl -X POST 'https://smartdevicemanagement.googleapis.com/v1/enterprises/privatekey/devices/devicekey:executeCommand' -H 'Content-Type: application/json' -H 'Authorization: authtoken' --data-raw '{
"command" : "sdm.devices.commands",
"params" : {
"commandName" : "cmdValue"
}
}'
As this is a POST request, I want to only decode if the response is an error message.
Here is the code I currently have:
guard let url = URL(string: "https://smartdevicemanagement.googleapis.com/v1/enterprises/\(project_id)/devices") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("token", forHTTPHeaderField: "Authorization")
let cmdParams: [String: String] = ["command":"sdm.devices.commands", "params" : ["commandName": "cmdValue"]]
do {
request.httpBody = try JSONSerialization.data(withJSONObject: cmdParams)
} catch let error {
print(error.localizedDescription)
}
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard error == nil else {print(error!.localizedDescription); return }
guard let data = data else {print("empty data"); return }
The cmdParams are throwing an error, so I'm not sure how to structure the params request properly, a successful POST will result in the API returning {} an unsuccessful request will return some error.
How can I adjust my code to get this working?
You need to encode the JSON string as data. Then you can add it as the httpBody. Don't forget to add the token to the request.
// Encode your JSON data
let jsonString = "{ \"command\" : \"sdm.devices.commands\", \"params\" : { \"commandName\" : \"cmdValue\" } }"
guard let jsonData = jsonString.data(using: .utf8) else { return }
// Send request
guard let url = URL(string: "https://smartdevicemanagement.googleapis.com/v1/enterprises/\(project_id)/devices") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = jsonData
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("token", forHTTPHeaderField: "Authorization") // Most likely you want to add some token here
// request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
// Handle HTTP request error
} else if let data = data {
// Handle HTTP request response
} else {
// Handle unexpected error
}
}
task.resume()
You could try using "urlencoded" to encode your request body. Here is my test code:
(note, since I do not have a paid subscription to this service I cannot fully test my code)
struct ContentView: View {
let project_id = 123 // <-- adjust to your needs
var body: some View {
Text("testing")
.onAppear {
if let url = URL(string: "https://smartdevicemanagement.googleapis.com/v1/enterprises/\(project_id)/devices") {
doPOST(url: url)
}
}
}
func doPOST(url: URL) {
var request = URLRequest(url: url)
request.httpMethod = "POST"
// try urlencoding
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("token", forHTTPHeaderField: "Authorization") // <-- your api "token" here
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)!
components.queryItems = [
URLQueryItem(name: "command", value: "sdm.devices.commands"),
URLQueryItem(name: "params", value: "{ \"commandName\" : \"cmdValue\" }")
]
if let query = components.url!.query {
print("--> query: \(query)")
request.httpBody = Data(query.utf8)
}
let task = URLSession.shared.dataTask(with: request) { data, response, error in
showResponse(data) // <-- for debuging
guard error == nil else { print("--> error: \(error)"); return }
guard let data = data else { print("empty data"); return }
}
task.resume()
}
func showResponse(_ data: Data?) {
if let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers), let jsonData = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) {
print("\n---> response: " + String(decoding: jsonData, as: UTF8.self))
} else {
print("=========> error")
}
}
}
If this does not work, have a look at this doc:
https://developers.google.com/nest/device-access/reference/rest/v1/enterprises.devices/executeCommand
In particular: The URL uses gRPC Transcoding syntax. It may be relevant.

Using POST and Auth with Firebase Database and Swift

I need to use REST Api on my iOS app to post/retrieve data from my server. The app is set up with a key generator, which gets me a id token, and then I format my http request with the id. I know something about my url request is wrong, I just don't know what, but I get back a status code 400 whenever I run this. Any ideas where I went wrong?
func postToFB() {
let preURL = "https://myapp.firebaseio.com/"
let url = URL(string: "\(preURL)\(code)/calculatorDisplay.json?auth=\(idToken)")!
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "PUT"
let parameters: [String: Any] = [
"field1": env.field1,
"field2": env.field2
]
request.httpBody = parameters.percentEncoded()
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data,
let response = response as? HTTPURLResponse,
error == nil else { // check for fundamental networking error
print("postCalcDataButtons error", error ?? "Unknown error")
return
}
guard (200 ... 299) ~= response.statusCode else { // check for http errors
print("postCalcDataButtons = statusCode should be 2xx, but is \(response.statusCode)")
print("postCalcDataButtons response = \(response)")
return
}
let responseString = String(data: data, encoding: .utf8)
print("postCalcDataButtons responseString = \(String(describing: responseString))")
}
task.resume()
}
Here's the extensions that make the above code work:
extension Dictionary {
func percentEncoded() -> Data? {
return map { key, value in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
.data(using: .utf8)
}
}
extension CharacterSet {
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]#" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return allowed
}()
}
Here's the response from the server:
<NSHTTPURLResponse: 0x60000110a0a0> { URL: https://calculonapp.firebaseio.com/zlwxrx/calculatorButtons.json?auth=authCode } { Status Code: 400, Headers {
"Access-Control-Allow-Origin" = (
"*"
);
"Cache-Control" = (
"no-cache"
);
Connection = (
"keep-alive"
);
"Content-Length" = (
77
);
"Content-Type" = (
"application/json; charset=utf-8"
);
Date = (
"Fri, 21 Aug 2020 21:16:43 GMT"
);
Server = (
nginx
);
"Strict-Transport-Security" = (
"max-age=31556926; includeSubDomains; preload"
);
} }
I was able to fix this issue by changing the http method when writing data to firebase to "PATCH", then adding JSONSerialization to encode my my upload before running the URLSession...this is the code I used:
if let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []) {
URLSession.shared.uploadTask(with: request, from: jsonData) { (data, response, error) in
if let httpResponse = response as? HTTPURLResponse {
completion(httpResponse.statusCode)
}
}
.resume()
}
You can keep in the guard statements while you test to catch for http error codes and report them to you, but once my code was working I removed them.

401 Forbidden when sending email with Swift and Mailgun

I have the following code but consistently get error 401 forbidden when attempting to run it:
func email() {
let session = URLSession.shared
let request = NSMutableURLRequest(url: NSURL(string: "https://api.mailgun.net/v3/{edited_out}/messages")! as URL)
request.httpMethod = "POST"
let data = "from: Swift Email <(test#test.com)>&to: [my_email_address#gmail.com,(my_email_address#gmail.com)]&subject:Hello&text:Testing_some_Mailgun_awesomness"
request.httpBody = data.data(using: String.Encoding.ascii)
request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.setValue("key-{edited_out}", forHTTPHeaderField: "api")
let task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.url!)")
print("response = \(response)")
let httpResponse = response as! HTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
The error is:
url = https://api.mailgun.net/v3/{edited_out}/messages
response = <NSHTTPURLResponse: 0x600000226a20> { URL: https://api.mailgun.net/v3/{edited_out}/messages } { status code: 401, headers {
Connection = "keep-alive";
"Content-Length" = 9;
"Content-Type" = "text/html; charset=utf-8";
Date = "Thu, 29 Dec 2016 21:22:46 GMT";
Server = nginx;
"Www-Authenticate" = "Basic realm=\"MG API\"";
} }
response code = 401
If I send such a request via curl with my credentials it works fine.
Any ideas?
You need to set the uesrname and the password.
Something like this:
request.setValue("Basic \(base64Credentials)", forHTTPHeaderField: "Authorization")
and base64Credentials is the :
let credentials= String(format: "%#:%#", username, password)
let base64Credentials= credentials.data(using: String.Encoding.utf8)!
Finally got it working with the following code, if it helps anyone else:
func email() {
let session = URLSession.shared
let request = NSMutableURLRequest(url: NSURL(string: "https://api.mailgun.net/v3/{edited_out}/messages")! as URL)
request.httpMethod = "POST"
let credentials = "api:key-{omitted}"
request.setValue("Basic \(credentials.toBase64())", forHTTPHeaderField: "Authorization")
let data = "from: Swift Email <(test#test.com)>&to: [my_email_address#gmail.com,(my_email_address#gmail.com)]&subject:Hello&text:Testing_some_Mailgun_awesomness"
request.httpBody = data.data(using: String.Encoding.ascii)
let task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.url!)")
print("response = \(response)")
let httpResponse = response as! HTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
extension String {
func fromBase64() -> String? {
guard let data = Data(base64Encoded: self) else {
return nil
}
return String(data: data, encoding: .utf8)
}
func toBase64() -> String {
return Data(self.utf8).base64EncodedString()
}
}
So I guess the answer from William would have worked with:
let base64Credentials = credentials.data(using: String.Encoding.utf8)!.base64EncodedString()
Instead of:
let base64Credentials = credentials.data(using: String.Encoding.utf8)!

Error Domain=NSCocoaErrorDomain in swift

When I send data to the server Post is perfectly fine and complete works but an error
erro return :
B
Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value.}
return data from server perfectly
data =
[ {
"$id": "1",
"Id": 14,
"Source": 23,
"Destination_": 21,
"Exclusive": false,
"AdultPrice": "70766",
"ChildPrice": "77076",
"BabyPrice": "54109",
"VetranPrice": "118664",
"DepartureDate": "1997-09-25T00:00:00",
"ArrivalDate": "2001-03-24T00:00:00",
"TrainTypeId": 1,
"NumberofSeats": 153 } ]
You can tell what is the reason?
let request = NSMutableURLRequest(URL: todosUrlRequest)
request.HTTPMethod = "POST"
request.setValue("application/json; charset=uft-8", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData
//3
let newTodo = [
"NumberOfPassenger": tedat,
"Source": cityIDSource,
"Destination": cityIDDestination,
"DapartureDate": raftDate,
"TicketType": typeTrainID,
"TravelType": 6,
"CloseDoor": copeqtar
]
print(newTodo)
//4
let jsonTodo: NSData
do {
jsonTodo = try NSJSONSerialization.dataWithJSONObject(newTodo, options: [])
request.HTTPBody = jsonTodo
} catch {
print("Error: cannot create JSON from todo")
return
}
print(jsonTodo)
request.HTTPBody = jsonTodo
//5
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(request) {
(data, response, error) in
// statusResponse
if let HTTPResponse = response as? NSHTTPURLResponse {
let statusCode = HTTPResponse.statusCode
if statusCode == 200 {
print(response)
//6
print(data)
if data != nil {
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
guard let responseData = data else {
return
}
self.dataRecive = responseData
print("currect")
}else{
print("error calling POST on /todos/1")
print(error)
}
}
dispatch_async(dispatch_get_main_queue()){
actInd.stopAnimating()
}
}
task.resume()