Skip to content

Instantly share code, notes, and snippets.

@below
Created April 30, 2021 07:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save below/8a7dcbda51919409f869e6c6fb2fe465 to your computer and use it in GitHub Desktop.
Save below/8a7dcbda51919409f869e6c6fb2fe465 to your computer and use it in GitHub Desktop.
public typealias AccessTokenPublisher = AnyPublisher<String, Error>
func fetchAuthorizedURLRequest(_ urlRequest: URLRequest,
accessToken: AccessTokenPublisher) -> AnyPublisher<Data, Error> {
accessToken
.flatMap { (accessToken: String) -> AnyPublisher<(data: Data, response: URLResponse), Error> in
URLSession.shared.dataTaskPublisher(
for: urlRequest.requestWithToken(accessToken)
)
// The URLError should be mapped to Error
.mapError { (urlError: URLError) -> Error in
urlError
}
.eraseToAnyPublisher()
}
.tryMap { result in
guard let urlResponse = result.response as? HTTPURLResponse, (200...299).contains(urlResponse.statusCode) else {
let statusCode = (result.response as? HTTPURLResponse)?.statusCode ?? 500
throw APIError(
statusCode: statusCode,
data: result.data)
}
return result.data
}
.eraseToAnyPublisher()
}
extension URLRequest {
func requestWithToken(_ token: String?) -> URLRequest {
var newRequest = self
var value: String? = nil
if let token = token {
value = "Bearer \(token)"
}
newRequest.setValue(value, forHTTPHeaderField: "Authorization")
return newRequest
}
}
struct APIError: Decodable, Error, CustomDebugStringConvertible {
let statusCode: Int
let data: Data
var debugDescription: String {
let string = String(data: data, encoding: .utf8) ?? "<NONE>"
return "\(statusCode): \(string)"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment