NSMutableURLRequest.HTTPMethod 没有设置正确的方法

NSMutableURLRequest.HTTPMethod not setting the correct Method

我有一个 API 的请求,它应该 POST 一些 json:

class func makeAPICall (serializedJSONObject contentMap: Dictionary<String, String>, completion: ((data: NSData?, response: NSURLResponse?, error: NSError?) -> Void)) throws -> Void {
        var jsonData: NSData
        do {
            jsonData = try NSJSONSerialization.dataWithJSONObject(contentMap, options: NSJSONWritingOptions())
            var jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding) as! String
            print(jsonString)
            jsonString = jsonString.stringByAddingPercentEncodingForFormUrlencoded()!
            print(jsonString)
            jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding)!
            let postsEndpoint: String = "https://www.example.com/api/v2"
            guard let postsURL = NSURL(string: postsEndpoint) else {
                throw APICallError.other("cannot create URL")
            }
            let postsURLRequest = NSMutableURLRequest(URL: postsURL)
            print(jsonData)
            postsURLRequest.HTTPBody = jsonData
            print(postsURLRequest)
            postsURLRequest.HTTPMethod = "POST"

            let config = NSURLSessionConfiguration.defaultSessionConfiguration()
            let session = NSURLSession(configuration: config)

            let task = session.dataTaskWithRequest(postsURLRequest, completionHandler: {
                (data, response, error) in
                completion(data: data, response: response, error: error)
            })
            task.resume() //starts the request. It's called resume() because a session starts in a suspended state
        } catch {
            print("lol, problem")
        }
    }

扩展名(针对 x-www-form-urlencoded 编码):

extension String {
    func stringByAddingPercentEncodingForFormUrlencoded() -> String? {
        let characterSet = NSMutableCharacterSet.alphanumericCharacterSet()
        characterSet.addCharactersInString("-._* ")

        return stringByAddingPercentEncodingWithAllowedCharacters(characterSet)?.stringByReplacingOccurrencesOfString(" ", withString: "+")
    }
}

现在我也有这个简单的测试页面来测试 json 请求:

<form action="v2/" method="post">
    <textarea name="data" rows="20" cols="80"></textarea>
    <input type="submit" />
</form>

服务器记录所有请求,这样我发现我的应用实际上使用的是 GET 而不是 POST

应用请求日志:

GET /api/v2/ HTTP/1.1

HTTP headers:
Host: www.example.com
Accept: */\*
Cookie: PHPSESSID=vd61qutdll216hbs3a677fgsq4
User-Agent: KM%20registratie%20tabbed%20NL/1 CFNetwork/758.2.8 Darwin/15.2.0
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: keep-alive

Request body:

(请注意请求正文也是空的,但我会为此提出不同的问题)

html 表单请求日志:

POST /api/v2/ HTTP/1.1

HTTP headers:
Host: www.example.com
Origin: http://www.example.com
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/\*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9
Referer: http://www.example.com/api/test.php
Accept-Language: en-us
Accept-Encoding: gzip, deflate

Request body:
data=%7B%22action%22%3A+%22vehicleRecords%22%2C%0D%0A%22token%22%3A+%22token_04e01fdc78205f0f6542bd523519e12fd3329ba9%22%2C%0D%0A%22vehicle%22%3A+%22vehicle_e5b79b2e%22%7D

你能先试试这个吗?

if let postEndpoint: NSURL = NSURL(string: "https://www.example.com/api/v2") {
    let postURLRequest: NSMutableURLRequest = NSMutableURLRequest(URL: postEndpoint)
    postURLRequest.HTTPMethod = "POST"
    postURLRequest.HTTPBody = UTF8EncodedJSON

    NSURLSession.sharedSession().dataTaskWithRequest(postURLRequest, completionHandler: { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in

    }).resume()
}

我只发现我们每个人处理代码的方式有 2 个不同,但看到 post 对我来说如何工作,我就 post 它并希望它可能有用。

配置和请求如下:

let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let a = apiString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
let request = NSMutableURLRequest(URL: NSURL(string: Utilities.getTranslation("websiteG") + a!)!)

虽然你的方式更简洁,但不要使用它。

之后,我只在已经设置主体后才应用该方法,尽管我真的怀疑稍后设置该方法是否会修复它。

if method == "POST" || method == "PUT" {
     request.HTTPBody = post!.dataUsingEncoding(NSUTF8StringEncoding)
}
request.HTTPMethod = method

最后但同样重要的是 NSURLSession 的制作和使用:

func httpRequest(configuration: NSURLSessionConfiguration, request: NSURLRequest!, callback: (NSData?, String?) -> Void) {
        let session = NSURLSession(configuration: configuration,
            delegate: self,
            delegateQueue: NSOperationQueue.mainQueue())
        task = session.dataTaskWithRequest(request) {
            (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
                if error != nil {
                    callback(nil, "\(error!.code)")
                } else {
                    let result = NSData(data: data!)
                    callback(result, nil)
                }
        }
        task.resume()
}

我真正看到的唯一区别是我分配了代表并且我使用了函数 "dataTaskWithRequest:" 而不是 "dataTaskWithRequest:completionHandler:"。

我真的不确定你的问题的答案是否在这里,但如果你想知道我仍然实现了哪些委托方法,你可以试一试:"URLSession:didReceiveChallenge:completionHandler:" 和 "URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:" 虽然我不认为他们会被解雇,所以我很确定你可以忽略代表的分配。

编辑:我只写整个函数。

func apiCall(method: String = "GET", post: String? = nil, apiString: String, success: (JSONData: NSData!, cancel: Bool!) -> Void) {
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true
    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    //website string
    let a = apiString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
    let request = NSMutableURLRequest(URL: NSURL(string: Utilities.getTranslation("websiteG") + a!)!)
    print(request)
    //Define a new API object
    let learn = API()
    //Here is supposed to be some code for creating the base64 authorization string, but because it's not important I decided to remove it.
    //Check if it's sending extra information with the call
    if method == "POST" || method == "PUT" {
        request.HTTPBody = post!.dataUsingEncoding(NSUTF8StringEncoding)
    }
    request.HTTPMethod = method
    //Perform request to the api
    configuration.HTTPAdditionalHeaders = ["Authorization": authString]
    learn.httpRequest(configuration, request: request, callback:{(data, error) -> Void in
        UIApplication.sharedApplication().networkActivityIndicatorVisible = false
        if let urlData = data {
            success(JSONData: urlData, cancel: false)
            //Gives back an NSData that can be used for reading data
        } else {
            if error == "-1009" {
                self.delegate?.viewShouldDismissLoading()
            }
            success(JSONData: nil, cancel: true)
        }
    })
}

url 应该有一个尾随 forward-slash 所以:"www.example.com/api/v2/"