Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.

Commit c99416f

Browse files
authored
Merge pull request #499 from graphql-java-kickstart/bugfix/cors-headers
Set default cors headers if missing fix #498
2 parents f834807 + 4fab1f6 commit c99416f

File tree

5 files changed

+87
-4
lines changed

5 files changed

+87
-4
lines changed

graphql-spring-boot-autoconfigure/src/main/java/graphql/kickstart/spring/web/boot/GraphQLInstrumentationAutoConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
@ConditionalOnClass(MetricsAutoConfiguration.class)
3030
@AutoConfigureAfter({MetricsAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class,
3131
GraphQLWebsocketAutoConfiguration.class})
32+
@EnableConfigurationProperties(GraphQLServletProperties.class)
3233
@ConditionalOnProperty(value = "graphql.servlet.enabled", havingValue = "true", matchIfMissing = true)
33-
@EnableConfigurationProperties({GraphQLServletProperties.class})
3434
public class GraphQLInstrumentationAutoConfiguration {
3535

3636
private final GraphQLServletProperties graphqlServletProperties;

graphql-spring-boot-autoconfigure/src/main/java/graphql/kickstart/spring/web/boot/GraphQLWebAutoConfiguration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import graphql.kickstart.spring.web.boot.metrics.MetricsInstrumentation;
5757
import graphql.kickstart.tools.boot.GraphQLJavaToolsAutoConfiguration;
5858
import graphql.schema.GraphQLSchema;
59+
import java.util.Arrays;
5960
import java.util.LinkedHashMap;
6061
import java.util.List;
6162
import java.util.Map;
@@ -78,6 +79,7 @@
7879
import org.springframework.context.annotation.Bean;
7980
import org.springframework.context.annotation.Conditional;
8081
import org.springframework.context.annotation.Configuration;
82+
import org.springframework.http.HttpMethod;
8183
import org.springframework.web.cors.CorsConfiguration;
8284
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
8385
import org.springframework.web.filter.CorsFilter;
@@ -126,6 +128,10 @@ public CorsConfiguration corsConfiguration() {
126128
@ConditionalOnProperty(value = "graphql.servlet.corsEnabled", havingValue = "true", matchIfMissing = true)
127129
public CorsFilter corsConfigurer(CorsConfiguration corsConfiguration) {
128130
Map<String, CorsConfiguration> corsConfigurations = new LinkedHashMap<>(1);
131+
if (corsConfiguration.getAllowedMethods() == null) {
132+
corsConfiguration.setAllowedMethods(
133+
Arrays.asList(HttpMethod.GET.name(), HttpMethod.HEAD.name(), HttpMethod.POST.name()));
134+
}
129135
corsConfigurations.put(graphQLServletProperties.getCorsMapping(), corsConfiguration);
130136

131137
UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package graphql.kickstart.spring.web.boot;
2+
3+
import static graphql.Scalars.GraphQLString;
4+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options;
5+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
6+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
7+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
8+
9+
import graphql.schema.GraphQLFieldDefinition;
10+
import graphql.schema.GraphQLObjectType;
11+
import graphql.schema.GraphQLSchema;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.api.extension.ExtendWith;
14+
import org.springframework.beans.factory.annotation.Autowired;
15+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
16+
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
17+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
18+
import org.springframework.boot.test.context.SpringBootTest;
19+
import org.springframework.boot.test.context.TestConfiguration;
20+
import org.springframework.context.annotation.Bean;
21+
import org.springframework.http.MediaType;
22+
import org.springframework.test.context.junit.jupiter.SpringExtension;
23+
import org.springframework.test.web.servlet.MockMvc;
24+
import org.springframework.test.web.servlet.ResultActions;
25+
26+
@ExtendWith(SpringExtension.class)
27+
@AutoConfigureMockMvc
28+
@ImportAutoConfiguration({JacksonAutoConfiguration.class, GraphQLWebAutoConfiguration.class})
29+
@SpringBootTest(properties = {"debug=true", "graphql.servlet.mapping=/graphql", "graphql.servlet.cors.allowed-origins=https://trusted.com"})
30+
class CorsTest {
31+
32+
@Autowired
33+
private MockMvc mockMvc;
34+
35+
@Test
36+
void evilDomain_shouldNotBeAllowed() throws Exception {
37+
ResultActions resultActions = performCorsPreflight("https://evil.com");
38+
resultActions
39+
.andExpect(status().isForbidden())
40+
.andExpect(content().string("Invalid CORS request"));
41+
}
42+
43+
private ResultActions performCorsPreflight(String origin) throws Exception {
44+
return mockMvc.perform(
45+
options("/graphql")
46+
.contentType(MediaType.APPLICATION_JSON)
47+
.header("Access-Control-Request-Method", "POST")
48+
.header("Origin", origin)
49+
);
50+
}
51+
52+
@Test
53+
void trustedDomain_shouldBeAllowed() throws Exception {
54+
ResultActions resultActions = performCorsPreflight("https://trusted.com");
55+
resultActions
56+
.andExpect(status().isOk())
57+
.andExpect(header().string("Access-Control-Allow-Origin", "https://trusted.com"))
58+
.andExpect(header().string("Access-Control-Allow-Methods", "GET,HEAD,POST"));
59+
}
60+
61+
@TestConfiguration
62+
static class MyTestConfiguration {
63+
64+
@Bean
65+
public GraphQLSchema graphQLSchema() {
66+
return GraphQLSchema.newSchema()
67+
.query(GraphQLObjectType.newObject().name("Query").field(
68+
GraphQLFieldDefinition.newFieldDefinition()
69+
.name("echo")
70+
.type(GraphQLString)
71+
.build()).build()).build();
72+
}
73+
}
74+
75+
}

graphql-spring-boot-autoconfigure/src/test/java/graphql/kickstart/spring/web/boot/GraphQLServletPropertiesTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,19 @@
77
import org.junit.jupiter.api.Test;
88
import org.junit.jupiter.api.extension.ExtendWith;
99
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
11+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
1012
import org.springframework.boot.test.context.SpringBootTest;
13+
import org.springframework.context.annotation.Import;
1114
import org.springframework.test.context.junit.jupiter.SpringExtension;
1215

1316
@ExtendWith(SpringExtension.class)
17+
@EnableConfigurationProperties(GraphQLServletProperties.class)
1418
@SpringBootTest(properties = {"graphql.servlet.mapping=/test",
1519
"graphql.servlet.contextSetting=PER_REQUEST_WITH_INSTRUMENTATION"})
1620
class GraphQLServletPropertiesTest {
1721

22+
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
1823
@Autowired
1924
private GraphQLServletProperties properties;
2025

graphql-spring-boot-autoconfigure/src/test/java/graphql/kickstart/spring/web/boot/TestAutoConfiguration.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
package graphql.kickstart.spring.web.boot;
22

33
import org.springframework.boot.SpringBootConfiguration;
4-
import org.springframework.boot.context.properties.EnableConfigurationProperties;
54
import org.springframework.context.annotation.Import;
65

76
@SpringBootConfiguration
8-
@Import(GraphQLServletProperties.class)
9-
@EnableConfigurationProperties
107
public class TestAutoConfiguration {
118

129

0 commit comments

Comments
 (0)