How to set HTTPBody? - ios

In Swift I'm trying to make a post request (using the NSURLSession) to sign in a user to a WebAPI web services.
The Url is www.myurltest.com/Token and I must pass the following string as POST body:
grant_type=password&username=MyUsername&password=MyPassword.
So in Swift I've make:
let session = NSURLSession.sharedSession();
let url = NSURL(string:"www.myurltest.com/Token");
let request = NSMutableURLRequest(URL: url!)
request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
Now I want to set the POST body (that is a string) but I don't know how:
request.HTTPBody = ?????
Thanks.

You're almost there, you just need to turn the string into an NSData object. If your string is in a variable named body, your code will look like request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)

Related

"HTTP Status 400 - Bad Request - The request sent by the client was syntactically incorrect"?

I've done a http request with post parameters so many times, and I have now so many of them working just fine, I don't know why this one is not
this is the code
let url = NSURL(string: "bla bla lba")
let request = NSMutableURLRequest(URL: url)
let body = "id=\(requestClient!.id!)"
print("body = \(body)")
request.HTTPBody = body.dataUsingEncoding(NSASCIIStringEncoding)
request.HTTPMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "content-type")
let session = NSURLSession.sharedSession()
let task1 = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
the server expects a form parameter named id and its value is long
when I print the id from swift (as you can see the code), I get this
id=1453045943881.0
and i get this error
HTTP Status 400 - Bad Request - The request sent by the client was syntactically incorrect.
sounds like the server said the request is not correct, but where is the wrong?
this is the server
#Path("/checkForResponses")
#POST
public Response checkForResponeses (#FormParam("id") long id) {

Differences between Using NSJSONSerialization.dataWithJSONObject and dataUsingEncoding to make up the HTTP body in Swift

I have seen two kinds of methods to make up the HTTP body.
First one is:
let url = NSURL(string: "http://example.com")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
let postString = "id=13&name=Jack"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
Second one is:
let url = NSURL(string: "http://example.com")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
let params = ["id":"13", "name":"Jack"] as Dictionary<String, String>
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
When I directly print out the request.HTTPBody the data is different. So I am wondering are there any differences between these two methods in terms of the implementation of the server side? Assuming I'am using PHP.
there're two format data.
in code using postString.dataUsingEncoding it will send data in urlencoded format. In client you must set request's Content-Type header to "application/x-www-form-urlencoded" or something like "application/x-www-form-urlencoded charset=utf-8"
in code using NSJSONSerialization.dataWithJSONObject it will send data in json format. In client you must set request's Content-Type header field to "application/json"
I'm iOS dev so I don't know about format's effect to server side PHP. to answer your question you must find difference between application/x-www-form-urlencoded and application/json format in server side

Put request IOS

I try to update a object in the database trough a API call. I do this action with a PUT request. A Post request was already made and is working fine. I thought it is just copy paste...
The API part works fine because if I execute the following curl command than it updates the row I wanted in the database
$ curl -H 'Accept: application/json' -i -X PUT -d 'UserLogin=Ub0D&EndDate=2014-01-17 00:00:00.0000000&Sport=Fietsen&Distance=1000&Duration=10&Achieved=true&DateCreated=2015-05-09 12:01:00.000000' http://localhost:8089/api/goal/ub0d -k -u ub0d:test123
But now the part in swift gives me a bad request error (400)...
This is my code
var url : NSURL
url = NSURL(string: _apiUrl + connectToApi(apiCall) + String("\(AccountRepository.Instance.getCurrentUserName())"))!
let request = NSMutableURLRequest(URL: url)
if postString != nil {
let postData : NSData = ("UserLogin=Ub0D&EndDate=2014-01-1700:00:00.0000000&Sport=Fietsen&Distance=1000&Duration=10&Achieved=true&DateCreated=2014-01-1700:00:00.0000000").dataUsingEncoding(NSUTF8StringEncoding)!
// create the request
request.HTTPMethod = "PUT"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "content-type")
request.setValue("application/json", forHTTPHeaderField: "Content-type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.HTTPBody = postData
}
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: true)!
I'm really stuck on it:(
You request can't have two different content types at the same time:
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "content-type")
request.setValue("application/json", forHTTPHeaderField: "Content-type")
The data you are sending are obviously not JSON, so I guess you want only
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "content-type")
and remove the "application/json" line.
There is also a difference between your date formats:
CURL
EndDate=2014-01-17 00:00:00.0000000
Swift
EndDate=2014-01-1700:00:00.0000000
Note the missing space between date and time, probably should be URL encoded (+):
EndDate=2014-01-17+00:00:00.0000000
In general, most REST APIs send error messages in response body, so it is always good to log the response for failed requests.

JSON NSURLRequest with credentials

I have an api in my swift app that needs some extra authorization. There are some examples provided by the service but none in swift.
My Code:
let request = NSURLRequest(URL: NSURL(string: "https://www.kimonolabs.com/api/au4sl00w?apikey=iFotcJDm95fB6Ua7XiZRDZA0jl3uYWev")!)
Example in Python
import urllib2
request = urllib2.Request("https://www.kimonolabs.com/api/au4sl00w? apikey=iFotcJDm95fB6Ua7XiZRDZA0jl3uYWev", headers={"authorization" : "Bearer A5ve02gq40itf0eoYfT5ny6drZwcysxx"})
contents = urllib2.urlopen(request).read()
Example in Ruby
require 'rest_client'
response = RestClient.get('https://www.kimonolabs.com/api/au4sl00w?apikey=iFotcJDm95fB6Ua7XiZRDZA0jl3uYWev', {'authorization' => 'Bearer A5ve02gq40itf0eoYfT5ny6drZwcysxx'});
print(response);
Example in R
library('RCurl')
library('rjson')
json <- getURL('https://www.kimonolabs.com/api/au4sl00w?apikey=iFotcJDm95fB6Ua7XiZRDZA0jl3uYWuc',
httpheader = c(authorization='Bearer A5ve02gq40itf0eoYfT5ny6drZwcysxx'))
obj <- fromJSON(json)
print(obj)
So, how can I do this in Swift?
Modified answer from: "How to make an HTTP request + basic auth in Swift".
I believe it would look something like this (and assuming your API_ID is au4sl00w) :
let token = "yourToken"
// create the request
let url = NSURL(string: "https://www.kimonolabs.com/api/au4sl00w?apikey=iFotcJDm95fB6Ua7XiZRDZA0jl3uYWev")
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "GET"
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
And be sure to create a new access token, now that this one is public :)

iOS Missing grant_type

I'm getting {"error_description":"Missing grant_type parameter value","error":"invalid_request"} when trying to request access token for the first time. My code is below:
let params : [String : String] =
["client_id" : clientID,
"client_secret" : secret,
"redirect_uri" : redirectURL,
"code" : code,
"grantType" : "authorization_code"
]
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("aapplication/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.addValue("\(request.HTTPBody!.length)", forHTTPHeaderField: "Content-Length")
What might be the problem? Thank you in advance.
Wow, I don't want to sound harsh, but there are multiple issues with this code.
You are not sending grant_type, but you do send grantType.
You are encoding the post body as application/json, but you are setting the Content-Type to be aapplication/x-www-form-urlencoded which seems to be a misspelling of application/x-www-form-urlencoded.
So two possible spelling issues and a content type mismatch.
Work out if you need to send application/x-www-form-urlencoded or application/json. Format the data and set the content type as needed.
Double check the spelling of everything.

Resources