Skip to content

Commit

Permalink
Fixed additional headers not making it into http requests (#736)
Browse files Browse the repository at this point in the history
  • Loading branch information
michalrentka authored Aug 3, 2023
1 parent a5f7364 commit 5101122
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 11 deletions.
12 changes: 6 additions & 6 deletions Zotero/Controllers/API/ZoteroApiClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ final class ZoteroApiClient: ApiClient {

/// Creates and starts a data request, takes care of retrying request in case of failure.
func send(request: ApiRequest, queue: DispatchQueue) -> Single<(Data?, HTTPURLResponse)> {
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint))
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint), additionalHeaders: self.manager.sessionConfiguration.httpAdditionalHeaders)
return self.createRequestSingle(for: request.endpoint) { $0.request(convertible).validate(acceptableStatusCodes: request.acceptableStatusCodes) }
.flatMap({ (dataRequest: DataRequest) -> Single<(Data?, HTTPURLResponse)> in
return dataRequest.rx.loggedResponseDataWithResponseError(queue: queue, encoding: request.encoding, logParams: request.logParams)
Expand Down Expand Up @@ -121,7 +121,7 @@ final class ZoteroApiClient: ApiClient {

/// Creates download request. Request needs to be started manually.
func download(request: ApiDownloadRequest, queue: DispatchQueue) -> Observable<DownloadRequest> {
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint))
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint), additionalHeaders: self.manager.sessionConfiguration.httpAdditionalHeaders)
return self.createRequestSingle(for: request.endpoint) { manager -> DownloadRequest in
return manager.download(convertible) { _, _ in (request.downloadUrl, [.createIntermediateDirectories, .removePreviousFile]) }
.validate(statusCode: request.acceptableStatusCodes)
Expand All @@ -133,21 +133,21 @@ final class ZoteroApiClient: ApiClient {
}

func upload(request: ApiRequest, data: Data, queue: DispatchQueue) -> Single<(Data?, HTTPURLResponse)> {
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint))
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint), additionalHeaders: self.manager.sessionConfiguration.httpAdditionalHeaders)
let method = HTTPMethod(rawValue: request.httpMethod.rawValue)
let headers = HTTPHeaders(convertible.allHeaders)
return self.createUploadRequest(request: request, queue: queue) { $0.upload(data, to: convertible, method: method, headers: headers) }
}

func upload(request: ApiRequest, queue: DispatchQueue, multipartFormData: @escaping (MultipartFormData) -> Void) -> Single<(Data?, HTTPURLResponse)> {
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint))
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint), additionalHeaders: self.manager.sessionConfiguration.httpAdditionalHeaders)
let method = HTTPMethod(rawValue: request.httpMethod.rawValue)
let headers = HTTPHeaders(convertible.allHeaders)
return self.createUploadRequest(request: request, queue: queue) { $0.upload(multipartFormData: multipartFormData, to: convertible, method: method, headers: headers) }
}

func upload(request: ApiRequest, fromFile file: File, queue: DispatchQueue) -> Single<(Data?, HTTPURLResponse)> {
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint))
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint), additionalHeaders: self.manager.sessionConfiguration.httpAdditionalHeaders)
let method = HTTPMethod(rawValue: request.httpMethod.rawValue)
let headers = HTTPHeaders(convertible.allHeaders)
return self.createUploadRequest(request: request, queue: queue) { $0.upload(file.createUrl(), to: convertible, method: method, headers: headers) }
Expand Down Expand Up @@ -204,7 +204,7 @@ final class ZoteroApiClient: ApiClient {

extension ZoteroApiClient: ApiRequestCreator {
func dataRequest(for request: ApiRequest) -> DataRequest {
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint))
let convertible = Convertible(request: request, baseUrl: self.url, token: self.token(for: request.endpoint), additionalHeaders: self.manager.sessionConfiguration.httpAdditionalHeaders)
return self.createRequest(for: request.endpoint) { $0.request(convertible).validate(acceptableStatusCodes: request.acceptableStatusCodes) }
}
}
Expand Down
4 changes: 2 additions & 2 deletions Zotero/Controllers/Sync/SyncController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1524,11 +1524,11 @@ final class SyncController: SynchronizationController {
action.result
.subscribe(on: self.workScheduler)
.subscribe(with: self, onSuccess: { `self`, _ in
self?.accessQueue.async(flags: .barrier) { [weak self] in
self.accessQueue.async(flags: .barrier) { [weak self] in
self?.processNextAction()
}
}, onFailure: { `self`, _ in
self?.accessQueue.async(flags: .barrier) { [weak self] in
self.accessQueue.async(flags: .barrier) { [weak self] in
self?.abort(error: .uploadObjectConflict(data: SyncError.ErrorData(itemKeys: [key], libraryId: libraryId)))
}
})
Expand Down
19 changes: 17 additions & 2 deletions Zotero/Models/Convertible.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct Convertible {
private let headers: [String: String]
private let timeout: Double

init(request: ApiRequest, baseUrl: URL, token: String?) {
init(request: ApiRequest, baseUrl: URL, token: String?, additionalHeaders: [AnyHashable: Any]?) {
switch request.endpoint {
case .zotero(let path):
self.url = baseUrl.appendingPathComponent(path)
Expand All @@ -31,10 +31,25 @@ struct Convertible {
self.httpMethod = request.httpMethod
self.encoding = request.encoding.alamoEncoding
self.parameters = request.parameters
self.headers = request.headers ?? [:]
self.headers = Convertible.merge(headers: request.headers ?? [:], with: additionalHeaders)
self.timeout = request.timeout
}

private static func merge(headers: [String: String], with additional: [AnyHashable: Any]?) -> [String: String] {
guard let additional, !additional.isEmpty else { return headers }

let mappedToString = Dictionary(
additional.map({ key, value -> (String, String) in
let stringKey = (key as? String) ?? "\(key)"
let stringValue = (value as? String) ?? "\(value)"
return (stringKey, stringValue)
}),
uniquingKeysWith: { left, _ in left }
)

return headers.merging(mappedToString, uniquingKeysWith: { left, _ in left })
}

var allHeaders: [String: String] {
var headers = self.headers
if let token = self.token {
Expand Down
2 changes: 1 addition & 1 deletion ZoteroTests/Extensions/OHHTTPStubs+Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func createStub(for request: ApiRequest, ignoreBody: Bool = false, baseUrl: URL,

extension ApiRequest {
func stubCondition(with baseUrl: URL, ignoreBody: Bool = false) -> HTTPStubsTestBlock {
guard let urlRequest = (try? Convertible(request: self, baseUrl: baseUrl, token: nil).asURLRequest()),
guard let urlRequest = (try? Convertible(request: self, baseUrl: baseUrl, token: nil, additionalHeaders: nil).asURLRequest()),
let url = urlRequest.url,
let host = url.host else {
return { _ in false }
Expand Down

0 comments on commit 5101122

Please sign in to comment.