SDWebImage not working with header property Authorization?

Created on 7 Sep 2017  路  12Comments  路  Source: SDWebImage/SDWebImage

I need to download image with Authorization header. but SDWebImage it is not working with Authorization Header.

error:

Error: Optional(Error Domain=NSURLErrorDomain Code=500 "(null)") : flowing-Url:- https://www.xxxx.world/images/r2.png

Here is Code :

     let manager: SDWebImageDownloader? = SDWebImageManager.shared().imageDownloader
            manager?.setValue("image/png" , forHTTPHeaderField: "Content-Type")
            manager?.setValue(Global.account?.token ?? "" , forHTTPHeaderField: "Authorization")

            _ = manager?.downloadImage(with: url, options: SDWebImageDownloaderOptions.allowInvalidSSLCertificates, progress: { (d, d2, d3) in

                print("loading..") 

            }, completed: { (image, data, error, status) in
                if image != nil{
                    print("finish..")
                    completionHandler(image)
                }else{
                    print("\(error) : flowing-Url:- \(urlString)")
                }
            })

Note: token is not nil and it is also valid on the other hand image download success when I used general url where no need Authorization

UPDate:

flowing code working perfectly:

    var request = URLRequest(url:url!)
    request.setValue("image/png" , forHTTPHeaderField: "Content-Type")
    request.setValue(Global.account?.token ?? "" , forHTTPHeaderField: "Authorization")

    var _urlrequst : URLRequest?
    do{
        _urlrequst =  try  Alamofire.JSONEncoding.default.encode(request)
    }catch let error {
       print(error)
    }

    URLSession.shared.dataTask(with: _urlrequst!,
                               completionHandler: { (data, respones, error) in

        DispatchQueue.main.async(execute: {
            let image = UIImage(data: data!)
                completionHandler(image)
        })
    }).resume()
awaiting response

Most helpful comment

The imageDownloader code works for me, maybe double check your HTTP requests to make sure it looks valid to you:

            if let manager = SDWebImageManager.shared().imageDownloader, let token = CredentialManager.sharedInstance.bearer {
                manager.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
            }

All 12 comments

SDWebImageManager does not support custom HTTP Header. So please use SDWebImageDownloader and use -[SDWebImageDownloader setValue:forHTTPHeaderField:] to set this HTTP Header and -[SDWebImageDownloader downloadImageWithURL:options:progress:completed:] to download.

It's OK to use the sharedDownloader, maybe it's the issue related to your request(for example, wrong token) and your image server. The Basic HTTP Authorization Header looks like this: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

not working . do I miss anything?

let url = URL(string: urlString)
        let manager = SDWebImageDownloader()

        manager.setValue("image/png" , forHTTPHeaderField: "Content-Type")
        manager.setValue(Global.account?.token ?? "" , forHTTPHeaderField: "Authorization")

        _ = manager.downloadImage(with: url, options: SDWebImageDownloaderOptions.allowInvalidSSLCertificates, progress: { (d, d2, d3) in

            print("loading..")

        }, completed: { (image, data, error, status) in
            if image != nil{
                print("finish..")
                completionHandler(image)
            }else{
                print("\(error) : flowing-Url:- \(urlString)")
            }
        })

Maybe the token is invalid? Please first check that completion block about error information. Also, you can use some HTTP debug tools(like Charles) to grab the HTTP request, response to find the issue. And, if the image server is hosted by yourself or your company, you can also ask them for help.

Moreover, SDWebImageDownloader provide two properties username and password to support basic HTTP Authorization, maybe it can also be helpful.

Yes I was tested it is working fine here I my test code with token .

```
let url = URL(string: urlString)
var request = URLRequest(url:url!)
request.setValue("image/png" , forHTTPHeaderField: "Content-Type")

    // Adding common parameters//
    if    Global.account?.token != nil {
        request.setValue(Global.account?.token ?? "" , forHTTPHeaderField: "Authorization")

    }

    URLSession.shared.dataTask(with: request,
                               completionHandler: { (data, respones, error) in
                                if error != nil {
                                    print("\(error) : flowing-Url:- \(urlString)")
                                    return
                                }else {
                                    print(respones?.url ?? "")
                                    print(data ?? "")
                                }

                                let imageToCache = UIImage(data: data!)
                                DispatchQueue.main.async(execute: {
                                    completionHandler(imageToCache)
                                })
    }).resume()
but when trying with this SDWebImage 

let url = URL(string: urlString)
let manager = SDWebImageDownloader()

    manager.setValue("image/png" , forHTTPHeaderField: "Content-Type")
    manager.setValue(Global.account?.token ?? "" , forHTTPHeaderField: "Authorization")

    _ = manager.downloadImage(with: url, options: SDWebImageDownloaderOptions.allowInvalidSSLCertificates, progress: { (d, d2, d3) in

        print("loading..")

    }, completed: { (image, data, error, status) in
        if image != nil{
            print("finish..")
            completionHandler(image)
        }else{
            print("\(error) : flowing-Url:- \(urlString)")
        }
    })

```

it is give me error:

Error: Optional(Error Domain=NSURLErrorDomain Code=500 "(null)") : flowing-Url:- https://www.xxxx.world/images/r2.png

You use Alamofire's Alamofire.JSONEncoding.default.encode to encode your request. So the HTTP Request is different from SDWebImage's request. (And this is why I suggest to use some HTTP debug tools because you can check the difference right in your hand)

Alamofire will set Content-Type=application/json and put the parameters in HTTP body. But SDWebImageDownloader will set Content-Type=image/png and put parameters in HTTP URL Query. You should check what actually your image server support and use the right format.

Check Alamofire's JSONEncoding: https://github.com/Alamofire/Alamofire/blob/c8a4d3a910bcfd53b9b855463495b8200ca80fd6/Source/ParameterEncoding.swift#L309

If you also need to JSONEncoding to encode your image request, you can write a little more code like the code above. Or if you really need HTTP Body in the request, you can use alamofire to download (In most case, SDWebImage does not need to set HTTP Body, so SDWebImageDownloader do not expose that as a public API)

I did but current I remove my dependancy with Alamofilre.

also I test it is working fine :

curl -X GET https://www.xxxxxxx.world/images/r8.png -H "Content-Type: image/png" -H 'Authorization: 883a097e-9f4a-4678-8aac-a20146ea2a83'

here is my full working code with token

let imageCache = NSCache<NSString, UIImage>()

class URLSessionImageDownload: ImageDownloadProtocol {

    func downloadImageUsing(_ urlString: String ,
                            completionHandler: @escaping (UIImage?) -> () ){

        let url = URL(string: urlString)
        var request = URLRequest(url:url!)
        request.setValue("image/png" , forHTTPHeaderField: "Content-Type")

        // Adding common parameters//
        if    Global.account?.token != nil {
            request.setValue(Global.account?.token ?? "" , forHTTPHeaderField: "Authorization")

        }

        URLSession.shared.dataTask(with: request,
                                   completionHandler: { (data, respones, error) in
                                    if error != nil {
                                        print("\(error) : flowing-Url:- \(urlString)")
                                        return
                                    }else {
                                        print(respones?.url ?? "")
                                        print(data ?? "")
                                    }

                                    let imageToCache = UIImage(data: data!)
                                    DispatchQueue.main.async(execute: {
                                        completionHandler(imageToCache)
                                    })
        }).resume()

    }

        func removeImageUsingUrlString(_ urlString: String) {
            if imageCache.object(forKey: urlString as NSString) != nil {
                imageCache.removeObject(forKey: urlString as NSString)
                return
            }
        }
}

To identify the network issue, the best way is to check the actual HTTP request and response. If you do not want to try some HTTP debug tools like Charles, you need to grap code to check. You can set an breakpoint at this line: https://github.com/rs/SDWebImage/blob/master/SDWebImage/SDWebImageDownloaderOperation.m#L68 and print the request all informations(including HTTP URL, HTTP HeaderFileds and HTTP Body).

Then use the NSURLSession code you provide above and set an breakpoint to check the same information. Compare these two and find the differences.

Ok I will do ! but I have an question. is there any problem the curl request with SDWebImage?

also I test it is working fine :

curl -X GET https://www.xxxxxxx.world/images/r8.png -H "Content-Type: image/png" -H 'Authorization: 883a097e-9f4a-4678-8aac-a20146ea2a83'

@nazmulkp Maybe the built-in HTTP Header will cause your image server respond 500 ? I found that SDWebImageDownloader set Accept=image/webp,image/*;q=0.8 when WebP enable and Accept=image/*;q=0.8 when disable as default. When you do not have any other solution, you can set that header filed to nil to remove or use that powerful headersFilter property to filter the HTTP Headers.

https://github.com/rs/SDWebImage/blob/master/SDWebImage/SDWebImageDownloader.m#L80

No Luck for me :

I have been trying with

    let manager: SDWebImageDownloader? = SDWebImageManager.shared().imageDownloader
    manager?.setValue("image/webp,image/*;q=0.8" , forHTTPHeaderField: "Accept")
    manager?.setValue(Global.account?.token ?? "" , forHTTPHeaderField: "Authorization")

aslo I was trying to set that header filed to nil

not working same result

The imageDownloader code works for me, maybe double check your HTTP requests to make sure it looks valid to you:

            if let manager = SDWebImageManager.shared().imageDownloader, let token = CredentialManager.sharedInstance.bearer {
                manager.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
            }

closing this due to lack of response. please reopen if you need more info

Was this page helpful?
0 / 5 - 0 ratings