Skip to content

Commit 0a2beb9

Browse files
authored
fix: crash when swizzle almofire uploadTask (#873)
1 parent ad99bee commit 0a2beb9

File tree

1 file changed

+56
-28
lines changed

1 file changed

+56
-28
lines changed

Sources/Instrumentation/URLSession/URLSessionInstrumentation.swift

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -202,36 +202,64 @@ public class URLSessionInstrumentation {
202202
}
203203
}
204204

205-
private func injectIntoNSURLSessionCreateTaskWithParameterMethods() {
206-
let cls = URLSession.self
207-
[
208-
#selector(URLSession.uploadTask(with:from:)),
209-
#selector(URLSession.uploadTask(with:fromFile:))
210-
].forEach {
211-
let selector = $0
212-
guard let original = class_getInstanceMethod(cls, selector) else {
213-
print("injectInto \(selector.description) failed")
214-
return
215-
}
216-
var originalIMP: IMP?
217-
218-
let block:
219-
@convention(block) (URLSession, URLRequest, AnyObject) -> URLSessionTask = { session, request, argument in
220-
let sessionTaskId = UUID().uuidString
221-
let castedIMP = unsafeBitCast(originalIMP,
222-
to: (@convention(c) (URLSession, Selector, URLRequest, AnyObject)
223-
-> URLSessionDataTask).self)
224-
let instrumentedRequest = URLSessionLogger.processAndLogRequest(request, sessionTaskId: sessionTaskId, instrumentation: self,
225-
shouldInjectHeaders: true)
226-
let task = castedIMP(session, selector, instrumentedRequest ?? request, argument)
227-
self.setIdKey(value: sessionTaskId, for: task)
228-
return task
205+
private func injectIntoNSURLSessionCreateTaskWithParameterMethods() {
206+
typealias UploadWithDataIMP = @convention(c) (URLSession, Selector, URLRequest, Data?) -> URLSessionTask
207+
typealias UploadWithFileIMP = @convention(c) (URLSession, Selector, URLRequest, URL) -> URLSessionTask
208+
209+
let cls = URLSession.self
210+
211+
// MARK: Swizzle `uploadTask(with:from:)`
212+
if let method = class_getInstanceMethod(cls, #selector(URLSession.uploadTask(with:from:))) {
213+
let originalIMP = method_getImplementation(method)
214+
let imp = unsafeBitCast(originalIMP, to: UploadWithDataIMP.self)
215+
216+
let block: @convention(block) (URLSession, URLRequest, Data?) -> URLSessionTask = { [weak self] session, request, data in
217+
guard let instrumentation = self else {
218+
return imp(session, #selector(URLSession.uploadTask(with:from:)), request, data)
219+
}
220+
221+
let sessionTaskId = UUID().uuidString
222+
let instrumentedRequest = URLSessionLogger.processAndLogRequest(
223+
request,
224+
sessionTaskId: sessionTaskId,
225+
instrumentation: instrumentation,
226+
shouldInjectHeaders: true
227+
)
228+
229+
let task = imp(session, #selector(URLSession.uploadTask(with:from:)), instrumentedRequest ?? request, data)
230+
instrumentation.setIdKey(value: sessionTaskId, for: task)
231+
return task
232+
}
233+
let swizzledIMP = imp_implementationWithBlock(block)
234+
method_setImplementation(method, swizzledIMP)
235+
}
236+
237+
// MARK: Swizzle `uploadTask(with:fromFile:)`
238+
if let method = class_getInstanceMethod(cls, #selector(URLSession.uploadTask(with:fromFile:))) {
239+
let originalIMP = method_getImplementation(method)
240+
let imp = unsafeBitCast(originalIMP, to: UploadWithFileIMP.self)
241+
242+
let block: @convention(block) (URLSession, URLRequest, URL) -> URLSessionTask = { [weak self] session, request, fileURL in
243+
guard let instrumentation = self else {
244+
return imp(session, #selector(URLSession.uploadTask(with:fromFile:)), request, fileURL)
245+
}
246+
247+
let sessionTaskId = UUID().uuidString
248+
let instrumentedRequest = URLSessionLogger.processAndLogRequest(
249+
request,
250+
sessionTaskId: sessionTaskId,
251+
instrumentation: instrumentation,
252+
shouldInjectHeaders: true
253+
)
254+
255+
let task = imp(session, #selector(URLSession.uploadTask(with:fromFile:)), instrumentedRequest ?? request, fileURL)
256+
instrumentation.setIdKey(value: sessionTaskId, for: task)
257+
return task
258+
}
259+
let swizzledIMP = imp_implementationWithBlock(block)
260+
method_setImplementation(method, swizzledIMP)
229261
}
230-
let swizzledIMP = imp_implementationWithBlock(
231-
unsafeBitCast(block, to: AnyObject.self))
232-
originalIMP = method_setImplementation(original, swizzledIMP)
233262
}
234-
}
235263

236264
private func injectIntoNSURLSessionAsyncDataAndDownloadTaskMethods() {
237265
let cls = URLSession.self

0 commit comments

Comments
 (0)