Skip to content

Commit

Permalink
throw GraphQLHTTPRequestError for JSON serialization error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Henry Hong committed Jul 3, 2019
1 parent b4dfc58 commit 9748016
Showing 1 changed file with 52 additions and 36 deletions.
88 changes: 52 additions & 36 deletions Sources/Apollo/HTTPNetworkTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,26 @@ public class HTTPNetworkTransport: NetworkTransport {
public func send<Operation>(operation: Operation, completionHandler: @escaping (_ response: GraphQLResponse<Operation>?, _ error: Error?) -> Void) -> Cancellable {
let headers = decorateRequestHeaders(for: operation)

let request = { () -> URLRequest in
guard operation.operationType == .query else {
return httpPostRequest(operation: operation, requestHeaders: headers, sendQueryDocument: true, autoPersistQueries: false)
}

if _useGETForQueries || (_useHttpGetMethodForPersistedQueries && _enableAutoPersistedQueries) {
return httpGetRequest(operation: operation, requestHeaders: headers, sendQueryDocument: !_enableAutoPersistedQueries, autoPersistQueries: _enableAutoPersistedQueries)
} else {
return httpPostRequest(operation: operation, requestHeaders: headers, sendQueryDocument: !_enableAutoPersistedQueries, autoPersistQueries: _enableAutoPersistedQueries)
}
}()
let request: URLRequest

let task = session.dataTask(with: request) { [weak self] (data: Data?, httpResponse: URLResponse?, httpError: Error?) in
guard let self = self else { return }

do {
request = try { () -> URLRequest in
guard operation.operationType == .query else {
return try httpPostRequest(operation: operation, requestHeaders: headers, sendQueryDocument: true, autoPersistQueries: false)
}

if _useGETForQueries || (_useHttpGetMethodForPersistedQueries && _enableAutoPersistedQueries) {
return try httpGetRequest(operation: operation, requestHeaders: headers, sendQueryDocument: !_enableAutoPersistedQueries, autoPersistQueries: _enableAutoPersistedQueries)
} else {
return try httpPostRequest(operation: operation, requestHeaders: headers, sendQueryDocument: !_enableAutoPersistedQueries, autoPersistQueries: _enableAutoPersistedQueries)
}
}()
} catch {
completionHandler(nil, error)
return EmptyCancellable()
}

let task = session.dataTask(with: request) { (data: Data?, httpResponse: URLResponse?, httpError: Error?) in
let result = self.handleResponse(data, httpResponse, httpError)
guard let body = result.0 else {
completionHandler(nil, result.1)
Expand All @@ -69,19 +74,25 @@ public class HTTPNetworkTransport: NetworkTransport {
switch errorMsg {
case "PersistedQueryNotFound", "PersistedQueryNotSupported":
// retry with standard call
let requestRetry = { () -> URLRequest in
guard operation.operationType == .query else {
// fallback to normal call
return self.httpGetRequest(operation: operation, requestHeaders: headers, sendQueryDocument: true, autoPersistQueries: false)
}

// retry with query document
if self._useGETForQueries {
return self.httpGetRequest(operation: operation, requestHeaders: headers, sendQueryDocument: true, autoPersistQueries: self._enableAutoPersistedQueries)
} else {
return self.httpPostRequest(operation: operation, requestHeaders: headers, sendQueryDocument: true, autoPersistQueries: self._enableAutoPersistedQueries)
}
}()
let requestRetry:URLRequest
do {
requestRetry = try { () -> URLRequest in
guard operation.operationType == .query else {
// fallback to normal call
return try self.httpGetRequest(operation: operation, requestHeaders: headers, sendQueryDocument: true, autoPersistQueries: false)
}

// retry with query document
if self._useGETForQueries {
return try self.httpGetRequest(operation: operation, requestHeaders: headers, sendQueryDocument: true, autoPersistQueries: self._enableAutoPersistedQueries)
} else {
return try self.httpPostRequest(operation: operation, requestHeaders: headers, sendQueryDocument: true, autoPersistQueries: self._enableAutoPersistedQueries)
}
}()
} catch {
completionHandler(nil, error)
return
}

let newSession = URLSession(configuration: self.session.configuration)
let (dataRetry, responseRetry, errorRetry) = newSession.synchronousDataTask(with: requestRetry)
Expand Down Expand Up @@ -143,24 +154,29 @@ public class HTTPNetworkTransport: NetworkTransport {
private func httpPostRequest<Operation: GraphQLOperation>(operation: Operation,
requestHeaders: [String: String?],
sendQueryDocument: Bool,
autoPersistQueries: Bool) -> URLRequest {
autoPersistQueries: Bool) throws -> URLRequest {
var request = URLRequest(url: url)
request.httpMethod = "POST"
_ = requestHeaders.compactMap ({ request.setValue($1, forHTTPHeaderField: $0) })
let body = requestBody(for: operation, sendQueryDocument: sendQueryDocument, autoPersistQueries: autoPersistQueries)

request.httpBody = try! serializationFormat.serialize(value: body)

return request
do {
let serializedBody = try serializationFormat.serialize(value: body)
request.httpBody = serializedBody
return request

} catch {
throw GraphQLHTTPRequestError.serializedQueryParamsMessageError
}
}

private func httpGetRequest<Operation: GraphQLOperation>(operation: Operation,
requestHeaders: [String: String?],
sendQueryDocument: Bool,
autoPersistQueries: Bool) -> URLRequest {
autoPersistQueries: Bool) throws -> URLRequest {

var urlComponent = URLComponents.init(url: url, resolvingAgainstBaseURL: true)
urlComponent?.queryItems = requestURLQueryItems(for: operation, sendQueryDocument: sendQueryDocument, autoPersistQueries: autoPersistQueries)
urlComponent?.queryItems = try requestURLQueryItems(for: operation, sendQueryDocument: sendQueryDocument, autoPersistQueries: autoPersistQueries)

guard let newUrl = urlComponent?.url else {
preconditionFailure("To send data via urlQueryUrl, URL construction must be valid")
Expand Down Expand Up @@ -203,21 +219,21 @@ public class HTTPNetworkTransport: NetworkTransport {

private func requestURLQueryItems<Operation: GraphQLOperation>(for operation: Operation,
sendQueryDocument: Bool,
autoPersistQueries: Bool) -> [URLQueryItem] {
autoPersistQueries: Bool) throws -> [URLQueryItem] {

var queryItems: [URLQueryItem] = []

let body = requestBody(for: operation, sendQueryDocument: sendQueryDocument, autoPersistQueries: autoPersistQueries)

_ = body.compactMap({ arg in
_ = try body.compactMap({ arg in
if let value = arg.value as? GraphQLMap {
do {
let data = try serializationFormat.serialize(value: value)
if let string = String(data: data, encoding: String.Encoding.utf8) {
queryItems.append(URLQueryItem(name: arg.key, value: string))
}
} catch {
print(error)
throw GraphQLHTTPRequestError.serializedQueryParamsMessageError
}
}

Expand Down

0 comments on commit 9748016

Please sign in to comment.