kean / Get

Web API client built using async/await
MIT License
943 stars 75 forks source link

How to globally set a common group of header #87

Closed skywalkerlw closed 1 year ago

skywalkerlw commented 1 year ago

Background:

The current situation is I have to assign headers to Request for each API request while my expectation is to set that globally.

For example, I have a base header required to send to the backend for any request. Ideally, there's a method I can use like

APIClient.setCommonHeader(headers)

Here is my code

import Foundation
import Get

struct LeisureAPIClient {
    static func getUser() async throws -> [User] {
        let config = LeisureAPI.users
        return try await APIClient(baseURL:config.baseURL) {
            $0.delegate = LeisureAPIClientDelegate.shared
        }.send(Request(path: config.path, headers: ["example"])).value 
    }
}

public enum LeisureAPI {
    case users
    case topContributors
}

extension LeisureAPI: TargetType {

    var baseURL: URL {
        return URL(string: "https://api.github.com")!
    }

    var path: String {
        switch self {
        case .users:
            return "/users"
        case .topContributors:
            return "/repos/scala/scala/contributors"
        }
    }

    var method: HttpMethod {
        return .get
    }

    var headers: [String : String]? {
        return nil
    }
}

enum HttpMethod: String {
    case post = "post"
    case get = "get"
}

protocol TargetType {

    /// The target's base `URL`.
    var baseURL: URL { get }

    /// The path to be appended to `baseURL` to form the full `URL`.
    var path: String { get }

    /// The HTTP method used in the request.
    var method: HttpMethod { get }

    /// Provides stub data for use in testing. Default is `Data()`.
    var sampleData: Data? { get }

    /// The headers to be used in the request.
    var headers: [String: String]? { get }
}

extension TargetType {
    var sampleData: Data? {
        return nil
    }

    var headers: [String: String]? {
        baseHeader
    }

    var baseHeader: [String: String] {
        [
            "Authorization": "allow",
            "userType": "xxx",
            "type": "iOS",
            "x-api-key": "xxxx",
            "device_id": "xxxx",
            "token": "xxxx",
            "uid": "xxxx"
        ]
    }
}

final class LeisureAPIClientDelegate: APIClientDelegate {
    static var shared = LeisureAPIClientDelegate()
    func client(_ client: APIClient, validateResponse response: HTTPURLResponse, data: Data, task: URLSessionTask) throws {
        if response.statusCode == 304 {
            print("304 returned")
            NotificationCenter.default.post(name: Notification.Name("EXPIRED"), object: nil)
        } else {
            print("validateResponse")
        }
    }
}
kean commented 1 year ago

There are a couple of ways to do it:

  1. Use URLSession httpAdditionalHeaders
  2. Implement APIClientDelegate method client(_:willSendRequest:) in modify the request there