This one is killing me! Long story short, I am running a Node.js server that communicates to a Mongo Database. I have been very successful with submitting data with HTTP POST(and see the results), but for the life of me I am failing with GET requests.
My code:
let url = NSURL(string: "http://*******/users/userlist")
let requestGet = NSMutableURLRequest(URL: url!)
var response: NSURLResponse?
requestGet.HTTPMethod = "GET"
requestGet.addValue("application/json", forHTTPHeaderField: "Accept")
NSURLConnection.sendAsynchronousRequest(requestGet, queue: NSOperationQueue.mainQueue())
{(response, data, error) in
println(NSString(data: data, encoding: NSUTF8StringEncoding))
}
I am able to step through the code above, but for some reason when I hit "NSURLConnection" Xcode completely ignores the 'println', which is somthing I cannot explain.
I know I'm doing something pretty stupid....
Related
I'd like to make multiple POST requests to a web server that I have got which inserts a new record in a table in my database. This will be repeated depending on the amount of exercises the user inputs.
I have a function for the POST request which is as follows.
func submitDetails(split_id:Int, day:String, name:String, set:String, rep:String)
{
var request = URLRequest(url: URL(string: "LINK OF WEB SERVICE")! as URL)
request.httpMethod = "POST"
let postString = "id=\(split_id)&day=\(day)&name=\(name)&sets=\(set)&reps=\(rep)"
print("Post string - \(postString)")
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest)
{
data, response, error in
if error != nil
{
print("error=\(String(describing: error))")
return
}
print("response = \(String(describing: response))")
let responseString = String(data: data!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
print ("responseString =\(String(describing: responseString))")
}
task.resume()
}
This is called within a loop,
for x in 0...MainMenuViewController.myVariables.day1NoExercise - 1
{
self.submitDetails(split_id: MainMenuViewController.myVariables.new_split_id, day: self.dayName.text!, name: self.exerciseName[x].text!, set: self.exerciseSets[x].text!, rep: self.exerciseReps[x].text!)
}
Currently, only the first exercise that the user inputs data for is inserted into the database. It seems like it is executing all the code too fast. I hope someone understands this and can help me out!
for API Calls always run asynchronous request
use background thread to help your application remain responsive
use compilation block to display error
show progress bar or something like that to let the user know that you are doing something
add Extra function to your server to allow bulk posting "Reduce http sessions "
Read :
https://medium.com/#sdrzn/networking-and-persistence-with-json-in-swift-4-c400ecab402d
https://medium.com/#sdrzn/networking-and-persistence-with-json-in-swift-4-part-2-e4f35a606141
Advise :
it's look like you taking your first steps with Swift/IOS so Just use http library like Alamofire to avoid all headache Like Queuing,Threading,Complitions Block .
https://github.com/Alamofire/Alamofire
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) {
Why aren't any results being printed?
I have been searching all over for an answer. I've tried many different example blocks of code. The print statements never fires unless an error is produced. For example: If I change the URL to "http" only with nothing else, I naturally get an error and it prints the error. However, any valid URL produces no result in the print statement.
func post()
{
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.thebeerstore.ca")!)
request.HTTPMethod = "POST"
let postString = "experiment"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString!)")
}
task.resume()
}
Edit: It works if I use a playground, but only in a playground.
In your application's Info.plist file, add the property App Transport Security Settings and under that, add Allow Arbitrary Loads and assign YES for it.
With the above settings in your Info.plist, the app should be able to load your http:// URLs as well
Note: I would recommend not to use the above settings in your
production build, it could result in security issues.
There is no good explanation for this, but having finally stuck this same problem code into my primary project, it now works perfectly ok. What changed??? Arrrrg! How many hours wasted and I still don't really know why it wasn't working outside of my primary app. Thanks for your help everyone.
Final code:
I do hope I can send over 100MB through a post request to be interpreted on the server side and store to the database. Haven't done this before. I'm a newbie.
func post()
{
let request = NSMutableURLRequest(URL: NSURL(string: "http://bruceexpress.com/database.php")!)
request.HTTPMethod = "POST"
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(stores, options: [])
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{
data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString!)")
}
task.resume()
}
Edit: Yes, you can post a huge block of data. Is this the correct way to do it? ( Forgive my silly questions, but I am recovering programming skills left over from 2001. I am a very outdated individual. )
Basically, what I have done is read all of the data on http://www.thebeerstore.ca, extracted every beer and its info and prices, and extracted every store and its info. I interpreted this data, converted it into a large JSON block, and sent it to my server to be interpreted by a php script which will store this data to a database.
Sound like the right thing to do, or is there a better way to fill the database?
I tried to send body in PUT request but the data is not received on backend
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "PUT"
let putBody = "bucket=\(bucket)&day=\(day)"
request.HTTPBody = putBody.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {(data, response, error) -> Void in
dispatch_async(dispatch_get_main_queue(), {() -> Void in
completion(data: data, response: response as! NSHTTPURLResponse, error: error)
})
})
task.resume()
The value of bucket (Int) is 2015040 and day (String) is day27. I tried making same request in Postman, the server received body data so there is nothing wrong with the server.
Is there any other way to set body of a request?
EDIT :
It's working perfectly if I change request method to POST in my request and server as well. So the question comes down to how to set body in PUT request?
I've just been dealing with this. Had the exact same issue where it was working perfectly fine with POST but not with PUT or PATCH requests. It seems that for PUT and PATCH requests, Swift is picky about the Content-Type header.
So try adding this:
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
This will work as long as your body is url style, so like this:
key=value&key=value&key=value
For those of you using JSON, just use application/json instead for the Content-Type.
I've tried lots of different things to recreate this curl request, and I'm going insane. If someone could help, I'd be very much appreciative.
curl -H "Content-Type: application/json" -X POST --data '[{"a": 4, "b": 5, "c": 6}]' \ -u username:password \ https://www.mywebsite.com
My latest attempt is:
let loginString = NSString(format: "%#:%#", username!, password!)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = loginData.base64EncodedStringWithOptions(nil)
var url: NSURL = NSURL(string: "www.mywebsite.com")!
var request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")
request.addValue("text/plain; charset=UTF-8", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
let bodyData = JSON(data!).rawString(encoding: NSUTF8StringEncoding, options: NSJSONWritingOptions.allZeros)
request.HTTPBody = bodyData?.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
if let tabBarVC : TabBarController = self.tabBarController as? TabBarController {
println(NSString(data: data, encoding: NSUTF8StringEncoding))
}
}
In this example, data is a dictionary ([String:String]) and JSON is form SwiftyJSON.
The above sends NSData to the server, which is encoded and the server doesn't like. The request is getting through, but the server can't read the data right. What do I need to do to exactly replicate the curl request above? I'm stuck!
Updated to reflect good responses below.
I did attempt to use application/json for content-type, but this returns the message:
{"status": "Internal error JSON uploads must be formatted as an array of objects", "code": 400, "version": "v1"}
It seems like progress if I use text/plain (as above) I get:
{"status": "Column a is missing", "code": 400, "version": "v1"}
Which I can't seem to figure out.
A couple of thoughts:
If nothing else, the line that says:
request.addValue("text/plain; charset=UTF-8", forHTTPHeaderField: "Content-Type")
Should be:
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
Your curl clearly states that the content type header was supposed to be JSON, so I'd set that accordingly.
Also, the line that says:
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Accept-encoding")
That's clearly not correct, either. I think you meant Accept not Accept-encoding, plus the server is undoubtedly not responding with a x-www-form-urlencoded response, anyway.
I would simply remove that line.
Your URL is missing the scheme (the http://), but I assume that was removed when editing your question, because I don't think it would work without that, but you assured us that the server did receive the request.
I'd suggest you consider a tool like Charles. Watch the request from curl and then again from your code. Compare and contrast and identify how they differ. Using this, you should be able to diagnose precisely what's going on and where the discrepancy rests.
You say:
The request is getting through, but the server can't read the data right.
If the problem persists, you should share with us how you know the request is getting through and what you mean by "can't read the data right."