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

Add additional parameters to all requests #1482

Closed
aelam opened this issue Nov 28, 2017 · 13 comments
Closed

Add additional parameters to all requests #1482

aelam opened this issue Nov 28, 2017 · 13 comments

Comments

@aelam
Copy link

aelam commented Nov 28, 2017

Now we want to set a group of parameters for all requests NOT in headers,
Is there any way I can do it ?

@pietrocaselani
Copy link
Member

pietrocaselani commented Nov 28, 2017

What kind of parameters do you want to send? Query parameters?
You could look at this document and maybe use the endpointClosure or requestClosure.
Let us know if you need any help.

@aelam
Copy link
Author

aelam commented Nov 29, 2017

Thanks for your reply!!

endpointClosureand requestClosure are easy to append headers but hard to append parameters

If I want to insert a group of default parameters
Take platform=app1, appVersion=1.0 as an example.
If it's GET I will append to the end of URL, if it's POST I need encode the parameter. the ParameterEncode is same as the origin request which set in Target, JSON or urlencode or anything else

I've look into Moya a lot of times
Seems I have to override the Endpoint methods to append them
If I have to override the Endpoint, I have to give up Moya
Do you have any ideas?

extension Endpoint {
    /// Returns the `Endpoint` converted to a `URLRequest` if valid. Returns `nil` otherwise.
    public var urlRequest: URLRequest? {
        guard let requestURL = Foundation.URL(string: url) else { return nil }

        var request = URLRequest(url: requestURL)
        request.httpMethod = method.rawValue
        request.allHTTPHeaderFields = httpHeaderFields

        switch task {
        case .requestPlain, .uploadFile, .uploadMultipart, .downloadDestination:
            return request
        case .requestData(let data):
            request.httpBody = data
            return request
        case let .requestParameters(parameters, parameterEncoding):
            return try? parameterEncoding.encode(request, with: parameters)
        case let .uploadCompositeMultipart(_, urlParameters):
            return try? URLEncoding(destination: .queryString).encode(request, with: urlParameters)
        case let .downloadParameters(parameters, parameterEncoding, _):
            return try? parameterEncoding.encode(request, with: parameters)
        case let .requestCompositeData(bodyData: bodyData, urlParameters: urlParameters):
            request.httpBody = bodyData
            return try? URLEncoding(destination: .queryString).encode(request, with: urlParameters)
        case let .requestCompositeParameters(bodyParameters: bodyParameters, bodyEncoding: bodyParameterEncoding, urlParameters: urlParameters):
            if bodyParameterEncoding is URLEncoding { fatalError("URLEncoding is disallowed as bodyEncoding.") }
            guard let bodyfulRequest = try? bodyParameterEncoding.encode(request, with: bodyParameters) else { return nil }
            return try? URLEncoding(destination: .queryString).encode(bodyfulRequest, with: urlParameters)
        }
    }
}

@SD10
Copy link
Member

SD10 commented Nov 29, 2017

In #1283 I talk about creating a plugin that allows parameters to be reused across multiple providers in point 5. This is not something I've tried to implement myself but it may be possible.

@stale
Copy link

stale bot commented Dec 13, 2017

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale label Dec 13, 2017
@stale
Copy link

stale bot commented Dec 20, 2017

This issue has been auto-closed because there hasn't been any activity for at least 21 days. However, we really appreciate your contribution, so thank you for that! 🙏 Also, feel free to open a new issue if you still experience this problem 👍.

@stale stale bot closed this as completed Dec 20, 2017
@sunshinejr sunshinejr removed the stale label Jan 10, 2018
@sunshinejr
Copy link
Member

sunshinejr commented Jan 10, 2018

Hey @aelam, you are right - it's not that simple to append parameters to all requests. Whenever I’ll find time I will post a function that I was using to achieve this. Adding this to my todo-list as we speak. Sorry for the troubles!

@BasThomas
Copy link
Contributor

I'll reopen so we can keep track 👍

@BasThomas BasThomas reopened this Jan 10, 2018
@stale
Copy link

stale bot commented Jan 24, 2018

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale label Jan 24, 2018
@SD10
Copy link
Member

SD10 commented Jan 24, 2018

I’d like this to remain open

Sent with GitHawk

@stale stale bot removed the stale label Jan 24, 2018
@sunshinejr
Copy link
Member

sunshinejr commented Jan 27, 2018

Hey @aelam, sorry for the wait. Here is the endpointClosure that you could use to built your own version. Basically we don't really introduce a function to append parameters to all targets as there are lots of undefined behaviors (as you will see in the code below). You need to have a domain specific knowledge to build your own version, where in older versions the behavior was mostly done by us under the hood and we had multiple issues asking why is something done this way and not another (in upload especially).

let endpointClosure1: MoyaProvider<HTTPBin>.EndpointClosure = { target in
    let additionalParameters = ["Additional": "Parameter"]
    let defaultEncoding = URLEncoding.default
    let task: Task

    switch target.task {
    case let .downloadDestination(destination):
        // First decision: what encoding to use when there wasn't one before
        task = .downloadParameters(parameters: additionalParameters, encoding: defaultEncoding, destination: destination)
    case .downloadParameters(var parameters, let encoding, let destination):
        additionalParameters.forEach { parameters[$0.key] = $0.value }
        task = .downloadParameters(parameters: parameters, encoding: encoding, destination: destination)
    case .requestCompositeData(let bodyData, var urlParameters):
        // Second decision: encode data and append the parameters there or append parameters to urlParameters?
        additionalParameters.forEach { urlParameters[$0.key] = $0.value }
        task = .requestCompositeData(bodyData: bodyData, urlParameters: urlParameters)
    case .requestCompositeParameters(let bodyParameters, let bodyEncoding, var urlParameters):
        // Third decision: where to append parameters here, body or url?
        additionalParameters.forEach { urlParameters[$0.key] = $0.value }
        task = .requestCompositeParameters(bodyParameters: bodyParameters, bodyEncoding: bodyEncoding, urlParameters: urlParameters)
    case let .requestData(data):
        task = .requestCompositeData(bodyData: data, urlParameters: additionalParameters)
    case let .requestJSONEncodable(encodable):
        // You would have to create data from `encodable`, encode it to JSON object, then append parameters
        // and make Data from it - and assign .requestData to the task
        task = target.task
    case .requestParameters(var parameters, let encoding):
        additionalParameters.forEach { parameters[$0.key] = $0.value }
        task = .requestParameters(parameters: parameters, encoding: encoding)
    case .requestPlain:
        task = .requestParameters(parameters: additionalParameters, encoding: defaultEncoding)
    case .uploadCompositeMultipart(let multipartData, var urlParameters):
        additionalParameters.forEach { urlParameters[$0.key] = $0.value }
        task = .uploadCompositeMultipart(multipartData, urlParameters: urlParameters)
    case let .uploadFile(url):
        // Another decision: where to add it with upload? in multipart data, or url?
        let data = Moya.MultipartFormData(provider: .file(url), name: "file")
        task = .uploadCompositeMultipart([data], urlParameters: additionalParameters)
    case let .uploadMultipart(multipartData):
        task = .uploadCompositeMultipart(multipartData, urlParameters: additionalParameters)
    }

    return Endpoint<HTTPBin>(url: URL(target: target).absoluteString, sampleResponseClosure: {.networkResponse(200, target.sampleData)}, method: target.method, task: task, httpHeaderFields: target.headers)
}

@stale
Copy link

stale bot commented Feb 10, 2018

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale label Feb 10, 2018
@stale
Copy link

stale bot commented Feb 17, 2018

This issue has been auto-closed because there hasn't been any activity for at least 21 days. However, we really appreciate your contribution, so thank you for that! 🙏 Also, feel free to open a new issue if you still experience this problem 👍.

@stale stale bot closed this as completed Feb 17, 2018
@D-james
Copy link

D-james commented Mar 19, 2021

same question, How to add common parameters?

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

No branches or pull requests

6 participants