Заголовок авторизации не установлен в Alamofire 5?

#ios #swift #alamofire #urlrequest

Вопрос:

Я устанавливаю базовый токен аутентификации в свой URL-запрос и использую Alamofire для выполнения.

Я установил 3 заголовка, содержимое, принять и аутентификацию…содержимое и принятие видны в сетевом трафике, но аутентификация отсутствует. Он доступен, если я распечатаю заголовки URL-запроса перед его отправкой…

Есть какие-нибудь идеи? поскольку я не вижу, как удалить заголовок аутентификации перед публикацией

Код выглядит следующим образом:

         // Construct url
        let url = try APIConstants.baseUrl.asURL()

        // Append path
        var urlRequest = URLRequest(url: url.appendingPathComponent(path))

        // Determine HTTP method
        urlRequest.httpMethod = method.rawValue

        let headers: HTTPHeaders = [
            .contentType(APIConstants.ContentType.json.rawValue),
            .accept(APIConstants.ContentType.json.rawValue),
        ]

        if let token = token {
            urlRequest.addValue("(APIConstants.API.token.rawValue) (token.key)",
                                forHTTPHeaderField: "Authorization")
        }

        urlRequest.headers = headers

        // Add http body to request
        if let parameters = parameters {
            do {
                let data = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
                urlRequest.httpBody = data
            } catch (_) {
                print("APIRouter: Failed to parse body into request.")
            }
        }

        //Encoding
        let encoding: ParameterEncoding = {
            switch method {
            case .get:
                return URLEncoding.default
            default:
                return JSONEncoding.default
            }
        }()

        return try encoding.encode(urlRequest, with: parameters)

    }

 

В моем клиенте rest я выполняю так:

         return Observable<T>.create { observer in
            let request = AF.request(urlConvertible).responseDecodable { (response: DataResponse<T, AFError>) in
                switch response.result {
                case .success(let value):
                    observer.onNext(value)
                    observer.onCompleted()
                case .failure(let error):
                    switch response.response?.statusCode {
                    case 403:
                        observer.onError(APIError.forbidden)
                    case 404:
                        observer.onError(APIError.notFound)
                    case 409:
                        observer.onError(APIError.conflict)
                    case 500:
                        observer.onError(APIError.internalServerError)
                    default:
                        observer.onError(error)
                    }
                }
            }

            return Disposables.create {
                request.cancel()
            }
        }
    }

 

Редактировать:

Обновлена функция, чтобы показать дальнейшую проблему:

     func asURLRequest() throws -> URLRequest {
        // Construct url
        let url = try APIConstants.baseUrl.asURL()

        // Append path
        var urlRequest = URLRequest(url: url.appendingPathComponent(path))

        // Determine HTTP method
        urlRequest.httpMethod = method.rawValue

        let headers: HTTPHeaders = [
            .contentType(APIConstants.ContentType.json.rawValue),
            .accept(APIConstants.ContentType.json.rawValue),
            .authorization("Token a5555485aa251b28fdsfasdfdsb379c131fddad")
        ]

        urlRequest.headers = headers

        // Add http body to request
        if let parameters = parameters {
            do {
                let data = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
                urlRequest.httpBody = data
            } catch (_) {
                print("APIRouter: Failed to parse body into request.")
            }
        }

        //Encoding
        let encoding: ParameterEncoding = {
            switch method {
            case .get:
                return URLEncoding.default
            default:
                return JSONEncoding.default
            }
        }()

        return try encoding.encode(urlRequest, with: parameters)

    }
 

Ответ №1:

После установки заголовка авторизации в вашем URLRequest :

 urlRequest.addValue("(APIConstants.API.token.rawValue) (token.key)", forHTTPHeaderField: "Authorization")
 

затем вы переопределяете все заголовки запроса, задав headers свойство:

 urlRequest.headers = headers
 

Хорошим решением было бы обновить headers то, что вы уже создали выше, вот так:

 var headers: HTTPHeaders = [
    .contentType(APIConstants.ContentType.json.rawValue),
    .accept(APIConstants.ContentType.json.rawValue),
]

if let token = token {
    headers.add(.authorization("(APIConstants.API.token.rawValue) (token.key)"))
}

urlRequest.headers = headers
 

Комментарии:

1. Я обновил код в вопросе, чтобы лучше проиллюстрировать проблему, я жестко закодировал заголовок auth в массив с образцом токена, он все еще присутствует в сетевом мониторе

2. это была одна проблема, другая заключалась в том, что я пропустил трейлинг / который, казалось, повторял заголовок auth..go figure

Ответ №2:

Другим решением является использование пары ключевых значений следующим образом:

 var header: HTTPHeaders = [:]
        
if let token = getValueFromUserDefaults(keyName: "authToken") as? String {
                
    header["Authorization"] = token
                
}
            
 

Я всегда использую этот метод. Мне так удобнее.