Skip to content

Commit 38040bf

Browse files
committed
Add WebFlux CORS reference documentation
Issue: SPR-16199
1 parent 7697b39 commit 38040bf

File tree

3 files changed

+214
-1
lines changed

3 files changed

+214
-1
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
[[webflux-cors]]
2+
= CORS
3+
4+
5+
== Introduction
6+
7+
For security reasons, browsers prohibit AJAX calls to resources residing outside the
8+
current origin. For example, as you're checking your bank account in one tab, you
9+
could have the evil.com website open in another tab. The scripts from evil.com should not
10+
be able to make AJAX requests to your bank API (e.g., withdrawing money from your account!)
11+
using your credentials.
12+
13+
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing[Cross-origin resource sharing]
14+
(CORS) is a http://www.w3.org/TR/cors/[W3C specification] implemented by
15+
http://caniuse.com/#feat=cors[most browsers] that allows you to specify in a flexible
16+
way what kind of cross domain requests are authorized, instead of using some less secured
17+
and less powerful hacks like IFRAME or JSONP.
18+
19+
Spring WebFlux supports CORS out of the box. CORS requests, including preflight ones with an `OPTIONS` method,
20+
are automatically dispatched to the various registered ``HandlerMapping``s. They handle
21+
CORS preflight requests and intercept CORS simple and actual requests thanks to a
22+
{api-spring-framework}/web/cors/reactive/CorsProcessor.html[CorsProcessor]
23+
implementation (https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java[DefaultCorsProcessor]
24+
by default) in order to add the relevant CORS response headers (like `Access-Control-Allow-Origin`)
25+
based on the CORS configuration you have provided.
26+
27+
28+
[[webflux-cors-controller]]
29+
== @CrossOrigin
30+
31+
You can add an
32+
{api-spring-framework}/web/bind/annotation/CrossOrigin.html[`@CrossOrigin`]
33+
annotation to your `@RequestMapping` annotated handler method in order to enable CORS on
34+
it. By default `@CrossOrigin` allows all origins and the HTTP methods specified in the
35+
`@RequestMapping` annotation:
36+
37+
[source,java,indent=0]
38+
[subs="verbatim,quotes"]
39+
----
40+
@RestController
41+
@RequestMapping("/account")
42+
public class AccountController {
43+
44+
@CrossOrigin
45+
@GetMapping("/{id}")
46+
public Mono<Account> retrieve(@PathVariable Long id) {
47+
// ...
48+
}
49+
50+
@DeleteMapping("/{id}")
51+
public Mono<Void> remove(@PathVariable Long id) {
52+
// ...
53+
}
54+
}
55+
----
56+
57+
It is also possible to enable CORS for the whole controller:
58+
59+
[source,java,indent=0]
60+
[subs="verbatim,quotes"]
61+
----
62+
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
63+
@RestController
64+
@RequestMapping("/account")
65+
public class AccountController {
66+
67+
@GetMapping("/{id}")
68+
public Mono<Account> retrieve(@PathVariable Long id) {
69+
// ...
70+
}
71+
72+
@DeleteMapping("/{id}")
73+
public Mono<Void> remove(@PathVariable Long id) {
74+
// ...
75+
}
76+
}
77+
----
78+
79+
In the above example CORS support is enabled for both the `retrieve()` and the `remove()`
80+
handler methods, and you can also see how you can customize the CORS configuration using
81+
`@CrossOrigin` attributes.
82+
83+
You can even use both controller-level and method-level CORS configurations; Spring will
84+
then combine attributes from both annotations to create merged CORS configuration.
85+
86+
[source,java,indent=0]
87+
[subs="verbatim,quotes"]
88+
----
89+
@CrossOrigin(maxAge = 3600)
90+
@RestController
91+
@RequestMapping("/account")
92+
public class AccountController {
93+
94+
@CrossOrigin("http://domain2.com")
95+
@GetMapping("/{id}")
96+
public Account retrieve(@PathVariable Long id) {
97+
// ...
98+
}
99+
100+
@DeleteMapping("/{id}")
101+
public void remove(@PathVariable Long id) {
102+
// ...
103+
}
104+
}
105+
----
106+
107+
108+
[[webflux-cors-java-config]]
109+
== Java Config
110+
111+
In addition to fine-grained, annotation-based configuration you'll probably want to
112+
define some global CORS configuration as well. This is similar to using filters but can
113+
be declared within Spring WebFlux and combined with fine-grained `@CrossOrigin` configuration.
114+
By default all origins and `GET`, `HEAD`, and `POST` methods are allowed.
115+
116+
Enabling CORS for the whole application is as simple as:
117+
118+
[source,java,indent=0]
119+
[subs="verbatim,quotes"]
120+
----
121+
@Configuration
122+
@EnableWebFlux
123+
public class WebConfig implements WebFluxConfigurer {
124+
125+
@Override
126+
public void addCorsMappings(CorsRegistry registry) {
127+
registry.addMapping("/**");
128+
}
129+
}
130+
----
131+
132+
You can easily change any properties, as well as only apply this CORS configuration to a
133+
specific path pattern:
134+
135+
[source,java,indent=0]
136+
[subs="verbatim,quotes"]
137+
----
138+
@Configuration
139+
@EnableWebFlux
140+
public class WebConfig implements WebFluxConfigurer {
141+
142+
@Override
143+
public void addCorsMappings(CorsRegistry registry) {
144+
registry.addMapping("/api/**")
145+
.allowedOrigins("http://domain2.com")
146+
.allowedMethods("PUT", "DELETE")
147+
.allowedHeaders("header1", "header2", "header3")
148+
.exposedHeaders("header1", "header2")
149+
.allowCredentials(false).maxAge(3600);
150+
}
151+
}
152+
----
153+
154+
155+
[[webflux-cors-webfilter]]
156+
== CORS WebFilter
157+
158+
You can apply CORS support through the built-in
159+
{api-spring-framework}/web/cors/reactive/CorsWebFilter.html[`CorsWebFilter`], which is a
160+
good fit with <<webflux-fn,functional endpoints>>.
161+
162+
To configure the filter, you can declare a `CorsWebFilter` bean and pass a
163+
`CorsConfigurationSource` to its constructor:
164+
165+
[source,java,indent=0]
166+
----
167+
@Bean
168+
CorsWebFilter corsFilter() {
169+
CorsConfiguration config = new CorsConfiguration();
170+
config.setAllowCredentials(true);
171+
config.addAllowedOrigin("http://domain1.com");
172+
config.addAllowedHeader("*");
173+
config.addAllowedMethod("*");
174+
175+
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
176+
source.registerCorsConfiguration("/**", config);
177+
178+
return new CorsWebFilter(source);
179+
}
180+
----
181+
182+
You can also easily permit all cross-origin requests for GET, HEAD, and POST requests by writing
183+
[source,java,indent=0]
184+
185+
----
186+
@Bean
187+
CorsWebFilter corsFilter() {
188+
return new CorsWebFilter(exchange -> new CorsConfiguration().applyPermitDefaultValues());
189+
}
190+
----
191+
192+
193+
[[webflux-cors-customizations]]
194+
== Advanced Customization
195+
196+
{api-spring-framework}/web/cors/CorsConfiguration.html[CorsConfiguration]
197+
allows you to specify how the CORS requests should be processed: allowed origins, headers, methods, etc.
198+
It can be provided in various ways:
199+
200+
* {api-spring-framework}/web/reactive/handler/AbstractHandlerMapping.html#setCorsConfigurations-java.util.Map-[`AbstractHandlerMapping#setCorsConfigurations()`]
201+
allows to specify a `Map` with several {api-spring-framework}/web/cors/CorsConfiguration.html[CorsConfiguration]
202+
instances mapped to path patterns like `/api/**`.
203+
* Subclasses can provide their own `CorsConfiguration` by overriding the
204+
`AbstractHandlerMapping#getCorsConfiguration(Object, ServerWebExchange)` method.
205+
* Handlers can implement the {api-spring-framework}/web/cors/reactive/CorsConfigurationSource.html[`CorsConfigurationSource`]
206+
interface in order to provide a {api-spring-framework}/web/cors/CorsConfiguration.html[CorsConfiguration]
207+
instance for each request.

src/docs/asciidoc/web/webflux-functional.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,8 @@ RouterFunction<ServerResponse> filteredRoute =
241241

242242
You can see in this example that invoking the `next.handle(ServerRequest)` is optional: we only
243243
allow the handler function to be executed when access is allowed.
244+
245+
[NOTE]
246+
====
247+
CORS support for functional endpoints is provided via a dedicated <<webflux-cors-webfilter,`CorsWebFilter`>>.
248+
====

src/docs/asciidoc/web/webflux.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,7 @@ from the base class and you can still have any number of other ``WebMvcConfigure
14481448
the classpath.
14491449

14501450

1451+
include::webflux-cors.adoc[leveloffset=+1]
14511452

14521453

14531454
[[webflux-http2]]
@@ -1461,4 +1462,4 @@ For more details please check out the
14611462
https://github.com/spring-projects/spring-framework/wiki/HTTP-2-support[HTTP/2 wiki page].
14621463

14631464
Currently Spring WebFlux does not support HTTP/2 with Netty. There is also no support for
1464-
pushing resources programmatically to the client.
1465+
pushing resources programmatically to the client.

0 commit comments

Comments
 (0)