Authorisation Missing/Droped in the Header URLSession iOS

59 views Asked by At

I am experiencing some issues where the authentication header is missing on the request but when I log in Xcode it shows it is sent. When I change the header to a different name other than "Authorization", I can be able to see the header.

Here is my network service

class NetworkService {
    private let session: URLSession

    init(session: URLSession = .shared) {
        self.session = session
    }

    func sendRequest<T: Decodable>(_ request: APIRequest) async -> Result<T, NetworkError> {
        do {
            let urlRequest = request.urlRequest(with: AppConfig.baseURL)

            // Printing headers For verification of token presence
            print("Request Headers: \(String(describing: urlRequest.allHTTPHeaderFields))")

            let (data, response) = try await session.data(for: urlRequest)
            
            
            guard let httpResponse = response as? HTTPURLResponse else {
                return .failure(.unknown)
            }

            switch httpResponse.statusCode {
            case 200...299:
                do {
                    let decodedResponse = try JSONDecoder().decode(T.self, from: data)
                    return .success(decodedResponse)
                } catch {
                    return .failure(.decodingError)
                }
            case 401:
                return .failure(.unauthorized)
            default:
                return .failure(.serverError)
            }
        } catch {
            return .failure(.unknown)
        }
    }
}

APIRequest

protocol APIRequest {
    var method: String { get }
    var path: String { get }
    var parameters: [String: Any]? { get }
    var headers: [String: String] { get }
    var body: Data? { get }

    func urlRequest(with baseURL: URL) -> URLRequest
    func encodeParameters() -> Data?
}

extension APIRequest {
    func urlRequest(with baseURL: URL) -> URLRequest {
        let url = baseURL.appendingPathComponent(path)
        var request = URLRequest(url: url)
        request.httpMethod = method
        request.allHTTPHeaderFields = headers
        request.httpBody = body ?? encodeParameters()
        return request
    }

    func encodeParameters() -> Data? {
        // Default implementation for encoding parameters
        nil
    }
}

APIclient

class APIClient {
    private let networkService: NetworkService

    init(networkService: NetworkService = NetworkService()) {
        self.networkService = networkService
    }

    func getAllMovies() async -> Result<MoviesResponse, NetworkError> {
        await networkService.sendRequest(APIRouter.getAllMovies)
    }
}

APIRouter

enum APIRouter: APIRequest {


    case getAllMovies
    
    var method: String {
        switch self {
        case .getAllMovies:
            return "GET"
        }
    }
    
    var path: String {
        switch self {
        case .getAllMovies:
            return "Movies"
        }
    }
    
    var parameters: [String: Any]? {
        nil
    }
    
    var headers: [String: String] {
        var headers = [APIHeaders.contentType: "application/json"]
        let session = SessionStore.shared
        
        switch self {
        case .getAllMovies:
            guard let token = session.currentUserData?.token.trimmingCharacters(in: .whitespacesAndNewlines) else {
                print("Token missing")
            }
            headers[APIHeaders.authorization] = "Bearer \(token)"
        }
        print("Final Headers: \(headers)")
        return headers
    }
    
    var body: Data? {
            switch self {
            case .getAllMovies:
                return nil
            }
        }
}
struct APIHeaders {
    static let contentType = "Content-Type"
    static let authorization = "Authorization"
    static let cookie = "Cookie"
}

and lastly view model

class GetAllMoviesViewModel: ObservableObject {
    private var apiClient: APIClient
    @Published var isLoading = false
    @Published var error: NetworkError?
    

    init(apiClient: APIClient = APIClient()) {
        self.apiClient = apiClient
    }

    func getAllMovies() {
        isLoading = true
        Task {
            let result = await apiClient.getAllMovies()
            await MainActor.run {
                isLoading = false
                switch result {
                case .success(let responses):
                    print("Movies: ", responses.data)
                case .failure(let error):
                    self.error = error
                }
            }
        }
    }
}

I have tried trimming the token string or even passing directly for the test but with no luck. I would appreciate any lead to figure out what might be the issue. Thanks.

0

There are 0 answers