Add test case for gh-774

This commit also ensures that a new local context is created, copying
the existing values. This avoids mutating the parent local context and
polluting it with local values.
This could cause unintended side effects on other child datafetchers.

Fixes gh-774
This commit is contained in:
Brian Clozel
2023-08-16 18:25:15 +02:00
parent 8131c7e88f
commit c5f1e5f4de
2 changed files with 37 additions and 1 deletions

View File

@@ -203,7 +203,7 @@ public class GraphQlObservationInstrumentation extends SimpleInstrumentation {
}
else {
GraphQLContext localContext = dataFetcherLocalContext == null ?
GraphQLContext.getDefault() : dataFetcherLocalContext;
GraphQLContext.newContext().build() : GraphQLContext.newContext().of(dataFetcherLocalContext).build();
return DataFetcherResult.newResult()
.data(value)
.localContext(localContext.put(ObservationThreadLocalAccessor.KEY, dataFetcherObservation))

View File

@@ -16,6 +16,7 @@
package org.springframework.graphql.observation;
import graphql.GraphQLContext;
import graphql.GraphqlErrorBuilder;
import graphql.execution.DataFetcherResult;
import graphql.schema.AsyncDataFetcher;
@@ -279,4 +280,39 @@ class GraphQlObservationInstrumentationTests {
ResponseHelper response = ResponseHelper.forResponse(responseMono);
}
@Test
void shouldNotOverrideExistingLocalContext() {
String document = """
{
bookById(id: 1) {
author {
firstName,
lastName
}
}
}
""";
DataFetcher<DataFetcherResult<Object>> bookDataFetcher = environment -> DataFetcherResult.newResult()
.data(BookSource.getBook(1L))
.localContext(GraphQLContext.newContext().of("test", "value").build())
.build();
DataFetcher<Author> authorDataFetcher = environment -> BookSource.getAuthor(101L);
DataFetcher<String> authorFirstNameDataFetcher = environment -> {
GraphQLContext context = environment.getLocalContext();
String value = context.get("test");
assertThat(value).isEqualTo("value");
return BookSource.getAuthor(101L).getFirstName();
};
ExecutionGraphQlRequest request = TestExecutionRequest.forDocument(document);
Mono<ExecutionGraphQlResponse> responseMono = graphQlSetup
.queryFetcher("bookById", bookDataFetcher)
.dataFetcher("Book", "author", authorDataFetcher)
.dataFetcher("Author", "firstName", authorFirstNameDataFetcher)
.toGraphQlService()
.execute(request);
ResponseHelper.forResponse(responseMono);
}
}