Home > Blockchain >  How can I pass parameters in an HTTP Post request in Swift?
How can I pass parameters in an HTTP Post request in Swift?

Time:03-26

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

  • Related