I am making an iOS app that makes requests to an API. The request is in this format:
curl -X PUT -H "Content-Type: application/json" -d '{"username":"blabla#hotmail.com","password":"blabla"}' "https://server.mywebsite.com/login"
The API can only accept single-quoted strings in the body but I can't make a string with single quotes in Swift without it adding backslashes and making the string unreadable by the API.
"\'{\"email\": \"blabla#hotmail.com\", \"password\": \"blabla\"}\'"
Is there a way I can pass this string in Swift without the backslashes? Or is there a String or JSON encoding that is in that format?
The single quotes in your curl are required just in the Unix shell (to quote the double quotes on the command line), they are not actually transmitted to the server. The server just sees this JSON payload:
{"username":"blabla#hotmail.com","password":"blabla"}
So in your Swift API request you can remove the single quotes from your string:
let auth = "{\"email\": \"blabla#hotmail.com\", \"password\": \"blabla\"}"
Is there are way to avoid the escaping of the double-quotes here? No. In Swift you can't switch between ' and " like you can in say Python. Nor does it have """.
Since it is easy to make quoting errors when building the JSON on your own, you may want to use JSONSerialization instead, like so:
let jsonAuth = [ "email": "blabla#hotmail.com",
"password": "blabla" ]
let jsonData = JSONSerialization.data(withJSONObject: jsonAuth)
let jsonString = String(data: data, encoding: .utf8)
Related
I am trying to get the file contents on Box through their API in Swift.
curl -L https://api.box.com/2.0/files/file_id/content -H "Authorization: Bearer access_token"
returns the right contents, but
curl https://api.box.com/2.0/files/file_id/content -H "Authorization: Bearer access_token"
does not.
So the "-L" part seems to be critical.
So far I have
let headers = [
"grant_type": "client_credentials",
"Authorization": "Bearer \(token)",
"scope": "public"
]
Alamofire.request("https://api.box.com/2.0/files/file_id/content", headers: headers).responseJSON { responseFile in
if let dataFile = responseFile.result.value {
print("JSON: \(dataFile)")
}
}
How can I add the "-L" part to this?
The overall structure should be correct since I can successfully get the metadata for the file by removing "/content" from the url.
According to curl manual -L/--location argument means
If the server reports that the requested page has moved to a different location (indicated with a Location: header and a 3XX response code), this option will make curl redo the request on the new place.
So, I guess, you must check response statusCode and if it will be 3xx you need to handle redirects. Check Alamofire framework documentation about that.
Also good to read about fundamentals Handling Redirects and Other Request Changes
Based on a-a-m's answer, I got it working with the following code.
Note that I used responseString instead of responseJSON for the second request since the response was in a file format rather than in JSON format.
Alamofire.request("https://api.box.com/2.0/files/\(file_id)/content", headers: headers).responseJSON { responseFile in
if let newUrl = responseFile.response?.url {
print("new link: \(newUrl)")
//make another request using the redirection url
Alamofire.request(newUrl).responseString { content in
let filecontent = content.result.value
print (filecontent)
self.contentText.text = filecontent
debugPrint(contents)
}
}
}
}
I generated a json using NSJSONSerialization.This is my code:
// parameters is `Dictionary<String, AnyObject>?`
let json = try! NSJSONSerialization.dataWithJSONObject(parameters!, options: NSJSONWritingOptions.init(rawValue: 0))
request.HTTPBody = json
But my server received this:
"{login:23232432434,mobile_captcha:,password:22e233434}"=>"[FILTERED]"
It seems server takes the whole json as a key and I think this because of that ".Maybe there is other reasons,please help me!
Those aren’t brackets; they’re (double) quotes/quotation marks. In valid JSON, quotation marks inside strings must be escaped with \, e.g. "Hello \"World\"".
The Web service you’re using is returning invalid JSON.
http://jsonlint.com is a useful resource to validate JSON strings.
I'm sending a POST request to an api using Alamofire and SwiftyJSON and getting a weird issue where it seems Alamofire maybe automatically escaping forward slashes. Only one section of the JSON i'm sending to the server is having it's forward slashes escaped, and its a base64 image string.
I set some breakpoints and checked my local data on device and know that the data is fine and unescaped up until the point Alamofire sends off the request, but when it gets to the server, it is coming in escaped. Not sure if there is some flag I need to set to prevent this or something?
The Alamofire request:
Alamofire.request(.POST,
submitUrl,
parameters: ["data":completedBlob.object], //completedBlob is a SwiftyJSON object
encoding: .JSON ,
headers: self.submitHeaders
).responseJSON{ response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
guard json["error"].isExists() else{ callback?(success: false, jsonObject: nil);return}
let result = json
Settings.setAuthToken(self.db, token: self.authToken)
callback?(success: true, jsonObject: result)
}
case .Failure(let error):
print("An error occured processing request: \(error)")
print(response.result.value)
}
}
Base 64 string before Alamofire sends it off:
data:image/png;base64, forward slashes in data here are unescaped
Didnt paste the entire base64 string because its huge, but all of the forward slashes in the base64 string are escaped. Here is what the server receives:
{"inspector":"data:image\/png;base64,forward slashes in data here are escaped.
it seems its even encoding the media types
data:image/png;base64
Looked through Alamofire documentation, cannot find any mention of this issue, so i'm starting to feel like it might not be alamofire, but im not sure what else it could be?
Details: Running Xcode 7.3 | Swift 2.2 | Alamofire 3.30 | SwiftyJSON 2.3.1 | Both installed using Carthage.
Thanks guys!
Following this page (https://django-oauth-toolkit.readthedocs.org/en/latest/rest-framework/getting_started.html), I was able to setup OAuth for my django project.
The following curl command gives me a token to access resource.
curl -X POST
-d "grant_type=password&username=<user_name>&password=<password>"
-u"<client_id>:<client_secret>" http://localhost:8000/o/token/
However, when I send request using Alamofire, things are a bit strange. This is my code
Alamofire.request(.POST, url, parameters: parameters, encoding: .JSON)
.authenticate(user: client_ID, password: client_Secret)
where parameter is a dictionary
[
"password": <password>,
"grant_type": password,
"username": <username>
]
Using curl command, I can see from Django that request.POST.items() returns the list of parameters. However, using Alamofire, there is nothing. The parameters appeared in request.body instead!
This problem is driving me crazy. Any help will be grateful!
Thanks in advance.
Well, your curl command is posting as Content-Type: application/x-www-form-urlencoded format, whereas you are forcing to post as json (.JSON). For this reason the request has passed as application/json to your django and you are seeing the parameter in body instead of POST.items().
So remove this from your code encoding: .JSON.
I'm using HTTParty to send data to a remote API, however the API is complaining because the JSON being sent by HTTParty appears to be being escaped, and is thus deemed invalid.
Here's what I'm doing:
query = {"count"=>1,
"workspaces"=>
{123445=>
{"title"=>"Test Project",
"description"=>"",
"start_date"=>"2015-06-01T00:00:00.000Z",
"due_date"=>"2015-08-31T00:00:00.000Z",
"price_in_cents"=>8000,
"currency"=>"USD",
"status_key"=>130,
"custom_field_values_attributes"=>[],
"workspace_groups_attributes"=>
[{"created_at"=>"2015-07-13T11:06:36-07:00",
"updated_at"=>"2015-07-13T11:06:36-07:00",
"name"=>"Test Customer",
"company"=>true,
"contact_name"=>nil,
"email"=>nil,
"phone_number"=>nil,
"address"=>nil,
"website"=>nil,
"notes"=>nil,
"id"=>"530947",
"custom_field_values_attributes"=>[]}],
"id"=>123445}},
"results"=>[{"key"=>"workspaces", "id"=>123445}]}
Calling to_json on query escapes the JSON too:
"{\"count\":1,\"workspaces\":{\"123445\":{\"title\":\"Test Project\",\"description\":\"\",\"start_date\":\"2015-06-01T00:00:00.000Z\",\"due_date\":\"2015-08-31T00:00:00.000Z\",\"price_in_cents\":8000,\"currency\":\"USD\",\"status_key\":130,\"custom_field_values_attributes\":[],\"workspace_groups_attributes\":[{\"created_at\":\"2015-07-13T11:06:36-07:00\",\"updated_at\":\"2015-07-13T11:06:36-07:00\",\"name\":\"Test Customer\",\"company\":true,\"contact_name\":null,\"email\":null,\"phone_number\":null,\"address\":null,\"website\":null,\"notes\":null,\"id\":\"530947\",\"custom_field_values_attributes\":[]}],\"id\":123445}},\"results\":[{\"key\":\"workspaces\",\"id\":123445}]}"
Is this expected behavior to escape the JSON? Or I'm wondering if the hash I'm building for query is invalid for JSON purposes?
Any help would be greatly appreciated.
Calling to_json on query doesn't yield escaped JSON.
Try puts query.to_json to see that.
You see backslashes because #inspect method on String (and this method is called to display contents of variables to console) displays String enclosed in double quotes, and it has to escape quotes which are in the given string itself.
Your problem is probably not having proper Content-Type headers. You should do something like this:
result = HTTParty.post(url, body: query.to_json, headers: {'Content-Type' => 'application/json'})