How to make HTTP request in Swift?
You can use URL
, URLRequest
and URLSession
or NSURLConnection
as you'd normally do in Objective-C. Note that for iOS 7.0 and later, URLSession
is preferred.
Using URLSession
Initialize a URL
object and a URLSessionDataTask
from URLSession
. Then run the task with resume()
.
let url = URL(string: "http://www.stackoverflow.com")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
}
task.resume()
Using NSURLConnection
First, initialize a URL
and a URLRequest
:
let url = URL(string: "http://www.stackoverflow.com")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
Then, you can load the request asynchronously with:
NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main) {(response, data, error) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
}
Or you can initialize an NSURLConnection
:
let connection = NSURLConnection(request: request, delegate:nil, startImmediately: true)
Just make sure to set your delegate to something other than nil
and use the delegate methods to work with the response and data received.
For more detail, check the documentation for the NSURLConnectionDataDelegate
protocol
Testing on an Xcode playground
If you want to try this code on a Xcode playground, add import PlaygroundSupport
to your playground, as well as the following call:
PlaygroundPage.current.needsIndefiniteExecution = true
This will allow you to use asynchronous code in playgrounds.
Making HTTP GET request with Swift 5
Right now, if there is an error, you are going to silently fail. So add some error logging, e.g.,
func httpRequest() {
let url = URL(string: "https://www.stackoverflow.com")! // note, https, not http
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard
error == nil,
let data = data,
let string = String(data: data, encoding: .utf8)
else {
print(error ?? "Unknown error")
return
}
print(string)
}
task.resume()
}
That should at least give you some indication of the problem.
A few other considerations:
If command line app, you have to recognize that the app may quit before this asynchronous network request finishes. One would generally start up a
RunLoop
, looping withrun(mode:before:)
until the network request finishes, as advised in therun
documentation.For example, you might give that routine a completion handler that will be called on the main thread when it is done. Then you can use that:
func httpRequest(completion: @escaping () -> Void) {
let url = URL(string: "https://www.stackoverflow.com")! // note, https, not http
let task = URLSession.shared.dataTask(with: url) { data, response, error in
defer {
DispatchQueue.main.async {
completion()
}
}
guard
error == nil,
let data = data,
let string = String(data: data, encoding: .utf8)
else {
print(error ?? "Unknown error")
return
}
print(string)
}
task.resume()
}
var finished = false
httpRequest {
finished = true
}
while !finished {
RunLoop.current.run(mode: .default, before: .distantFuture)
}In standard macOS apps, you have to enable outgoing (client) connections in the “App Sandbox” capabilities.
If playground, you have to set
needsIndefiniteExecution
.By default, macOS and iOS apps disable
http
requests unless you enable "Allow Arbitrary Loads” in yourInfo.plist
. That is not applicable to command line apps, but you should be aware of that should you try to do this in standard macOS/iOS apps.In this case, you should just use
https
and avoid that consideration altogether.
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 can I make a http request on swift with authentication?
Here you go you just need to add the header for Authorization
Use Codable for JSON parsing don't use JSONSerialization
and use this tool for converting the Json
to the struct
let url = URL(string: "http://209.97.133.56/api/ucs")!
let token = "your token"
var request = URLRequest(url: url)
request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { (data, response , error) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8) ?? "Invalid JSON")
}.resume()
Edit
Use the tool that I have give to convert your json to the struct, JSON converted by the tool
struct UPS: Codable {
let data: [UPSData]
enum CodingKeys: String, CodingKey {
case data = "data"
}
}
struct UPSData: Codable {
let id: String
let unidadeCurricularID: Int
let unidadeCurricularNome: String
let unidadeCurricularAbreviatura: String
let unidadeCurricularAtivo: Int
let unidadeCurricularIDMapSiges: Int
let anoCurricularID: Int
let anoCurricularNome: String
let anoCurricularAbreviatura: String?
let anoCurricularAtivo: Int
let anoCurricularIDMapSiges: Int
let periodoTempoID: Int
let periodoTempoNome: String
let periodoTempoAvreviatura: String
let periodoTempoOrdem: Int
let periodoTempoAtivo: Int
let periodoTempoIDMapSiges: String
let numeroEstudante: Int
let idAnoLetivo: Int
let idUnidadeCurricular: Int
let idEstadoInscricao: Int
let idAnoCurricular: Int
let numeroCreditos: Int
enum CodingKeys: String, CodingKey {
case id = "id"
case unidadeCurricularID = "unidadeCurricularId"
case unidadeCurricularNome = "unidadeCurricularNome"
case unidadeCurricularAbreviatura = "unidadeCurricularAbreviatura"
case unidadeCurricularAtivo = "unidadeCurricularAtivo"
case unidadeCurricularIDMapSiges = "unidadeCurricularIdMapSiges"
case anoCurricularID = "anoCurricularId"
case anoCurricularNome = "anoCurricularNome"
case anoCurricularAbreviatura = "anoCurricularAbreviatura"
case anoCurricularAtivo = "anoCurricularAtivo"
case anoCurricularIDMapSiges = "anoCurricularIdMapSiges"
case periodoTempoID = "periodoTempoId"
case periodoTempoNome = "periodoTempoNome"
case periodoTempoAvreviatura = "periodoTempoAvreviatura"
case periodoTempoOrdem = "periodoTempoOrdem"
case periodoTempoAtivo = "periodoTempoAtivo"
case periodoTempoIDMapSiges = "periodoTempoIdMapSiges"
case numeroEstudante = "numeroEstudante"
case idAnoLetivo = "idAnoLetivo"
case idUnidadeCurricular = "idUnidadeCurricular"
case idEstadoInscricao = "idEstadoInscricao"
case idAnoCurricular = "idAnoCurricular"
case numeroCreditos = "numero_creditos"
}
}
Add all of your network request code in this class
class NetworkRequest {
func auth<T: Decodable>(with url: URL, token: String, completion: @escaping (T) -> Void) {
var request = URLRequest(url: url)
request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { (data, response , error) in
guard let data = data else { return }
do {
completion(try JSONDecoder().decode(T.self, from: data))
} catch let error {
print(error)
}
}.resume()
}
}
use this code any where in your class
NetworkRequest().auth(with: url, token: token) { (ups: UPS) in
print("do what do want to you")
}
How to build Http Request with IP address in Swift?(Moya)
var baseURL: URL = URL(string: "http://github.com/apple/swift")
try this ?
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.
HTTP Requests in Swift 3
There are a couple problems with your code:
- By default, your app cannot connect to insecure (i.e. HTTP) site. It's a feature called App Transport Security. You need to make an exception in your app's
Info.plist
file to connect to HTTP sites. - This:
dataTask(urlwith: ! as URL)
. What are you trying to unwrap with the exclamation mark (!
)? What's the variable name?
A lot of class names have changed between Swift 2 and 3 so those answers you've found may not be applicable. Below is an example that connects to httpbin.org to get your IP address:
import PlaygroundSupport
import Foundation
let url = URL(string: "https://httpbin.org/ip")
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
guard error == nil else {
print(error!)
return
}
guard let data = data else {
print("Data is empty")
return
}
let json = try! JSONSerialization.jsonObject(with: data, options: [])
print(json)
}
task.resume()
PlaygroundPage.current.needsIndefiniteExecution = true
Related Topics
How to Add Spacing Between Uitableviewcell
Save Generated Gif to Camera Roll
What's the Difference Between the Atomic and Nonatomic Attributes
How to Export Uiimage Array as a Movie
Fast and Lean Pdf Viewer For Iphone/Ipad/Ios - Tips and Hints
How to Load Custom Uitableviewcells from Xib Files
Iphone: Detecting User Inactivity/Idle Time Since Last Screen Touch
How to Get Current Location from User in Ios
How to Intercept Touches Events on a Mkmapview or Uiwebview Objects
How to Get My Ip Address Programmatically on Ios/Macos
How to Record Video of Front and Back Camera At a Time in Ios
Uistackview Hiding/Unhiding Arrangedsubview Issue
How to Embed a Custom Font in an Iphone Application
How to Input Currency Format on a Text Field (From Right to Left) Using Swift
How to Present Uialertcontroller When Not in a View Controller
Xcode 6 Bug: Unknown Class in Interface Builder File