In this tutorial, you will learn how to send HTTP Post Request in Swift and how to read HTTP Response and Response Body. This tutorial will cover:
- Send HTTP Post Request,
- Convert Query String request parameters to JSON,
- Convert Swift structure to JSON,
- Set HTTP Request Headers,
- Read HTTP Response,
- Read HTTP Response Headers,
- Read HTTP Response Body as String,
- Read HTTP Response Body as JSON
To learn how to send HTTP GET Request please read this tutorial: HTTP GET Request Example in Swift
Public RESTful Web Service Endpoint
In this tutorial, I will use public and free at the time of writing this tutorial RESTful Web Service: https://jsonplaceholder.typicode.com. This web service endpoint allows me to send HTTP Requests to it and get back JSON response. For example, if I open the following URL in the browser windows: https://jsonplaceholder.typicode.com/todos/1 I will get back the following JSON document:
{ "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false }
I can also send HTTP Post Request to https://jsonplaceholder.typicode.com/todos and get back a created record. For example, if I send an HTTP Post request containing the following JSON payload in the body of HTTP Request:
{ "userId": 300, "title": "delectus aut autem", "completed": false }
I will get back a response similar to this:
{ "userId": "300", "title": "My urgent task", "completed": "false", "id": 201 }
So let’s try and see how it works with Swift.
Send HTTP POST Request
Below is a very simple example of how you can send an HTTP POST Request in Swift. Please note the comments in the code.
// Prepare URL let url = URL(string: "https://jsonplaceholder.typicode.com/todos") guard let requestUrl = url else { fatalError() } // Prepare URL Request Object var request = URLRequest(url: requestUrl) request.httpMethod = "POST" // HTTP Request Parameters which will be sent in HTTP Request Body let postString = "userId=300&title=My urgent task&completed=false"; // Set HTTP Request Body request.httpBody = postString.data(using: String.Encoding.utf8); // Perform HTTP Request let task = URLSession.shared.dataTask(with: request) { (data, response, error) in // Check for Error if let error = error { print("Error took place \(error)") return } // Convert HTTP Response Data to a String if let data = data, let dataString = String(data: data, encoding: .utf8) { print("Response data string:\n \(dataString)") } } task.resume()
Please note how in the code snippet above we convert the Data object to a String. The result of the above HTTP Post request should print out the following JSON string:
{ "userId": "300", "title": "My urgent task", "completed": "false", "id": 201 }
Here is how the code above looks in my Xcode Playground:
Set HTTP Request Header
If your HTTP Request needs to contain specific HTTP Request Headers, then below is an example of how you can do it.
var request = URLRequest(url: requestUrl) request.httpMethod = "POST" // Set HTTP Request Header request.setValue("application/json", forHTTPHeaderField: "Accept")
You can set more than one header.
request.setValue("application/json", forHTTPHeaderField: "Accept") request.setValue("application/json", forHTTPHeaderField: "Content-Type")
Read HTTP Response Headers
Once you have received HTTP Response, you can then read from that HTTPURLResponse object all HTTP Request headers at once or if you know the HTTP request header name, then you can read the value of that specific header.
Read All Header Fields
let allHeaderFields:[AnyHashable : Any] = response.allHeaderFields print("All headers: \(allHeaderFields)")
Read a Specific HTTP Header Value
let contentTypeHeader = response.value(forHTTPHeaderField: "Content-Type")
and here how it is being used when HTTP Response is received:
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in if let response = response as? HTTPURLResponse { // Read all HTTP Response Headers print("All headers: \(response.allHeaderFields)") // Read a specific HTTP Response Header by name print("Specific header: \(response.value(forHTTPHeaderField: "Content-Type") ?? " header not found")") } } task.resume()
Read HTTP Response Body
When HTTP Response arrives, you will most likely need to read its HTTP Response Body. Use the below code snippet to convert the HTTP Response Body/Data to a human-readable String value.
if let data = data, let dataString = String(data: data, encoding: .utf8) { print("Response data string:\n \(dataString)") }
and here how it looks if used with URLSession data task:
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in if let data = data, let dataString = String(data: data, encoding: .utf8) { print("Response data string:\n \(dataString)") } } task.resume()
Swift Struct as Request Body
You can also send Swift structure in HTTP Response Body. For example, instead of sending HTTP Request parameters as we did in the example above userId=300&title=My urgent task&completed=false, we can create a Swift structure and set it as HTTP Response body.
The following request parameters String could also be represented in the following way:
struct ToDoResponseModel: Codable { var userId: Int var id: Int? var title: String var completed: Bool } let newTodoItem = ToDoResponseModel(userId: 300, title: "Urgent task 2", completed: true)
Using the JSONEncoder() we can then encode the above Swift structure into JSON Data and set it as Request Body.
let jsonData = try JSONEncoder().encode(newTodoItem) request.httpBody = jsonData
Note: Do not forget to set HTTP Headers: Accept and Content-Type to application/json.
// Set HTTP Request Headers request.setValue("application/json", forHTTPHeaderField: "Accept") request.setValue("application/json", forHTTPHeaderField: "Content-Type")
For example:
struct ToDoResponseModel: Codable { var userId: Int var id: Int? var title: String var completed: Bool } let url = URL(string: "https://jsonplaceholder.typicode.com/todos") guard let requestUrl = url else { fatalError() } var request = URLRequest(url: requestUrl) request.httpMethod = "POST" // Set HTTP Request Header request.setValue("application/json", forHTTPHeaderField: "Accept") request.setValue("application/json", forHTTPHeaderField: "Content-Type") let newTodoItem = ToDoResponseModel(userId: 300, title: "Urgent task 2", completed: true) let jsonData = try JSONEncoder().encode(newTodoItem) request.httpBody = jsonData let task = URLSession.shared.dataTask(with: request) { (data, response, error) in if let error = error { print("Error took place \(error)") return } guard let data = data else {return} do{ let todoItemModel = try JSONDecoder().decode(ToDoResponseModel.self, from: data) print("Response data:\n \(todoItemModel)") print("todoItemModel Title: \(todoItemModel.title)") print("todoItemModel id: \(todoItemModel.id ?? 0)") }catch let jsonErr{ print(jsonErr) } } task.resume()
Covert Response Data into Swift Structure
Once the HTTP Response arrives, we can then decode the JSON Payload into a Swift Struct. In the code example above we have already done that. To convert data object container JSON string we will use JSONDecoder(). For example:
do{ let todoItemModel = try JSONDecoder().decode(ToDoResponseModel.self, from: data) print("Response data:\n \(todoItemModel)") print("todoItemModel Title: \(todoItemModel.title)") print("todoItemModel id: \(todoItemModel.id ?? 0)") }catch let jsonErr{ print(jsonErr) }
Here is how my code in Xcode playground looks now:
I hope this tutorial was helpful to you. Check other Swift tutorials on this web site and you will find a lot of useful code examples to use.
To learn how to send HTTP GET Request please read this tutorial: HTTP GET Request Example in Swift
Thanks for this tutorial, it’s invaluable! I’m sure lots of people read your page, but no one has left any reply… So I’m the first! 🙂
Thank you, Amir! 🙏🙂
Hi
I am new to ios and swift. Can me please help me in authenticating a spring restful webservice for ios app