How do I make an HTTP request in Swift?

前端 未结 20 1060
不知归路
不知归路 2020-11-22 05:10

I read The Programming Language Swift by Apple in iBooks, but cannot figure out how to make an HTTP request (something like cURL) in Swift. Do I need to import Obj-C classes

相关标签:
20条回答
  • 2020-11-22 06:01

    You can use Just, a python-requests style HTTP library.

    Some example of sending HTTP request with Just:

    // synchronous GET request with URL query a=1
    let r = Just.get("https://httpbin.org/get", params:["a":1])
    
    // asynchronous POST request with form value and file uploads
    Just.post(
        "http://justiceleauge.org/member/register",
        data: ["username": "barryallen", "password":"ReverseF1ashSucks"],
        files: ["profile_photo": .URL(fileURLWithPath:"flash.jpeg", nil)]
    ) { (r)
        if (r.ok) { /* success! */ }
    }
    

    In both cases, the result of a request r can be accessed in ways similar to python-request:

    r.ok            // is the response successful?
    r.statusCode    // status code of response
    r.content       // response body as NSData?
    r.text          // response body as text?
    r.json          // response body parsed by NSJSONSerielization
    

    You can find more examples in this playground

    Using this library in synchronous mode in a playground is the closest thing to cURL one can get in Swift.

    0 讨论(0)
  • 2020-11-22 06:01

    //Here is an example that worked for me

    //Swift function that post a request to a server with key values

    func insertRecords()
    {
    
    
    
        let usrID = txtID.text
        let checkin = lblInOut.text
        let comment = txtComment.text
    
    
    
        // The address of the web service
        let urlString = "http://your_url/checkInOut_post.php"
    
        // These are the keys that your are sending as part of the post request
        let keyValues = "id=\(usrID)&inout=\(checkin)&comment=\(comment)"
    
    
    
    
        // 1 - Create the session by getting the configuration and then
        //     creating the session
    
        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session = NSURLSession(configuration: config, delegate: nil, delegateQueue: nil)
    
    
        // 2 - Create the URL Object
    
        if let url = NSURL(string: urlString){
    
    
            // 3 - Create the Request Object
    
            var request  = NSMutableURLRequest(URL: url)
            request.HTTPMethod = "POST"
    
            // set the key values
            request.HTTPBody = keyValues.dataUsingEncoding(NSUTF8StringEncoding);
    
    
            // 4 - execute the request
    
            let taskData = session.dataTaskWithRequest(request, completionHandler: {
    
                (data:NSData!, response:NSURLResponse!, error:NSError!) -> Void in
    
                println("\(data)")
    
                // 5 - Do something with the Data back
    
                if (data != nil) {
    
                    // we got some data back
                    println("\(data)")
    
                    let result = NSString(data: data , encoding: NSUTF8StringEncoding)
                    println("\(result)")
    
                    if result == "OK" {
    
                        let a = UIAlertView(title: "OK", message: "Attendece has been recorded", delegate: nil, cancelButtonTitle: "OK")
    
                        println("\(result)")
    
                        dispatch_async(dispatch_get_main_queue()) {
    
    
                        a.show()
    
    
                        }
    
    
                    } else {
                      // display error and do something else
    
                    }
    
    
                } else
    
                {   // we got an error
                    println("Error getting stores :\(error.localizedDescription)")
    
                }
    
    
            })
    
            taskData.resume()
    
    
    
        }
    
    
    }
    

    PHP Code to get the key values

    $empID = $_POST['id'];

    $inOut = $_POST['inout'];

    $comment = $_POST['comment'];

    0 讨论(0)
  • 2020-11-22 06:01

    For XCUITest to stop the test finishing before the async request completes use this (maybe reduce the 100 timeout):

    func test_api() {
        let url = URL(string: "https://jsonplaceholder.typicode.com/posts/42")!
        let exp = expectation(description: "Waiting for data")
        let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
            guard let data = data else { return }
            print(String(data: data, encoding: .utf8)!)
            exp.fulfill()
        }
        task.resume()
        XCTWaiter.wait(for: [exp], timeout: 100)
    }
    
    0 讨论(0)
  • 2020-11-22 06:01

    To make HTTP requests is core functionality for modern languages and one of the first things many developers learn when acclimating to new environments. When it comes to Swift there are a fair amount of solutions to this problem both built into the language and by the community. Let’s take a look at some of the most popular ones.

    This is the Alamofire Request Example:-

    We are going to use Swift on the command line in all of the following examples. This doesn’t mean you can’t copy and paste any of this to Xcode, but Swift has an array of useful command-line utilities that make testing the code in this tutorial easy.

    Follow along by opening your terminal and navigating to the directory where you want this code to live. My directory is named SwiftHTTP which you will see in the examples in the rest of this post.

    Enter the following to generate an executable command-line project:

    swift package init --type executable
    

    This will also generate a Package.swift file for you. With this, we can add dependencies to use Swift Package Manager for installing third-party libraries.

    HTTP Requests with URLRequest

    First up, we are going to use a built-in API called URLRequest. If you’re following along using the command line, open up main.swift in the Sources directory that was generated from the previous command, and enter the following code:

    import Foundation
    
    // Set the URL the request is being made to.
    let request = URLRequest(url: NSURL(string: "https://api.nasa.gov/planetary/apod? 
    api_key=DEMO_KEY")! as URL)
    do {
        // Perform the request
        var response: AutoreleasingUnsafeMutablePointer<URLResponse?>? = nil
        let data = try NSURLConnection.sendSynchronousRequest(request, returning: response)
    
        // Convert the data to JSON
        let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
    
        if let json = jsonSerialized, let url = json["url"], let explanation = json["explanation"] {
            print(url)
            print(explanation)
        }
    }
    

    That’s all you need to do to make an HTTP request. Head back to your terminal and run the following command, keeping in mind that you might have to modify this to fit the name of your Swift project:

    swift build && .build/debug/SwiftHTTP
    

    HTTP Requests with URLSession

    URLSession is another popular way to send HTTP requests that are built into the language. URLSession also doesn’t execute requests off of the main thread, which is pretty nifty.

    Modify main.swift to include the following code:

    import Foundation
    
    let url = URL(string: "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY")
    
    let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
    
        if let data = data {
            do {
                // Convert the data to JSON
                let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: 
                []) as? [String : Any]
    
                if let json = jsonSerialized, let url = json["url"], let explanation = 
                json["explanation"] {
                    print(url)
                    print(explanation)
                }
            }  catch let error as NSError {
                print(error.localizedDescription)
            }
        } else if let error = error {
            print(error.localizedDescription)
        }
    }
    
    task.resume()
    
    // Infinitely run the main loop to wait for our request.
    // Only necessary if you are testing in the command line.
    RunLoop.main.run()
    

    The example we used before with URLRequest was synchronous, but this one is asynchronous. For this reason, we are calling RunLoop.main.run() at the end to make sure the script doesn’t finish executing before the request is responded to. Feel free to take that last line out if you are using this code in a different context.

    Just like before, run this code:

    swift build && .build/debug/SwiftHTTP
    

    Once you get a response, kill the script with ctrl-c.

    HTTP Requests with Alamofire

    The previous methods have been built into the language. But there are also third-party networking libraries in Swift. Alamofire is an excellent (and also the most popular) in the Swift community.

    Alamofire is a user-friendly and versatile library with a lot of options. It has chainable request and response methods and takes care of boilerplate functionality such as validating HTTP responses.

    Unlike the other examples, we need to modify Package.swift for this to work. We’ll also be using another library called SwiftyJSON, which makes parsing JSON more user-friendly and works very well with Alamofire.

    Replace the code inside Package.swift with the following to add Alamofire and SwiftyJSON as dependencies:

    import PackageDescription
    
    let package = Package(
       name: "SwiftHTTP",
       dependencies: [
           .Package(url: "https://github.com/Alamofire/Alamofire.git", majorVersion: 4),
           .Package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", majorVersion: 3, 
           minor: 1)
       ]
    )
    

    Now head back to main.swift to change the code to use Alamofire:

    import Foundation
    import Alamofire
    import SwiftyJSON
    
    Alamofire.request("https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY").responseJSON 
    { response in
        if let result = response.result.value {
            let json = JSON(result)
            print(json["url"])
            print(json["explanation"])
        }
    }
    
    RunLoop.main.run()
    

    Just like in our previous option, the request is asynchronous so we are calling RunLoop.main.run().

    0 讨论(0)
  • 2020-11-22 06:02

    Using URLSession + Swift 5

    Just adding to cezar's answer, if you want to make web request using Apple's URLSession class, there are multiple way to do the task

    1. Simple GET Request with URL
    2. Simple GET Request with URL and Parameters
    3. Simple GET Request with URL with Error Handlings
    4. Simple POST Request with URL, Parameters with Error Handlings

    1. Simple GET Request with URL

    func simpleGetUrlRequest()
        {
            let url = URL(string: "https://httpbin.org/get")!
    
            let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
                guard let data = data else { return }
                print("The response is : ",String(data: data, encoding: .utf8)!)
                //print(NSString(data: data, encoding: String.Encoding.utf8.rawValue) as Any)
            }
            task.resume()
        }
    

    Note : Make sure You must add "NSAppTransportSecurity" key in pList for http requests

    <key>NSAppTransportSecurity</key>
    <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    </dict>
    

    2. Simple GET Request with URL and Parameters

    func simpleGetUrlWithParamRequest()
        {
            let url = URL(string: "https://www.google.com/search?q=peace")!
            
            let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
                
                if error != nil || data == nil {
                    print("Client error!")
                    return
                }
                guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
                    print("Server error!")
                    return
                }
                print("The Response is : ",response)
            }
            task.resume()
        }
    

    3. Simple GET Request with URL with Error Handlings

    func simpleGetUrlRequestWithErrorHandling()
        {
            let session = URLSession.shared
            let url = URL(string: "https://httpbin.org/get")!
            
            let task = session.dataTask(with: url) { data, response, error in
                
                if error != nil || data == nil {
                    print("Client error!")
                    return
                }
                
                guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
                    print("Server error!")
                    return
                }
                
                guard let mime = response.mimeType, mime == "application/json" else {
                    print("Wrong MIME type!")
                    return
                }
                
                do {
                    let json = try JSONSerialization.jsonObject(with: data!, options: [])
                    print("The Response is : ",json)
                } catch {
                    print("JSON error: \(error.localizedDescription)")
                }
                
            }
            task.resume()
        }
    

    4. Simple POST Request with URL, Parameters with Error Handlings.

    func simplePostRequestWithParamsAndErrorHandling(){
            let configuration = URLSessionConfiguration.default
            configuration.timeoutIntervalForRequest = 30
            configuration.timeoutIntervalForResource = 30
            let session = URLSession(configuration: configuration)
            
            let url = URL(string: "https://httpbin.org/post")!
            
            var request = URLRequest(url: url)
            request.httpMethod = "POST"
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            request.addValue("application/json", forHTTPHeaderField: "Accept")
            
            let parameters = ["username": "foo", "password": "123456"]
            
            do {
                request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
            } catch let error {
                print(error.localizedDescription)
            }
            
            let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
                
                if error != nil || data == nil {
                    print("Client error!")
                    return
                }
                
                guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
                    print("Oops!! there is server error!")
                    return
                }
                
                guard let mime = response.mimeType, mime == "application/json" else {
                    print("response is not json")
                    return
                }
                
                do {
                    let json = try JSONSerialization.jsonObject(with: data!, options: [])
                    print("The Response is : ",json)
                } catch {
                    print("JSON error: \(error.localizedDescription)")
                }
                
            })
            
            task.resume()
        }
    

    Your suggestions are appreciated!!

    0 讨论(0)
  • 2020-11-22 06:03

    An example for a sample "GET" request is given below.

    let urlString = "YOUR_GET_URL"
    let yourURL = URL(string: urlstring)
    let dataTask = URLSession.shared.dataTask(with: yourURL) { (data, response, error) in
    do {
        let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
        print("json --- \(json)")
        }catch let err {
        print("err---\(err.localizedDescription)")
        }
       }
    dataTask.resume()
    
    0 讨论(0)
提交回复
热议问题