Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Post request with parameters in both body and url #909

Closed
kristiyandobrev opened this issue Jan 8, 2017 · 10 comments
Closed

Post request with parameters in both body and url #909

kristiyandobrev opened this issue Jan 8, 2017 · 10 comments
Labels

Comments

@kristiyandobrev
Copy link

kristiyandobrev commented Jan 8, 2017

I am not entirely sure if that is an issue but please feel free to prove me wrong.

What I am trying to achieve is to make a POST request to an API. The first thing is that I have to provide the TOKEN for the API, encodend in the url like:

http://awesomeapi.com?token=mytoken

Unfortunately the API I am calling, is made in a way so that it accepts the token only if it's a URL encoded parameter.

Next thing is I have to send a parameters in a JSON body like :

{
    param1: value,
    param2: value
}

So in general I have to make a POST request and provide both URL encoded parameters and body parameters.

While researching about an answer I came into Issue 431, where the author is trying to achieve the same, but I can not see a straightforward answer to his question.

Reading the docs make me think that having parameters in the request body and as URL encoded is of course possible in separate requests, but having them combined in one is not or at least not documented yet. Am I right about that ? If not, can you provide an example of how can this be done ?

@bjarkehs
Copy link
Contributor

bjarkehs commented Jan 8, 2017

You can change the used ParameterEncoding. An idea could be to create a ParameterEncoding like:

public struct TokenEncoding: ParameterEncoding {
    public let token: String
    private let urlEncoding = URLEncoding(destination: .methodDependent)

    init(token: String) {
        self.token = token
    }

    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        // use URLEncoding to encoding parameters
        // use something like URLEncoding's implementation to add token to URL.
        // URLEncoding can be found here: https://github.com/Alamofire/Alamofire/blob/master/Source/ParameterEncoding.swift#L70
    }
}

This does require that token stays the same I guess. Another way could have it pull out token from passed parameters and then treat the token parameter in a special way. Mind you all of this code has not been tested in any way.

@scottrhoyt
Copy link
Contributor

As @bjarkehs suggests, writing a custom ParameterEncoding could be a great idea. However, I might prefer searching for a token parameter to in parameters to url encode and then encode the rest as JSON--as opposed to taking the token as an initializer argument. However, that's a personal style and use case decision.

Another option would be to create a PluginType to do this. It would work similarly to AccessTokenPlugin so take a look here for docs and here for implementation.

@pedrovereza
Copy link
Member

I'll close this issue since it's been inactive for a while. Feel free to reopen if you still have questions, @kristiyandobrev

@kristiyandobrev
Copy link
Author

@pedrovereza I just came to a similar issue again, so I consider re-openning the issue again, since I am uncertain if it's possible to make for example POST or PUT request to api/resource/:id and pass a json body out of the box, without any additional implementation, as it was suggested above.

@pedrovereza
Copy link
Member

@kristiyandobrev I think what you're looking for is what @scottrhoyt suggested:

I might prefer searching for a token parameter to in parameters to url encode and then encode the rest as JSON.

Basically, if you have an endpoint like:

enum API {
    case example(id:String, name:String, lastName: String)
}

In order to make a request to api/resource/:id passing name and lastName as json body, you have to:

  • Encode id on the url
    public var path: String {
        switch self {
        case .example(let id, _, _):
            return "api/resource/\(id)"
        }
    }
  • Pass name and lastName as parameters
    public var parameters: [String : Any]? {
        switch self {
        case .example(let _, let name, let lastName):
            return ["name": name, "lastName": lastName]
        }
    }
  • Encode parameters as json
    public var parameterEncoding: Moya.ParameterEncoding { 
        switch self {
        case .example:
            return JSONEncoding.default 
        }
   }

@pedrovereza
Copy link
Member

@kristiyandobrev were you able to make the request as you wanted?

@kristiyandobrev
Copy link
Author

Yes. Thanks for the help .

@AhmAbdallah
Copy link

AhmAbdallah commented Jan 4, 2020

I want to call this https://www.blaalb.com/restApi/testApi/myOrders?number=1&month=24

enum MyWebService {
    switch self {
       case getMyOrders(number: Int, month: Int)
   }
}

var path: String {
   switch self {
      case . getMyOrders:
      return "/myOrders"
     }
  }
}

var method: Moya.Method {
     switch self {
      case .getMyOrders:
      return .get
   }
}

var task: Task {
    switch self {
      case . getMyOrders(let number, let month):
      let p = ["number" : number,
               "month": month]
    return .requestParameters(parameters:p , encoding: URLEncoding.default)
 }
}

@zohairhadi
Copy link

zohairhadi commented Oct 25, 2020

Can you please help with the comment by @AhmAbdallah , it will help many others as well.
I have a similar problem where I need to send parameters in both body and url

@sunshinejr
Copy link
Member

@zohairhadi you should be able to do that easier now, with the Task type we have: Task..requestCompositeParameters(bodyParameters:bodyEncoding:urlParameters), which allow you to combine url encoded parameters with another type (data / parameters).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants