1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.codec.http.cors;
17
18 import io.netty5.handler.codec.http.DefaultHttpHeaders;
19 import io.netty5.handler.codec.http.EmptyHttpHeaders;
20 import io.netty5.handler.codec.http.HttpHeaders;
21 import io.netty5.handler.codec.http.HttpMethod;
22 import io.netty5.util.internal.StringUtil;
23
24 import java.util.Collections;
25 import java.util.Date;
26 import java.util.LinkedHashSet;
27 import java.util.Map;
28 import java.util.Map.Entry;
29 import java.util.Set;
30 import java.util.concurrent.Callable;
31
32
33
34
35 public final class CorsConfig {
36
37 private final Set<String> origins;
38 private final boolean anyOrigin;
39 private final boolean enabled;
40 private final Set<String> exposeHeaders;
41 private final boolean allowCredentials;
42 private final long maxAge;
43 private final Set<HttpMethod> allowedRequestMethods;
44 private final Set<String> allowedRequestHeaders;
45 private final boolean allowNullOrigin;
46 private final Map<CharSequence, Callable<?>> preflightHeaders;
47 private final boolean shortCircuit;
48 private final boolean allowPrivateNetwork;
49
50 CorsConfig(final CorsConfigBuilder builder) {
51 origins = new LinkedHashSet<>(builder.origins);
52 anyOrigin = builder.anyOrigin;
53 enabled = builder.enabled;
54 exposeHeaders = builder.exposeHeaders;
55 allowCredentials = builder.allowCredentials;
56 maxAge = builder.maxAge;
57 allowedRequestMethods = builder.requestMethods;
58 allowedRequestHeaders = builder.requestHeaders;
59 allowNullOrigin = builder.allowNullOrigin;
60 preflightHeaders = builder.preflightHeaders;
61 shortCircuit = builder.shortCircuit;
62 allowPrivateNetwork = builder.allowPrivateNetwork;
63 }
64
65
66
67
68
69
70 public boolean isCorsSupportEnabled() {
71 return enabled;
72 }
73
74
75
76
77
78
79 public boolean isAnyOriginSupported() {
80 return anyOrigin;
81 }
82
83
84
85
86
87
88 public String origin() {
89 return origins.isEmpty() ? "*" : origins.iterator().next();
90 }
91
92
93
94
95
96
97 public Set<String> origins() {
98 return origins;
99 }
100
101
102
103
104
105
106
107
108
109
110 public boolean isNullOriginAllowed() {
111 return allowNullOrigin;
112 }
113
114
115
116
117
118
119
120
121
122
123
124 public boolean isPrivateNetworkAllowed() {
125 return allowPrivateNetwork;
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150 public Set<String> exposedHeaders() {
151 return Collections.unmodifiableSet(exposeHeaders);
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 public boolean isCredentialsAllowed() {
172 return allowCredentials;
173 }
174
175
176
177
178
179
180
181
182
183
184
185 public long maxAge() {
186 return maxAge;
187 }
188
189
190
191
192
193
194
195 public Set<HttpMethod> allowedRequestMethods() {
196 return Collections.unmodifiableSet(allowedRequestMethods);
197 }
198
199
200
201
202
203
204
205
206
207 public Set<String> allowedRequestHeaders() {
208 return Collections.unmodifiableSet(allowedRequestHeaders);
209 }
210
211
212
213
214
215
216 public HttpHeaders preflightResponseHeaders() {
217 if (preflightHeaders.isEmpty()) {
218 return EmptyHttpHeaders.INSTANCE;
219 }
220 final HttpHeaders preflightHeaders = new DefaultHttpHeaders();
221 for (Entry<CharSequence, Callable<?>> entry : this.preflightHeaders.entrySet()) {
222 final Object value = getValue(entry.getValue());
223 if (value instanceof Iterable) {
224 preflightHeaders.add(entry.getKey(), (Iterable<?>) value);
225 } else {
226 preflightHeaders.add(entry.getKey(), value);
227 }
228 }
229 return preflightHeaders;
230 }
231
232
233
234
235
236
237
238
239
240
241
242 public boolean isShortCircuit() {
243 return shortCircuit;
244 }
245
246
247
248
249 @Deprecated
250 public boolean isShortCurcuit() {
251 return isShortCircuit();
252 }
253
254 private static <T> T getValue(final Callable<T> callable) {
255 try {
256 return callable.call();
257 } catch (final Exception e) {
258 throw new IllegalStateException("Could not generate value for callable [" + callable + ']', e);
259 }
260 }
261
262 @Override
263 public String toString() {
264 return StringUtil.simpleClassName(this) + "[enabled=" + enabled +
265 ", origins=" + origins +
266 ", anyOrigin=" + anyOrigin +
267 ", exposedHeaders=" + exposeHeaders +
268 ", isCredentialsAllowed=" + allowCredentials +
269 ", maxAge=" + maxAge +
270 ", allowedRequestMethods=" + allowedRequestMethods +
271 ", allowedRequestHeaders=" + allowedRequestHeaders +
272 ", preflightHeaders=" + preflightHeaders +
273 ", isPrivateNetworkAllowed=" + allowPrivateNetwork + ']';
274 }
275
276
277
278
279 @Deprecated
280 public static Builder withAnyOrigin() {
281 return new Builder();
282 }
283
284
285
286
287 @Deprecated
288 public static Builder withOrigin(final String origin) {
289 if ("*".equals(origin)) {
290 return new Builder();
291 }
292 return new Builder(origin);
293 }
294
295
296
297
298 @Deprecated
299 public static Builder withOrigins(final String... origins) {
300 return new Builder(origins);
301 }
302
303
304
305
306 @Deprecated
307 public static class Builder {
308
309 private final CorsConfigBuilder builder;
310
311
312
313
314 @Deprecated
315 public Builder(final String... origins) {
316 builder = new CorsConfigBuilder(origins);
317 }
318
319
320
321
322 @Deprecated
323 public Builder() {
324 builder = new CorsConfigBuilder();
325 }
326
327
328
329
330 @Deprecated
331 public Builder allowNullOrigin() {
332 builder.allowNullOrigin();
333 return this;
334 }
335
336
337
338
339 @Deprecated
340 public Builder disable() {
341 builder.disable();
342 return this;
343 }
344
345
346
347
348 @Deprecated
349 public Builder exposeHeaders(final String... headers) {
350 builder.exposeHeaders(headers);
351 return this;
352 }
353
354
355
356
357 @Deprecated
358 public Builder allowCredentials() {
359 builder.allowCredentials();
360 return this;
361 }
362
363
364
365
366 @Deprecated
367 public Builder maxAge(final long max) {
368 builder.maxAge(max);
369 return this;
370 }
371
372
373
374
375 @Deprecated
376 public Builder allowedRequestMethods(final HttpMethod... methods) {
377 builder.allowedRequestMethods(methods);
378 return this;
379 }
380
381
382
383
384 @Deprecated
385 public Builder allowedRequestHeaders(final String... headers) {
386 builder.allowedRequestHeaders(headers);
387 return this;
388 }
389
390
391
392
393 @Deprecated
394 public Builder preflightResponseHeader(final CharSequence name, final Object... values) {
395 builder.preflightResponseHeader(name, values);
396 return this;
397 }
398
399
400
401
402 @Deprecated
403 public <T> Builder preflightResponseHeader(final CharSequence name, final Iterable<T> value) {
404 builder.preflightResponseHeader(name, value);
405 return this;
406 }
407
408
409
410
411 @Deprecated
412 public <T> Builder preflightResponseHeader(final String name, final Callable<T> valueGenerator) {
413 builder.preflightResponseHeader(name, valueGenerator);
414 return this;
415 }
416
417
418
419
420 @Deprecated
421 public Builder noPreflightResponseHeaders() {
422 builder.noPreflightResponseHeaders();
423 return this;
424 }
425
426
427
428
429 @Deprecated
430 public CorsConfig build() {
431 return builder.build();
432 }
433
434
435
436
437 @Deprecated
438 public Builder shortCurcuit() {
439 builder.shortCircuit();
440 return this;
441 }
442 }
443
444
445
446
447 @Deprecated
448 public static final class DateValueGenerator implements Callable<Date> {
449
450 @Override
451 public Date call() throws Exception {
452 return new Date();
453 }
454 }
455 }