DefaultCorsProcessorTests.java 14.7 KB
Newer Older
S
Sebastien Deleuze 已提交
1
/*
2
 * Copyright 2002-2017 the original author or authors.
S
Sebastien Deleuze 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.cors.reactive;

import org.junit.Before;
import org.junit.Test;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
25
import org.springframework.http.server.reactive.ServerHttpResponse;
S
Sebastien Deleuze 已提交
26 27
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.web.cors.CorsConfiguration;
28
import org.springframework.web.server.ServerWebExchange;
S
Sebastien Deleuze 已提交
29

30 31 32 33 34 35 36 37
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.http.HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS;
import static org.springframework.http.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
import static org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS;
import static org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD;
R
Rossen Stoyanchev 已提交
38

S
Sebastien Deleuze 已提交
39
/**
R
Rossen Stoyanchev 已提交
40
 * {@link DefaultCorsProcessor} tests with simple or pre-flight CORS request.
S
Sebastien Deleuze 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
 *
 * @author Sebastien Deleuze
 */
public class DefaultCorsProcessorTests {

	private DefaultCorsProcessor processor;

	private CorsConfiguration conf;


	@Before
	public void setup() {
		this.conf = new CorsConfiguration();
		this.processor = new DefaultCorsProcessor();
	}


	@Test
	public void actualRequestWithOriginHeader() throws Exception {
60
		ServerWebExchange exchange = actualRequest();
61
		this.processor.process(this.conf, exchange);
62 63 64 65

		ServerHttpResponse response = exchange.getResponse();
		assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
S
Sebastien Deleuze 已提交
66 67 68 69
	}

	@Test
	public void actualRequestWithOriginHeaderAndNullConfig() throws Exception {
70
		ServerWebExchange exchange = actualRequest();
71
		this.processor.process(null, exchange);
72 73 74 75

		ServerHttpResponse response = exchange.getResponse();
		assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
76 77 78 79
	}

	@Test
	public void actualRequestWithOriginHeaderAndAllowedOrigin() throws Exception {
80
		ServerWebExchange exchange = actualRequest();
S
Sebastien Deleuze 已提交
81
		this.conf.addAllowedOrigin("*");
82
		this.processor.process(this.conf, exchange);
83 84 85 86 87 88 89

		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals("*", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertFalse(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_MAX_AGE));
		assertFalse(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
90 91 92 93
	}

	@Test
	public void actualRequestCredentials() throws Exception {
94
		ServerWebExchange exchange = actualRequest();
S
Sebastien Deleuze 已提交
95 96 97 98
		this.conf.addAllowedOrigin("http://domain1.com");
		this.conf.addAllowedOrigin("http://domain2.com");
		this.conf.addAllowedOrigin("http://domain3.com");
		this.conf.setAllowCredentials(true);
99
		this.processor.process(this.conf, exchange);
100 101 102 103 104 105 106

		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals("http://domain2.com", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertTrue(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
		assertEquals("true", response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
107 108 109 110
	}

	@Test
	public void actualRequestCredentialsWithOriginWildcard() throws Exception {
111
		ServerWebExchange exchange = actualRequest();
S
Sebastien Deleuze 已提交
112 113
		this.conf.addAllowedOrigin("*");
		this.conf.setAllowCredentials(true);
114
		this.processor.process(this.conf, exchange);
115 116 117 118 119 120 121

		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals("http://domain2.com", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertTrue(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
		assertEquals("true", response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
122 123 124 125
	}

	@Test
	public void actualRequestCaseInsensitiveOriginMatch() throws Exception {
126
		ServerWebExchange exchange = actualRequest();
S
Sebastien Deleuze 已提交
127
		this.conf.addAllowedOrigin("http://DOMAIN2.com");
128
		this.processor.process(this.conf, exchange);
S
Sebastien Deleuze 已提交
129

130 131 132
		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
133 134 135 136
	}

	@Test
	public void actualRequestExposedHeaders() throws Exception {
137
		ServerWebExchange exchange = actualRequest();
S
Sebastien Deleuze 已提交
138 139 140
		this.conf.addExposedHeader("header1");
		this.conf.addExposedHeader("header2");
		this.conf.addAllowedOrigin("http://domain2.com");
141
		this.processor.process(this.conf, exchange);
142 143 144 145 146 147 148 149

		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals("http://domain2.com", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertTrue(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS));
		assertTrue(response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header1"));
		assertTrue(response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header2"));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
150 151 152 153
	}

	@Test
	public void preflightRequestAllOriginsAllowed() throws Exception {
154
		ServerWebExchange exchange = preFlightRequest().header(ACCESS_CONTROL_REQUEST_METHOD, "GET").toExchange();
S
Sebastien Deleuze 已提交
155
		this.conf.addAllowedOrigin("*");
156
		this.processor.process(this.conf, exchange);
S
Sebastien Deleuze 已提交
157

158
		assertNull(exchange.getResponse().getStatusCode());
S
Sebastien Deleuze 已提交
159 160
	}

161

S
Sebastien Deleuze 已提交
162 163
	@Test
	public void preflightRequestWrongAllowedMethod() throws Exception {
164
		ServerWebExchange exchange = preFlightRequest().header(ACCESS_CONTROL_REQUEST_METHOD, "DELETE").toExchange();
S
Sebastien Deleuze 已提交
165
		this.conf.addAllowedOrigin("*");
166
		this.processor.process(this.conf, exchange);
S
Sebastien Deleuze 已提交
167

168
		assertEquals(HttpStatus.FORBIDDEN, exchange.getResponse().getStatusCode());
S
Sebastien Deleuze 已提交
169 170 171 172
	}

	@Test
	public void preflightRequestMatchedAllowedMethod() throws Exception {
173
		ServerWebExchange exchange = preFlightRequest().header(ACCESS_CONTROL_REQUEST_METHOD, "GET").toExchange();
S
Sebastien Deleuze 已提交
174
		this.conf.addAllowedOrigin("*");
175
		this.processor.process(this.conf, exchange);
S
Sebastien Deleuze 已提交
176

177 178 179
		ServerHttpResponse response = exchange.getResponse();
		assertNull(response.getStatusCode());
		assertEquals("GET,HEAD", response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS));
S
Sebastien Deleuze 已提交
180 181 182 183
	}

	@Test
	public void preflightRequestTestWithOriginButWithoutOtherHeaders() throws Exception {
184
		ServerWebExchange exchange = preFlightRequest().toExchange();
185
		this.processor.process(this.conf, exchange);
S
Sebastien Deleuze 已提交
186

187 188 189
		ServerHttpResponse response = exchange.getResponse();
		assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
S
Sebastien Deleuze 已提交
190 191 192 193
	}

	@Test
	public void preflightRequestWithoutRequestMethod() throws Exception {
194
		ServerWebExchange exchange = preFlightRequest().header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1").toExchange();
195
		this.processor.process(this.conf, exchange);
S
Sebastien Deleuze 已提交
196

197 198 199
		ServerHttpResponse response = exchange.getResponse();
		assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
S
Sebastien Deleuze 已提交
200 201 202 203
	}

	@Test
	public void preflightRequestWithRequestAndMethodHeaderButNoConfig() throws Exception {
204
		ServerWebExchange exchange = preFlightRequest()
205 206
				.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
				.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1")
207 208
				.toExchange();

209
		this.processor.process(this.conf, exchange);
S
Sebastien Deleuze 已提交
210

211 212 213
		ServerHttpResponse response = exchange.getResponse();
		assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
S
Sebastien Deleuze 已提交
214 215 216 217
	}

	@Test
	public void preflightRequestValidRequestAndConfig() throws Exception {
218
		ServerWebExchange exchange = preFlightRequest()
219 220
				.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
				.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1")
221 222
				.toExchange();

S
Sebastien Deleuze 已提交
223 224 225 226 227 228
		this.conf.addAllowedOrigin("*");
		this.conf.addAllowedMethod("GET");
		this.conf.addAllowedMethod("PUT");
		this.conf.addAllowedHeader("header1");
		this.conf.addAllowedHeader("header2");

229
		this.processor.process(this.conf, exchange);
230 231 232 233 234 235 236 237

		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals("*", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertTrue(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS));
		assertEquals("GET,PUT", response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS));
		assertFalse(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_MAX_AGE));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
238 239 240 241
	}

	@Test
	public void preflightRequestCredentials() throws Exception {
242
		ServerWebExchange exchange = preFlightRequest()
243 244
				.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
				.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1")
245 246
				.toExchange();

S
Sebastien Deleuze 已提交
247 248 249 250 251 252
		this.conf.addAllowedOrigin("http://domain1.com");
		this.conf.addAllowedOrigin("http://domain2.com");
		this.conf.addAllowedOrigin("http://domain3.com");
		this.conf.addAllowedHeader("Header1");
		this.conf.setAllowCredentials(true);

253
		this.processor.process(this.conf, exchange);
254 255 256 257 258 259 260

		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals("http://domain2.com", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertTrue(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
		assertEquals("true", response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
261 262 263 264
	}

	@Test
	public void preflightRequestCredentialsWithOriginWildcard() throws Exception {
265
		ServerWebExchange exchange = preFlightRequest()
266 267
				.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
				.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1")
268 269
				.toExchange();

S
Sebastien Deleuze 已提交
270 271 272 273 274 275
		this.conf.addAllowedOrigin("http://domain1.com");
		this.conf.addAllowedOrigin("*");
		this.conf.addAllowedOrigin("http://domain3.com");
		this.conf.addAllowedHeader("Header1");
		this.conf.setAllowCredentials(true);

276
		this.processor.process(this.conf, exchange);
277 278 279 280 281

		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals("http://domain2.com", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
282 283 284 285
	}

	@Test
	public void preflightRequestAllowedHeaders() throws Exception {
286
		ServerWebExchange exchange = preFlightRequest()
287 288
				.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
				.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2")
289 290
				.toExchange();

S
Sebastien Deleuze 已提交
291 292 293 294 295
		this.conf.addAllowedHeader("Header1");
		this.conf.addAllowedHeader("Header2");
		this.conf.addAllowedHeader("Header3");
		this.conf.addAllowedOrigin("http://domain2.com");

296
		this.processor.process(this.conf, exchange);
297 298 299 300 301 302 303 304

		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_HEADERS));
		assertTrue(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1"));
		assertTrue(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2"));
		assertFalse(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header3"));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
305 306 307 308
	}

	@Test
	public void preflightRequestAllowsAllHeaders() throws Exception {
309
		ServerWebExchange exchange = preFlightRequest()
310 311
				.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
				.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2")
312 313
				.toExchange();

S
Sebastien Deleuze 已提交
314 315 316
		this.conf.addAllowedHeader("*");
		this.conf.addAllowedOrigin("http://domain2.com");

317
		this.processor.process(this.conf, exchange);
318 319 320 321 322 323 324 325

		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_HEADERS));
		assertTrue(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1"));
		assertTrue(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2"));
		assertFalse(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("*"));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
326 327 328 329
	}

	@Test
	public void preflightRequestWithEmptyHeaders() throws Exception {
330
		ServerWebExchange exchange = preFlightRequest()
331 332
				.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
				.header(ACCESS_CONTROL_REQUEST_HEADERS, "")
333 334
				.toExchange();

S
Sebastien Deleuze 已提交
335 336 337
		this.conf.addAllowedHeader("*");
		this.conf.addAllowedOrigin("http://domain2.com");

338
		this.processor.process(this.conf, exchange);
339 340 341 342 343

		ServerHttpResponse response = exchange.getResponse();
		assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_HEADERS));
		assertNull(response.getStatusCode());
S
Sebastien Deleuze 已提交
344 345 346 347
	}

	@Test
	public void preflightRequestWithNullConfig() throws Exception {
348
		ServerWebExchange exchange = preFlightRequest().header(ACCESS_CONTROL_REQUEST_METHOD, "GET").toExchange();
S
Sebastien Deleuze 已提交
349
		this.conf.addAllowedOrigin("*");
350
		this.processor.process(null, exchange);
S
Sebastien Deleuze 已提交
351

352 353 354
		ServerHttpResponse response = exchange.getResponse();
		assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
		assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
S
Sebastien Deleuze 已提交
355 356
	}

357

358 359
	private ServerWebExchange actualRequest() {
		return corsRequest(HttpMethod.GET).toExchange();
360 361 362 363 364 365
	}

	private MockServerHttpRequest.BaseBuilder<?> preFlightRequest() {
		return corsRequest(HttpMethod.OPTIONS);
	}

366
	private MockServerHttpRequest.BaseBuilder<?> corsRequest(HttpMethod method) {
367
		return MockServerHttpRequest
368
				.method(method, "http://localhost/test.html")
369 370 371
				.header(HttpHeaders.ORIGIN, "http://domain2.com");
	}

S
Sebastien Deleuze 已提交
372
}