URLSession で http header 情報を確認する

たまに、APIの結果を処理するときに、MIME Typeを見てから確認したいってことはありませんか? 基本的にはjsonが返るAPIだけど、エラー時にはhtmlになるのでjsonかhtmlか判別してから処理をしたいとか。

そんなときにはURLResponseを見てみましょう。

API Headerをみる

まずは、GithubのAPIでheaderを見てみましょう。

$ curl -i https://api.github.com/users/TachibanaKaoru

header情報はこんな感じです。

HTTP/2 200 
server: GitHub.com
date: Tue, 23 Nov 2021 01:14:34 GMT
content-type: application/json; charset=utf-8
cache-control: public, max-age=60, s-maxage=60
x-frame-options: deny
x-content-type-options: nosniff
x-ratelimit-limit: 60
x-ratelimit-remaining: 57
x-ratelimit-reset: 1637633003
x-ratelimit-resource: core
x-ratelimit-used: 3
accept-ranges: bytes
content-length: 1420
x-github-request-id: F181:4C52:2DB5F1D:2FC7BBC:619C4079

{
  "login": "TachibanaKaoru",
  "id": 225811,
  "node_id": "MwQ6VsdlcjIy3regxMQ==",
  "avatar_url": "https://avatars.githubusercontent.com/u/225811?v=4",
  "gravatar_id": "",
  "url": "https://api.github.com/users/TachibanaKaoru",
...

これをURLSessionでよんで、header情報を見てみましょう。

取得できるresponseからMIME Typeが取得できます。

HTTPURLResponseにキャストして、response.allHeaderFields でheader情報を取得できます。

当然 http status codeなどもとれるので、サーバーの状態に応じて細かい処理を行うこともできますね。

        guard let url = URL(string: "https://api.github.com/users/TachibanaKaoru") else {
            return
        }
        
        URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
            
            let mimeType = response?.mimeType
            //"application/json" が返ります

            let textEncodingName = response?.textEncodingName
            //"utf-8" が返ります

            //その他いろいろ。
            let suggestedFilename = response?.suggestedFilename
            let returnedURL = response?.url            
            let expectedContentLength = response?.expectedContentLength
            
            if let response = response as? HTTPURLResponse {

                // statusCodeをみてみる。
                let statusCode = response.statusCode
                
                // statusCodeの説明文を取得する。
                // (localizedStringですが、表示されるのは英語のみ)
                let statusCodeString = HTTPURLResponse.localizedString(forStatusCode: statusCode)
                
                // すべてのヘッダー
                let headers = response.allHeaderFields
                
                // 特定のヘッダー情報を見てみる
                let xLimit: Any? = response.value(forHTTPHeaderField: "x-ratelimit-limit")
                let xRemain: Any? = response.value(forHTTPHeaderField: "x-ratelimit-remaining")

            }

            if let data = data{
                // mimeTypeに応じた処理を行う
            }
            
        }).resume()