Hey guys! If I understand it correctly, in Alamofire 5 all the underlying requests in the Request type are being created asynchronously. Because of that we can't really do anything just before the request is executed (e.g. log request info to the console), like it was in Alamofire 4 (we could synchronously access the request property).
From what I've gathered there is an Adapter, but:
URLRequest? property - it would be really great to have an access to its parent Request typeI was thinking if something like this would be a viable addition to Alamofire and/or if there is something that I missed that we can do already. Cheers!
Hi @sunshinejr,
Great question! I'm wondering this a bit myself as @jshier was the main driver behind the async change. You could certainly create an EventMonitor to be notified when the URLSessionTask is actually created, but that's a bit clunky IMO. Almost seems like we need a chainable API or something to be able to do a print(request) internally when the task is created.
Interested to get your thoughts @jshier...
EventMonitor was designed for exactly this use. In fact, I've used it myself to easily add logging of all requests and responses (including generic responses) with only a few lines of code.
final class LoggingMonitor: EventMonitor {
func requestDidResume(_ request: Request) {
print("Request started: \(request)")
let body = request.request.map { $0.httpBody.map { String(decoding: $0, as: UTF8.self) } ?? "No body." }
print("Body data: \(body)")
}
func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value>) {
debugPrint(response)
let body = request.data.map { String(decoding: $0, as: UTF8.self) } ?? "No body."
print("[Body]: \(body)")
}
}
This allows easy logging of every request made and response received. There are many other events to tap into, and I think more will be added before Alamofire 5 has shipped due to additional features.
As for per-Request monitoring, Request already takes its own EventMonitor reference. We would just need to refactor that, perhaps with a protocol that only supports Request events, and add the chainable API. However, I'd consider that low priority.
@cnoon @jshier thanks so much for a quick update! I didn't see that Request has its own EventMonitor and I think it's almost what I wanted. I just don't think that Request needs a whole EventMonitor protocol in it - maybe we could split this into RequestEventMonitor protocol and so on?
Also, while requestDidResume is great, I would love to have requestWillResume as well. This could help when you just want to log request & cancel if needed. Or if you want to validate everything just before firing it up.
Let me know if this makes sense. I could help implementing that as well :)
@sunshinejr Can you describe the use cases you have in mind in more detail? Also, feel free to take a look at the EventMonitor API and see what additional events might make sense. Personally, I'm not sure will counterparts to every did event would make sense.
@jshier yeah I don't think that adding will to every did counterpart is needed as well.
I think the only event I would love to have right now would be the requestWillResume. Mainly because of the fact that I don't think that there is a place currently that gives you an access to the Request object with produced urlRequest that is about to be fired. And the main use-case for that would be cancellation.
Because Alamofire 5 is producing underlying requests asynchronously, and there are all sorts of adapters that could be producing new urlRequests, I want to be able to cancel the request before it hits the network but after it finishes its underlying work.
I also would like to check if the request I'm firing has everything I wanted in it (for debugging and such) and so on - I believe that giving me the notification after it resumed is just not enough.
@jshier @cnoon what do you guys think?
@sunshinejr I'm still interested in an actual use case for a requestWillResume event. There are other events that fire earlier in the request lifecycle already, including a few during and after the URLRequest creation process, so why would this event be necessary? Additionally, while it's easy to imagine your use case, I'd like some specific examples. Why would anyone need to cancel a request that's been enqueued but not started, and why would they need to do it from an EventMonitor and not just cancel the Request directly?
We won't be adding such an event for the 5.0 release. If a compelling use case is found and there's a good point to add this event, we can do so in a minor release.