Alamofire 4 sends method as POST but server reads it GET - swift

I have a very weird problem here, using Alamofire 4 Swift 4 Xcode 9.1
let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 30
manager.session.configuration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
let request = manager.request(
url,
method: HTTPMethod.post,
parameters: [:])
But server replies with method not allowed because it reads it as GET, however, if I change HTTPMethod.put or .delete or any other method, the server reads it correctly, the problem is with post specifically!
By debugging Alamofire's class 'SessionManager', specially the following method:
open func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil)
-> DataRequest
The method here is correct, POST, so it's just fine before it goes out the application, what's wrong?

It was adding '/' at the end of the URL that was causing this.

Related

Alamofire session configurations are not reflected in the request

Alamofire Version: 5.1
We are modifying our alamofire session configuration as following:
let apiManager: Session = {
let configuration = URLSessionConfiguration.af.default
configuration.timeoutIntervalForRequest = 20
configuration.requestCachePolicy = .reloadIgnoringCacheData
configuration.urlCache = nil
let manager = Alamofire.Session(
configuration: configuration,
cachedResponseHandler: ResponseCacher(behavior: .doNotCache)
)
return manager
}()
And we are making the request as following
apiManager.request(
url,
method: .post,
parameters: requestBodyParameters,
encoding: JSONEncoding.default,
headers: generateHeaders(enableAuth: authorisation) // to generate headers
)
.validate(statusCode: 200..<300)
.responseJSON { response in
print(response)
}
}
}
But the request configurations is not updated, they remain at default values
[Timeout]
60
[Cache policy]
UseProtocolCachePolicy
You're looking at the URLRequest generated by Alamofire which doesn't include the URLSession-level configuration, and which will never reflect the cache customization. If you want to see the actual URLRequest being performed after it passes through both Alamofire and URLSession, you can access the latest URLSessionTask that the Alamofire Request (in this case a DataRequest) performed by using request.task. However, like I said, this will never reflect the other behaviors you've attached, like a ResponseCacher, since those exist outside of the request pipeline.

How to get original requests in Alamofire 5?

I made a wrapper for Alamofire which makes the data request first and then it prints the details of original URLRequest.
let dataRequest = session.request(url, method: .get, parameters: parameters)
let originalRequest = dataRequest.request
// Now print somehow the details of original request.
It worked fine on Alamofire 4.9, but it stopped in the newest 5.0 version. The problem is that dataRequest.request is nil. Why this behavior has changed? How can I access URLRequest underneath DataRequest?
URLRequests are now created asynchronously in Alamofire 5, so you're not going to be able to access the value immediately. Depending on what you're doing with the URLRequest there may be other solutions. For logging we recommend using the new EventMonitor protocol. You can read our documentation to see more, but adding a simple logger is straightforward:
final class Logger: EventMonitor {
let queue = DispatchQueue(label: ...)
// Event called when any type of Request is resumed.
func requestDidResume(_ request: Request) {
print("Resuming: \(request)")
}
// Event called whenever a DataRequest has parsed a response.
func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {
debugPrint("Finished: \(response)")
}
}
let logger = Logger()
let session = Session(eventMonitors: [logger])
I had to obtain the URLRequest in a test case. Solved it by adding .responseData and using XCTestExpectation to wait for the async code to return:
func testThatHeadersContainContentEncoding() {
let exp = expectation(description: "\(#function)\(#line)")
let request = AF.request("http://test.org",
method: .post, parameters: ["test":"parameter"],
encoding: GZIPEncoding.default,
headers: ["Other":"Header"])
request.responseData { data in
let myHeader = request.request?.value(forHTTPHeaderField: additionalHeader.dictionary.keys.first!)
// .. do my tests
exp.fulfill()
}
waitForExpectations(timeout: 10, handler: nil)
}

Alamofire with YouTube API Issues (Swift 3)

I'm having some trouble converting my old Alamofire code to the new Swift 3 version. I'm getting the error: Extra argument 'method' in call
// Fetch the videos dynamiclly through the YouTube Data API
Alamofire.request("https://www.googleapis.com/youtube/v3/playlistItems", method: .get, parameters: ["part":"snippet", "playlistId":UPLOADS_PLAYLIST_ID,"key":API_KEY], encoding: ParameterEncoding.URL, headers: nil)
Can someone help me with this?
The problem is not in the method argument but in the encoding which you can set to URLEncoding.default also since the header is nil then i guess you dont need it
let parameters: Parameters = ["part":"snippet",
"playlistId":UPLOADS_PLAYLIST_ID,
"key":API_KEY]
let url = "https://www.googleapis.com/youtube/v3/playlistItems"
Alamofire.request(url,
method: .get,
parameters: parameters,
encoding: URLEncoding.default)
.responseData(completionHandler: { response in
//do what you want
})
by the way you can change responseData back to what you already have

Issue with Alamofire Request

I am trying to use Alamofire to make a web request. It had been working absolutely fine, but after doing a recent pod update it has stopped.
My syntax is:
var params = [String : Any]()
if (data != nil) {
params = try! JSONSerialization.jsonObject(with: data!, options: []) as! [String : Any]
}
let _ = Alamofire.request( "http://example.com" , method: Method, parameters: params?, encoding: .queryString, headers: [:]).response{ (request, response, data, error) in
}
the error looks is "Extra argument 'method' in call" and I don't seem to be able to get rid of it. My parameters of the request to Alamofire.request seem ok to me, but clearly I am missing something.
You're not passing anything to the method parameter. I don't know what you're trying to provide in the encoding parameter either but that went through some changes in Alamofire 4.0. For example and for simplicity's sake, this compiles:
let _ = Alamofire.request( "http://example.com" , method: HTTPMethod.get, parameters: nil, encoding: JSONEncoding.default, headers: nil)

EXC_BAD_ACCESS Error In App, Alamofire 3.1.2

I'm running Xcode 7.1, with an iOS device on 9.1, and the latest version of Alamofire, I believe it's 3.1.2.
I've seen others with similar errors - this one from SO and this one from their Github issues page - to mine, but the resolutions did not work for me. The resolutions that worked in these scenarios seemed to be deleting the DerivedData folders, but that doesn't work in my situation.
The issue is that I can make web requests with Alamofire when I run in the simulator, but I get the following error (in the image) when I install the application on my device.
I've tried using a device running 9.1, 9.0.1 and 8.3. All of these devices crash when I attempt to make the web request. I'm stuck on this and I've made no headway. This worked until I updated all my pods in my podfile and my Xcode version a couple of nights ago.
I'm a newbie at iOS development, so if you need to see more error logs or things of that nature, let me know and I'll do my best to get you those. Any help is appreciated.
Edit: Adding code for the Alamofire.request method as requested. Also adding code for the referenced Manager.sharedInstance.request method. These are methods within the Alamofire library itself.
// Alamofire.request
public func request(
method: Method,
_ URLString: URLStringConvertible,
parameters: [String: AnyObject]? = nil,
encoding: ParameterEncoding = .URL,
headers: [String: String]? = nil)
-> Request
{
return Manager.sharedInstance.request(
method,
URLString,
parameters: parameters,
encoding: encoding,
headers: headers
)
}
// Manager.sharedInstance.request
public func request(
method: Method,
_ URLString: URLStringConvertible,
parameters: [String: AnyObject]? = nil,
encoding: ParameterEncoding = .URL,
headers: [String: String]? = nil)
-> Request
{
let mutableURLRequest = URLRequest(method, URLString, headers: headers)
let encodedURLRequest = encoding.encode(mutableURLRequest, parameters: parameters).0
return request(encodedURLRequest)
}
One problem is that stringByAddingPercentEncodingWithAllowedCharacters returns an optional, and when you do string interpolation, you're going to get Optional(...) appearing in the string. Thus when it tries to create a URL from that, it's undoubtedly failing. Print the uri string and you'll see the issue. E.g., if the searchTerm was "foo bar", the uri would become:
https://api.spotify.com/v1/search&q=Optional("foo%20bar")&type=artist,album,track
But that's not correct. Add a ! to the end of the expression to unwrap it:
let searchTermEncoded = searchTerm.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
And then the URI will be (largely) correct.
--
I'd suggest not doing this percent escaping yourself (as the character set you're using is not correct, even once you do properly unwrap searchTermEncoded). Let Alamofire do this for you:
let urlString = "https://api.spotify.com/v1/search"
let parameters = ["q" : searchTerm, "type" : "artist,album,track"]
Alamofire.request(.GET, urlString, parameters: parameters)
.responseJSON { response in
guard response.result.error == nil else {
print(response.result.error)
return
}
print(response.result.value)
}