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.