【问题标题】:POST requests in Alamofire Parameter Encoding returning GET responsesAlamofire 参数编码中的 POST 请求返回 GET 响应
【发布时间】:2016-04-09 19:10:34
【问题描述】:

我正在尝试使用 Alamofire (3.0) 快速创建一个 Route Builder,并且我的所有 GET 请求都成功了,但是当我尝试发出 POST 请求时,例如,我仍然得到相同的响应GET 方法。

我的 API 路由是:

/users //GET -> return list of users
/users //POST -> create new user with the parameters sent

当我使用 Postman 时,一切正常。

这是我的路由器代码:

import Foundation
import Alamofire


enum UserRouter: URLRequestConvertible{

    static let baseURL = NSURL(string: "http://192.168.0.106/users")!

    case Users
    case CreateUser([String: AnyObject])
    case ReadUser(Int)
    case UpdateUser(Int, [String: AnyObject])
    case DestroyUser(Int)

    var URL: NSURL { return UserRouter.baseURL.URLByAppendingPathComponent(route.path) }

    var route: (path: String, parameters: [String: AnyObject]?) {

        switch self{

        case .Users:
            return ("/", nil)
        case .ReadUser(let userID):
            return ("/\(userID)", nil)
        case .CreateUser(let userInfo):
            return ("/", userInfo)
        case .UpdateUser(let userID, let userInfo):
            return ("/\(userID)", userInfo)
        case .DestroyUser(let userID):
            return ("/\(userID)", nil)
        }

    }

    var method: Alamofire.Method{

        switch self{

        case .Users:
            return .GET
        case .ReadUser:
            return .GET
        case .CreateUser:
            return .POST
        case .UpdateUser:
            return .PUT
        case .DestroyUser:
            return .DELETE

        }

    }

    var URLRequest: NSMutableURLRequest {

        let httpRequest = NSMutableURLRequest(URL: URL)
        httpRequest.HTTPMethod = method.rawValue

        switch self{

        case .CreateUser (let userInfo):
            print("creating")
            print(httpRequest.HTTPMethod) //Print: POST on CreateUser, like it should.
            return Alamofire.ParameterEncoding.JSON.encode(httpRequest, parameters: userInfo).0
        default:
            return Alamofire.ParameterEncoding.URL.encode(httpRequest, parameters: (route.parameters ?? [ : ])).0

        }

    }

}

func testRoute(){

   Alamofire.request(UserRouter.CreateUser(["name":"test"])).responseJSON{ (response) in

        switch response.result{

        case .Success(let data):
            print (data) //Error here, printing GET response instead of my API response for creating users (POST).
        case .Failure:
            print("fail")
        }

    }

}

【问题讨论】:

    标签: swift alamofire


    【解决方案1】:

    原来问题是Alamofire.request() 生成的命令(curl -i -X POST...)和我的 Apache 如何处理 URL 的尾部斜杠的组合。所以当我尝试POST "http://192.168.0.106/users"时,我被重定向(301)到GET "http://192.168.0.106/users"

    所以我必须在我的 .htaccess 中包含这行命令:

    # Redirect Trailing Slashes...
    RewriteCond %{REQUEST_URI} !(.*)/$
    RewriteRule ^(.*)/$ /$1 [L,R=301]
    

    并更改我的路由器代码,始终在末尾附加一个斜杠:

    var route: String {
    
            switch self{
    
            case .Users:
                return ""
            case .ReadUser(let userID):
                return "/\(userID)/"
            case .CreateUser:
                return "/"
            case .UpdateUser(let userID):
                return "/\(userID)/"
            case .DestroyUser(let userID):
                return "/\(userID)/"
            }
    
        }
    

    【讨论】:

      【解决方案2】:

      这将生成一个 JSON POST 请求。您确定您的 Web 服务正在等待 JSON 请求吗?确保不要将 Web 服务返回 JSON 响应的事实与请求格式混为一谈。

      如果您的 Web 服务期待标准 POST 请求(即带有 application/x-www-form-urlencodedContent-Type 的请求),您也可以将 URL 用于 .CreateUser

      var URLRequest: NSMutableURLRequest {
      
          let httpRequest = NSMutableURLRequest(URL: URL)
          httpRequest.HTTPMethod = method.rawValue
      
          switch self {
          case .CreateUser (let userInfo):
              return Alamofire.ParameterEncoding.URL.encode(httpRequest, parameters: userInfo).0
          default:
              return Alamofire.ParameterEncoding.URL.encode(httpRequest, parameters: (route.parameters ?? [ : ])).0
          }
      
      }
      

      如果您对请求是否正确创建有疑问,我发现Charles 等工具可用于确认发送到网络服务的准确请求。

      【讨论】:

      • 你好@Rob。它没有用。我下载了查尔斯并检查了请求。使用我的应用程序时,我得到了 GET 作为方法,使用 Postman 我得到了 POST 作为方法。我使用 Laravel 5.2 创建我的 web 服务,我不知道这是否是相关信息。
      • 那么,我建议除了您在代码示例中包含的内容之外,还有其他事情正在发生。当我执行Alamofire.request(UserRouter.CreateUser(["name":"test"])). ... 时,我得到了正确的POST 请求。这就是为什么我突然想到您的服务可能真的期待application/x-www-form-urlencoded 请求。顺便说一句,在您的 Postman 中,您是发送 JSON 请求并获得 JSON 响应,还是请求 application/x-www-form-urlencoded?如果您的请求确实是 JSON,那么我将删除此答案。
      • 我为我的请求截取了这些截图,第一个来自邮递员:http://imgur.com/a/N2DMx。我真的不知道发生了什么事。 (我不认为你应该删除你的答案,查尔斯是一个很好的提示)
      • 我的问题是请求的Content-Type。 Charles "Overview" 选项卡向我们显示了响应的Content-Type。单击“请求”选项卡并查看原始内容或标题并确认邮递员的POST 请求的content-type。与您的 Alamofire 请求进行比较和对比。
      • 在 Postman 中我尝试使用 form-datax-www-form-urlencoded,都得到了预期的结果。我认为问题不在于内容类型,因为我的应用请求在我的 Web 服务中以 GET 形式到达。你知道如何调试来自 Alamofire 的请求,以便检查它是否作为 POST 方法离开?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-25
      相关资源
      最近更新 更多