HTTP Request in Swift with POST method
The key is that you want to:
- set the
httpMethod
toPOST
; - optionally, set the
Content-Type
header, to specify how the request body was encoded, in case server might accept different types of requests; - optionally, set the
Accept
header, to request how the response body should be encoded, in case the server might generate different types of responses; and - set the
httpBody
to be properly encoded for the specificContent-Type
; e.g. ifapplication/x-www-form-urlencoded
request, we need to percent-encode the body of the request.
E.g., in Swift 3 and later you can:
let url = URL(string: "https://httpbin.org/post")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.httpMethod = "POST"
let parameters: [String: Any] = [
"id": 13,
"name": "Jack & Jill"
]
request.httpBody = parameters.percentEncoded()
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard
let data = data,
let response = response as? HTTPURLResponse,
error == nil
else { // check for fundamental networking error
print("error", error ?? URLError(.badServerResponse))
return
}
guard (200 ... 299) ~= response.statusCode else { // check for http errors
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
// do whatever you want with the `data`, e.g.:
do {
let responseObject = try JSONDecoder().decode(ResponseObject<Foo>.self, from: data)
print(responseObject)
} catch {
print(error) // parsing error
if let responseString = String(data: data, encoding: .utf8) {
print("responseString = \(responseString)")
} else {
print("unable to parse response as string")
}
}
}
task.resume()
Where the following extensions facilitate the percent-encoding request body, converting a Swift Dictionary
to a application/x-www-form-urlencoded
formatted Data
:
extension Dictionary {
func percentEncoded() -> Data? {
map { key, value in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
.data(using: .utf8)
}
}
extension CharacterSet {
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed: CharacterSet = .urlQueryAllowed
allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return allowed
}()
}
And the following Decodable
model objects facilitate the parsing of the application/json
response using JSONDecoder
:
// sample Decodable objects for https://httpbin.org
struct ResponseObject<T: Decodable>: Decodable {
let form: T // often the top level key is `data`, but in the case of https://httpbin.org, it echos the submission under the key `form`
}
struct Foo: Decodable {
let id: String
let name: String
}
This checks for both fundamental networking errors as well as high-level HTTP errors. This also properly percent escapes the parameters of the query.
Note, I used a name
of Jack & Jill
, to illustrate the proper x-www-form-urlencoded
result of name=Jack%20%26%20Jill
, which is “percent encoded” (i.e. the space is replaced with %20
and the &
in the value is replaced with %26
).
See previous revision of this answer for Swift 2 rendition.
Swift 5, make http post request
Below is the code for Post
Method,using URLSession
let Url = String(format: "http://10.10.10.53:8080/sahambl/rest/sahamblsrv/userlogin")
guard let serviceUrl = URL(string: Url) else { return }
let parameters: [String: Any] = [
"request": [
"xusercode" : "YOUR USERCODE HERE",
"xpassword": "YOUR PASSWORD HERE"
]
]
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else {
return
}
request.httpBody = httpBody
request.timeoutInterval = 20
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
} catch {
print(error)
}
}
}.resume()
}
How to send POST parameters in Swift?
No different than in Objective-C, HTTPBody expects an NSData object:
var bodyData = "key1=value&key2=value&key3=value"
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
You'll have to setup the values & keys yourself in the string.
How to send a POST request through Swift?
I think you should pass your request instead of the url to session.dataTask
here is how my code looks like:
private let url = URL(string: "http://example.com/")!
func httpPost(jsonData: Data) {
if !jsonData.isEmpty {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = jsonData
URLSession.shared.getAllTasks { (openTasks: [URLSessionTask]) in
NSLog("open tasks: \(openTasks)")
}
let task = URLSession.shared.dataTask(with: request, completionHandler: { (responseData: Data?, response: URLResponse?, error: Error?) in
NSLog("\(response)")
})
task.resume()
}
}
How can I make a post request in Swift that reads more than 1 parameter?
I don't think the JSON data you were providing in parameters was valid (I check using jsonlint.com) Try this:
func postRequest(classroomID: String, email: String, vote: String){
//declare parameter as a dictionary which contains string as key and value combination.
let parameters: [String:Any] = [
"classroomID": classroomID,
"LastUpdated": "2020-01-01",
"TheVoteData":[
"Email": email,
"TheVote": vote
]
]
//create the url with NSURL
let url = URL(string: "https://www.api-gateway/dynamoDB/resource")!
//now create the Request object using the url object
var request = URLRequest(url: url)
request.httpMethod = "POST" //set http method as POST
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) // pass dictionary to data object and set it as request body
} catch let error {
print(error.localizedDescription)
}
//HTTP Headers
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let jsonData = try! JSONSerialization.data(withJSONObject: parameters, options: [])
//create dataTask using the session object to send data to the server
let task = URLSession.shared.uploadTask(with: request, from: jsonData) { data, response, error in
if let data = data, let dataString = String(data: data, encoding: .utf8) {
print(dataString)
}
//Returns HHTP response if
if let httpResponse = response as? HTTPURLResponse {
print(httpResponse.statusCode)
}
}
task.resume()
}
POST Parameters in Swift
Try to do parameter as array.
var params=[Candto] ()
Then loop whenever you want and append your object to array.
Related Topics
<Input Type="Number"/> Is Not Showing a Number Keypad on iOS
How to Post Nested JSON by Swiftyjson and Alamofire
How Do We Create a Bigger Center Uitabbar Item
Enterprise App Deployment Doesn't Install on iOS 8.1.3
Getting Text from Image on iOS (Image Processing)
Default Tab Bar Item Colors Using Swift Xcode 6
"Your Binary Is Not Optimized for iPhone 5" (Itms-90096) When Submitting
Showing the File Download Progress with Nsurlsessiondatatask
Scrolling Slow on Mobile/iOS When Using Overflow:Scroll
Redirect Nslog to File in Swift Not Working
How to Display the Default iOS 6 Share Action Sheet with Available Share Options
Uitextview Style Is Being Reset After Setting Text Property
Uibutton Doesn't Listen to Content Mode Setting
Avaudioplayer Throws Breakpoint in Debug Mode