Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding checks for json end_document in http transport #5895

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ fun <D : Operation.Data> Operation<D>.parseJsonResponse(
* ```
*
* By default, this method does not close the [jsonReader]
*
* @see [toApolloResponse]
*/
@JvmOverloads
fun <D : Operation.Data> Operation<D>.parseResponse(
Expand All @@ -111,21 +113,24 @@ fun <D : Operation.Data> Operation<D>.parseResponse(
deferredFragmentIdentifiers,
)
} catch (throwable: Throwable) {
val apolloException = if (throwable is ApolloException) {
throwable
} else {
ApolloNetworkException(
message = "Error while reading JSON response",
platformCause = throwable
)
}
return ApolloResponse.Builder(requestUuid = requestUuid ?: uuid4(), operation = this)
.exception(exception = apolloException)
ApolloResponse.Builder(requestUuid = requestUuid ?: uuid4(), operation = this)
.exception(exception = throwable.wrapIfNeeded())
.isLast(true)
.build()
}
}

private fun Throwable.wrapIfNeeded(): ApolloException {
return if (this is ApolloException) {
this
} else {
ApolloNetworkException(
message = "Error while reading JSON response",
platformCause = this
)
}
}

/**
* writes a successful GraphQL Json response containing "data" to the given sink.
*
Expand All @@ -146,9 +151,12 @@ fun <D : Operation.Data> Operation<D>.composeJsonResponse(
}

/**
* Parses the [JsonReader] into an [ApolloResponse]
* Reads a single [ApolloResponse] from [this]. Returns an error response if [this] contains
* more than one JSON response or trailing tokens.
* [toApolloResponse] takes ownership and closes [this].
*
* Warning: this closes the [JsonReader]. If you need to reuse it, use [parseResponse]
* @return the parsed [ApolloResponse]
* @see parseResponse
*/
@ApolloExperimental
fun <D : Operation.Data> JsonReader.toApolloResponse(
Expand All @@ -158,17 +166,54 @@ fun <D : Operation.Data> JsonReader.toApolloResponse(
deferredFragmentIdentifiers: Set<DeferredFragmentIdentifier>? = null,
): ApolloResponse<D> {
return use {
operation.parseResponse(it, requestUuid, customScalarAdapters, deferredFragmentIdentifiers)
try {
ResponseParser.parse(
this,
operation,
requestUuid,
customScalarAdapters,
deferredFragmentIdentifiers,
).also {
if (peek() != JsonReader.Token.END_DOCUMENT) {
throw JsonDataException("Expected END_DOCUMENT but was ${peek()}")
}
}
} catch (throwable: Throwable) {
ApolloResponse.Builder(requestUuid = requestUuid ?: uuid4(), operation = operation)
.exception(exception = throwable.wrapIfNeeded())
.isLast(true)
.build()
}
}
}

/**
* Reads a [ApolloResponse] from [this].
* The caller is responsible for closing [this].
*
* @return the parsed [ApolloResponse]
* @see [toApolloResponse]
*/
@ApolloExperimental
fun <D : Operation.Data> JsonReader.parseResponse(
operation: Operation<D>,
requestUuid: Uuid? = null,
customScalarAdapters: CustomScalarAdapters = CustomScalarAdapters.Empty,
deferredFragmentIdentifiers: Set<DeferredFragmentIdentifier>? = null,
): ApolloResponse<D> {
return operation.parseResponse(this, requestUuid, customScalarAdapters, deferredFragmentIdentifiers)
return try {
ResponseParser.parse(
this,
operation,
requestUuid,
customScalarAdapters,
deferredFragmentIdentifiers,
)
} catch (throwable: Throwable) {
ApolloResponse.Builder(requestUuid = requestUuid ?: uuid4(), operation = operation)
.exception(exception = throwable.wrapIfNeeded())
.isLast(true)
.build()
}
}

Loading