Am working on a simple Swift test app which just calls Perl script on my server. Right now I just want to send over a username and id, and get them back in a JSON response. Nothing more, am still in the learning stage.
But no matter which way I try, I cannot successfully send the two parameters in my URLRequest.
In the sample below, you'll see I try to send them in the main url, I've tried to add them as forHTTPHeaderFields, but the response I get back in my URLSessionDataDelegate is always:
data is {"userid":"","username":""} JSON Optional({ userid = ""; username = "";
let file = File(link: "http://example.com/cgi-bin/swift.pl?username=John&userid=01", data: "hello")
uploadService.start(file: file)
And within my instance of URLSession I have tried:
// From one of my view controllers I create a File struct
// from a YouTube lesson. Eventually I want to send a file.
// So for now am using just *Hello*:
let uploadTask = UploadTask(file: file)
let url = URL(string: file.link)!
let uploadData = Data(file.data.utf8)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField:"Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("John", forHTTPHeaderField: "username")
request.addValue("01", forHTTPHeaderField: "userid")
uploadTask.task = uploadSession.uploadTask(with: request, from: uploadData)
uploadTask.task?.resume()
Every other part of the Swift test works, I get a response and data in my URSessionDelegate, and no errors. Obviously I just can't figure out how to properly send over the two parameters. For the record:
the Perl script below does work from a linux command line, or when called from a web browser.
If I hardcode the return repsonse in the perl script below, I do recieve it in the my URLSessionDelegate, so I know that I am parsing it correctly
As well, my server's error log shows that $header1 and $header2 never get initialized.
#!/usr/bin/perl -w
use strict;
use CGI;
use JSON;
my $q = new CGI;
my $header1 = $q->param("username");
my $header2 = $q->param("userid");
print $q->header('application/json');
my %out = (username=>"$header1", userid=>"$header2");
my $json = encode_json \%out;
print $json;
exit(0);
CodePudding user response:
You are sending the parameters username and userid as http header values. Your perl scrip is expecting them a query parameters. So first create a URLComponents object, than add query items and finally create your url.
Try this:
let uploadTask = UploadTask(file: file)
var urlComponents = URLComponents(string: file.link)!
let queryItems = [URLQueryItem(name: "username", value: "John"),
URLQueryItem(name: "userid", value: "01")]
urlComponents.queryItems = queryItems
let url = urlComponents.url!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField:"Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
uploadTask.task = uploadSession.uploadTask(with: request, from:
uploadData)
uploadTask.task?.resume()
Have a look at this Post that shows how to add query parameters using an extension to URL
CodePudding user response:
In these two lines:
request.addValue("John", forHTTPHeaderField: "username")
request.addValue("01", forHTTPHeaderField: "userid")
You are adding those as http headers and not url query parameters.
To add query parameters, you need to convert to URLComponents first and then convert back: https://developer.apple.com/documentation/foundation/urlcomponents
var urlComponents = URLComponents(string: file.link)!
urlComponents.queryItems = [
URLQueryItem(name: "username", value: "name"),
URLQueryItem(name: "userid", value: "id")
]
let newURL = urlComponents.url!
//use the newURL
CodePudding user response:
Just create a dictionary with data
let parameterDictionary = ["username" : "John", "userid": "01"]
Then create httpBody object using
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameterDictionary, options: []) else { return }
Then simply add that body in your request parameter
request.httpBody = httpBody