3

Disclaimer: I'm new to iOS programming, so this question is probably as simple as it looks. It's not a trick question!

I've a Swift project that uses Almofire to send HTTP requests. I want to add a parameter to the query string for every single request made.

So, I want to add mykey=myval to every request.

  • EG: http://example.com/index -> http://example.com/index?mykey=myval
  • EG: http://example.com/index?key=val -> http://example.com/index?key=val&mykey=myval

I have found that all requests seem to go through

public func request(URLRequest: URLRequestConvertible) -> Request {
    return Manager.sharedInstance.request(URLRequest.URLRequest)
}

in a file named Almofire.swift

and also through

public func request(URLRequest: URLRequestConvertible) -> Request {
    var dataTask: NSURLSessionDataTask?
    dispatch_sync(queue) {
        dataTask = self.session.dataTaskWithRequest(URLRequest.URLRequest)
    }

    let request = Request(session: session, task: dataTask!)
    delegate[request.delegate.task] = request.delegate

    if startRequestsImmediately {
        request.resume()
    }

    return request
}

in a file named Manager.swift, so I'm presuming I need to add a bit of code here. Due to my lack of Swift knowledge I've spend hours experimenting but no joy - only exceptions.

Does anyone know how I can add a parameter to all requests?

nhgrif
  • 61,578
  • 25
  • 134
  • 173
Mr. Flibble
  • 26,564
  • 23
  • 69
  • 100

3 Answers3

3

You don't need to change anything in Alamofire's code. Instead you can use the URLRequestConvertible protocol to encapsulate your URLs and parameter in an enum:

enum Router: URLRequestConvertible {
    static let baseURLString = "https://example.com" // define your base URL here
    static var defaultParams = ["myKey": "myValue"] // set the default params here

    // define a case for every request you need
    case Index
    case Endpoint1(param: String)
    case Endpoint2(param1: String, param2: String)

    var URLRequest: NSMutableURLRequest {
        let result: (path: String, parameters: [String: AnyObject]) = {
            // set the path and params for each request
            switch self {
            case .Index:
                return ("/index", Router.defaultParams)
            case .Endpoint1(let param):
                var params = Router.defaultParams
                params.updateValue(param, forKey: "key")
                return ("/endpoint", params)
            case .Endpoint2(let param1, let param2):
                var params = Router.defaultParams
                params.updateValue(param1, forKey: "key1")
                params.updateValue(param2, forKey: "key2")
                return ("/endpoint2", params)
            }
        }()

        // create the URL and the request
        let URL = NSURL(string: Router.baseURLString)!
        let URLRequest = NSURLRequest(URL: URL.URLByAppendingPathComponent(result.path))
        let encoding = Alamofire.ParameterEncoding.URL

        return encoding.encode(URLRequest, parameters: result.parameters).0
    }
}

Then you can call your requests in the following matter:

// sends a request to 'https://example.com/index?myKey=myValue'
Alamofire.request(Router.Index).response { (request, urlResponse, data, error) -> Void in
    // handle response
}

// sends a request to 'https://example.com/endpoint?key=value&myKey=myValue'
Alamofire.request(Router.Endpoint1(param: "value")).response { (request, urlResponse, data, error) -> Void in
    // handle response
}

// sends a request to 'https://example.com/endpoint2?key1=value1&key2=value2&myKey=myValue'
Alamofire.request(Router.Endpoint2(param1: "value1", param2: "value2")).response { (request, urlResponse, data, error) -> Void in
    // handle response
}
joern
  • 27,354
  • 7
  • 90
  • 105
  • thanks for that. I understand that I'll lose my changes if the file gets overwritten. I can create a wrapper on Almofire that has the same method signatures and put my changes there. But I still need to know how to add to the request after the request has been created. – Mr. Flibble Oct 09 '15 at 14:27
  • Please see my updated answer for a solution to your issue. – joern Oct 09 '15 at 19:41
0

Simple request ->

func someFunction()
{
    Alamofire.request(.GET, "apiName", parameters:["Key":"Value"])
        .response { request, response, data, error in
            if error == nil {
                print(request)
                print(response)
            }
            else {
                //Display Error Message
                print(error)
            }

    }
}
Kakshil Shah
  • 3,466
  • 1
  • 17
  • 31
0

This is another solution of adding default parameters to every urlRequest. You have to create your class that conforms to RequestInterceptor protocol, and define "adapt" method:

class UserRequestInterceptor: RequestInterceptor {
        static var defaultParameters = ["mykey": "myval"]
        
        public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
            var urlRequest = urlRequest
            
            let encoding = URLEncodedFormParameterEncoder.default
            if let request = try? encoding.encode(UserRequestInterceptor.defaultParameters, into: urlRequest) {
                urlRequest = request
            }
            
            completion(.success(urlRequest))
        }
    }

and when you decide to create an URL request you have to add "interceptor" parameter:

func userFunction()
    {
        AF.request("http://example.com/index", method: .get,
                   interceptor: UserRequestInterceptor()) // this line will be add all default params to every request
            .response { response in
                // ...
            })
    }

or you can create new Alamofire Session and init it with UserRequestInterceptor:

class UserClass {   
    let afSession = Session(interceptor: GlobusPro.SDK.GlobusProRequestInterceptor())
   ...
    func userFunction()
    {
        afSession.request("http://example.com/index", method: .get) 
            .response { response in
                // ...
            })
    }
}
slavik
  • 1,341
  • 2
  • 11
  • 16