背景
网上搜到的关于SDWebImage 添加 token,亦或者 SDWebImage add header的方法,都是直接使用SDWebImageDownloader
中的setValue:forHTTPHeaderField:
方法来设置。但是设置了之后笔者这边图片还是出不来,仔细研究后发现笔者这边的图片显示是先经过一次302跳转,然后跳转后才是真正的图片链接,第二次的这个链接是需要 token 的。
而直接设置SDWebImageDownloader
的HTTPHeaderField
设置到了第一个链接上面,302重定向后第二个链接的HTTPHeaderField
仍是没有 token
解决方法
一般来说,直接使用SDWebImageDownloader
中的setValue:forHTTPHeaderField:
方法设置即可。如下:
1 |
|
对于经过302重定向的链接,则需要如下修改:
打开SDWebImageDownloader.m
类,修改- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler
方法如下:
1 |
|
原理:简单的说是把 重定向的request 变为 CustomRequest, 然后给 CustomRequest 添加 header,最后回调 CustomRequest,而给 CustomRequest 设置 Header的方法,是使用SDWebImageDownloader
中setValue:forHTTPHeaderField:
设置的。
优化
上面的方法需要直接修改 SDWebImage
类库,如果后续更新类库,则可能丢失或者每次都要修改一次。所以需要一个更好的解决方法:
使用 SwizzleMethod
hook替换 SDWebImageDownloader.m
类中- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler
这个方法,代码如下:
1 | // 使用 Aspects 库 |
更进一步,假如某些图片链接需要token,某些不需要,要怎么处理。只修改上面的方法不行,因为上面的方法只有重定向 URL 才会访问,非重定向的链接不会走上面的方法,所以需要找到非重定向的链接走的方法,然后在那个方法里处理。
查看 SDWebImageDownloader
类中的方法后发现,在请求的 header 的赋值是在createDownloaderOperationWithUrl:options:context:
方法中,如下:
1 | xxx |
而给链接添加 token 的方法是全局调用的,传值 token 到 header 中,所以想要控制某些链接不加 token,某些添加,就需要在createDownloaderOperationWithUrl:options:context:
这个方法之前控制,使用 AspectPositionBegore参数,hook这个方法保证在header赋值到 request之前,判断域名决定是否添加 token,代码如下:
1 |
|
完整代码如下:
1 |
|