代码之家  ›  专栏  ›  技术社区  ›  Pradumna Patil

REST API的问题

  •  -2
  • Pradumna Patil  · 技术社区  · 7 年前

    我正在努力 REST API's 在里面 iOS application .

    我已经测试过了 Server URL Parameters 属于 POST 方法

    它正在返回

    您的浏览器发送了此服务器无法理解的请求

    响应中出现此错误。

    对于 GET 要求 API 工作正常。 如果有人遇到同样的问题,请告诉我。

    非常感谢。

    let configuration = URLSessionConfiguration.default;
    let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
    var urlString = String()
    urlString.append(Constant.BASE_URL)
    urlString.append(methodName)
    
    let encodedUrl = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
    let serverUrl: URL = URL(string: (encodedUrl?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed))!)!
    var request : URLRequest = URLRequest(url: serverUrl, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60.0)
    var paramStr : String = String()
    if requestDict.count > 0 {
        let keysArray = requestDict.keys
        for  key in keysArray {
            if paramStr.isEmpty{
                paramStr.append("\(key)=\(requestDict[key]! as! String)")
            }else{
                paramStr.append("&\(key)=\(requestDict[key]! as! String)")
            }
        }
    }
    
    let postData:Data = try! JSONSerialization.data(withJSONObject: requestDict)//paramStr.data(using: .utf8)!
    let reqJSONStr = String(data: postData, encoding: .utf8)
    let postLength = "\(postData.count)"
    
    request.httpMethod = "POST"
    request.setValue(postLength, forHTTPHeaderField: "Content-Length")
    //request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    //request.httpBody = reqJSONStr?.data(using: .utf8)
    
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    request.httpBody = try! JSONSerialization.data(withJSONObject: requestDict)
    
    
    
    if  headerValue != nil{
        let allkeys = headerValue.keys
        for key in allkeys {
            request.setValue(headerValue[key] as! String?, forHTTPHeaderField: key)
        }
    }
    
    let postDataTask : URLSessionDataTask = session.dataTask(with: request, completionHandler:
    {
        data, response, error in
        if data != nil && error == nil{
            let res = String(data: data!, encoding: .utf8)
            let dict = convertToDictionary(text: res!)
            if let httpResponse = response as? HTTPURLResponse {
                //print("error \(httpResponse.statusCode)")
                if httpResponse.statusCode == 200
                {
                    DispatchQueue.main.async {
                        successBlock (response!,(dict)!)
                    }
                }
                else
                {
                    if (error?.localizedDescription) != nil
                    {
                        errorBlock((error?.localizedDescription)! as String)
                    }
                    else
                    {
                        errorBlock("")
                    }
                }
            }
            else
            {
                errorBlock((error?.localizedDescription)! as String)
            }
        }
        else{
            if let httpResponse = error as? HTTPURLResponse {
                //print("error \(httpResponse.statusCode)")
            }
            errorBlock((error?.localizedDescription)! as String)
        }
    })
    postDataTask.resume()
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Reinier Melian    7 年前

    假设您的后端需要一个url编码的表单请求,那么您应该将参数字典转换为url编码的字符串

    这是一个例子

    let parameters : [String:Any] = ["ajax":1,"test":"abuela"]
    
    var queryItems : [URLQueryItem] = []
    for key in parameters.keys {
        if let value = parameters[key] as? String {
            queryItems.append(URLQueryItem(name: key, value: value))
        }else{
            queryItems.append(URLQueryItem(name: key, value: String(describing:parameters[key]!)))
        }
    }
    
    var urlComponents = URLComponents()
    urlComponents.queryItems = queryItems
    

    那么如果你

    print(urlComponents.percentEncodedQuery!)
    

    你会得到

    test=abuela&ajax=1

    然后,您需要添加 urlString

    urlString.append("&" + urlComponents.percentEncodedQuery!)
    

    完整代码

    let configuration = URLSessionConfiguration.default;
    let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
    var urlString = String()
    urlString.append(Constant.BASE_URL)
    urlString.append(methodName)
    
    var queryItems : [URLQueryItem] = []
    for key in parameters.keys {
        if let value = parameters[key] as? String {
            queryItems.append(URLQueryItem(name: key, value: value))
        }else{
            queryItems.append(URLQueryItem(name: key, value: String(describing:parameters[key]!)))
        }
    }
    
    var urlComponents = URLComponents()
    urlComponents.queryItems = queryItems
    
    print(urlComponents.percentEncodedQuery!)
    urlString.append("&" + urlComponents.percentEncodedQuery!)
    
    let encodedUrl = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
    let serverUrl: URL = URL(string: urlString)!
    var request : URLRequest = URLRequest(url: serverUrl, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60.0)
    
    
    request.httpMethod = "POST"
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    
    let postDataTask : URLSessionDataTask = session.dataTask(with: request, completionHandler:
    {
        data, response, error in
        if data != nil && error == nil{
            let res = String(data: data!, encoding: .utf8)
            let dict = convertToDictionary(text: res!)
            if let httpResponse = response as? HTTPURLResponse {
                //print("error \(httpResponse.statusCode)")
                if httpResponse.statusCode == 200
                {
                    DispatchQueue.main.async {
                        successBlock (response!,(dict)!)
                    }
                }
                else
                {
                    if (error?.localizedDescription) != nil
                    {
                        errorBlock((error?.localizedDescription)! as String)
                    }
                    else
                    {
                        errorBlock("")
                    }
                }
            }
            else
            {
                errorBlock((error?.localizedDescription)! as String)
            }
        }
        else{
            if let httpResponse = error as? HTTPURLResponse {
                //print("error \(httpResponse.statusCode)")
            }
            errorBlock((error?.localizedDescription)! as String)
        }
    })
    postDataTask.resume()
    

    如果后端正在等待 application/json http正文编码

    您正在httpBody中传递JSON对象,但您的contentType标头错误,而不是 "application/x-www-form-urlencoded" "application/json" ,我认为您的json转换是错误的,请尝试直接使用requestDict JSONSerialization 将在有效的JSON对象中转换字典,您可以在 request.httpBody

    代替

    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    

    通过

    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    

    使用它将requestDict参数字典转换为JSON

    request.httpBody = try! JSONSerialization.data(withJSONObject: requestDict)