
io.muserver.rest.CORSConfigBuilder Maven / Gradle / Ivy
Show all versions of mu-server Show documentation
package io.muserver.rest;
import io.muserver.Method;
import io.muserver.MuServerBuilder;
import io.muserver.Mutils;
import io.muserver.handlers.CORSHandlerBuilder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import static java.util.Arrays.asList;
/**
* A builder to set configuration for CORS requests.
*/
public class CORSConfigBuilder {
private boolean allowCredentials = false;
private Collection allowedOrigins = Collections.emptySet();
private List allowedOriginRegex = new ArrayList<>();
private Collection exposedHeaders = Collections.emptySet();
private Collection allowedHeaders = Collections.emptySet();
private long maxAge = -1;
/**
* All origins will be allowed
* @return This builder
*/
public CORSConfigBuilder withAllOriginsAllowed() {
return withAllowedOrigins((Collection)null);
}
/**
* If set to true, then access-control-allow-credentials
is returned with true
on CORS responses.
* @param allowCredentials Whether or not to include the credentials header
* @return This builder
*/
public CORSConfigBuilder withAllowCredentials(boolean allowCredentials) {
this.allowCredentials = allowCredentials;
return this;
}
/**
* The origin values that CORS requests are allowed for, or null to allow all origins.
* @param allowedOrigins Allowed origins, such as https://example.org
or http://localhost:8080
* @return This builder
*/
public CORSConfigBuilder withAllowedOrigins(Collection allowedOrigins) {
if (allowedOrigins != null) {
for (String allowedOrigin : allowedOrigins) {
if (!allowedOrigin.startsWith("http://") && !allowedOrigin.startsWith("https://")) {
throw new IllegalArgumentException(allowedOrigin + " is invalid: origins much have an http:// or https:// prefix");
}
if (allowedOrigin.lastIndexOf('/') > 8) {
throw new IllegalArgumentException(allowedOrigin + " is invalid: origins should not have any paths. Example origin: https://example.org");
}
}
}
this.allowedOrigins = allowedOrigins;
return this;
}
/**
* The origin values that CORS requests are allowed for.
* @param allowedOrigins Allowed origins, such as https://example.org
or http://localhost:8080
* @return This builder
*/
public CORSConfigBuilder withAllowedOrigins(String... allowedOrigins) {
return withAllowedOrigins(asList(allowedOrigins));
}
/**
* The origin values that CORS requests are allowed for.
* If called multiple times, then just one of the patterns need to match to allow the origin.
* Note: this is a no-op if null
is used.
* @param allowedOriginRegex A regex to match, e.g. Pattern.compile("https://.*\\.example\\.org")
to allow
* all subdomains of example.org
over HTTPS.
* @return This builder
*/
public CORSConfigBuilder withAllowedOriginRegex(Pattern allowedOriginRegex) {
if (allowedOriginRegex != null) {
this.allowedOriginRegex.add(allowedOriginRegex);
}
return this;
}
/**
* The origin values that CORS requests are allowed for.
* If called multiple times, then just one of the patterns need to match to allow the origin.
* Note: this is a no-op if null
is used.
* @param allowedOriginRegex A regex to match, e.g. "https://.*\\.example\\.org"
to allow
* all subdomains of example.org
over HTTPS.
* @return This builder
* @throws PatternSyntaxException If the expression's syntax is invalid
*/
public CORSConfigBuilder withAllowedOriginRegex(String allowedOriginRegex) {
if (allowedOriginRegex == null) {
return this;
}
return withAllowedOriginRegex(Pattern.compile(allowedOriginRegex));
}
/**
* Adds all localhost URLs (whether http or https) as allowed origins.
* @return This builder
*/
public CORSConfigBuilder withLocalhostAllowed() {
return withAllowedOriginRegex(Pattern.compile("https?://localhost(:[0-9]+)?"));
}
/**
* Specifies which headers (aside from "simple" headers) are allowed to be accessed by JavaScript in responses.
* The "simple" headers are: Cache-Control
, Content-Language
,
* Content-Type
, Expires
, Last-Modified
, Pragma
* (so you do not need to specify these values).
* @param headerNames The names of headers to allow, for example Content-Type
* @return This builder
*/
public CORSConfigBuilder withExposedHeaders(String... headerNames) {
Mutils.notNull("headerNames", headerNames);
return withExposedHeaders(asList(headerNames));
}
/**
* Specifies which headers (aside from "simple" headers) are allowed to be accessed by JavaScript in responses.
* The "simple" headers are: Cache-Control
, Content-Language
,
* Content-Type
, Expires
, Last-Modified
, Pragma
* (so you do not need to specify these values).
* @param headerNames The names of headers to allow, for example Content-Type
* @return This builder
*/
public CORSConfigBuilder withExposedHeaders(Collection headerNames) {
Mutils.notNull("headerNames", headerNames);
this.exposedHeaders = headerNames;
return this;
}
/**
* On preflight OPTIONS requests, specifies which headers are allowed to be sent on the request, aside from the "simple" headers.
* The "simple" headers are Accept
, Accept-Language
, Content-Language
,
* Content-Type
(but only with a MIME type of application/x-www-form-urlencoded
, multipart/form-data
, or text/plain
).
* You do not need to specify the simple headers.
* @param headerNames The names of headers to allow, for example Content-Length
* @return This builder
*/
public CORSConfigBuilder withAllowedHeaders(String... headerNames) {
Mutils.notNull("headerNames", headerNames);
return withAllowedHeaders(asList(headerNames));
}
/**
* On preflight OPTIONS requests, specifies which headers are allowed to be sent on the request, aside from the "simple" headers.
* The "simple" headers are Accept
, Accept-Language
, Content-Language
,
* Content-Type
(but only with a MIME type of application/x-www-form-urlencoded
, multipart/form-data
, or text/plain
).
* You do not need to specify the simple headers.
* @param headerNames The names of headers to allow, for example Content-Length
* @return This builder
*/
public CORSConfigBuilder withAllowedHeaders(Collection headerNames) {
Mutils.notNull("headerNames", headerNames);
this.allowedHeaders = headerNames;
return this;
}
/**
* On preflight OPTIONS requests, specifies the time the response is valid for
* @param seconds The age in seconds, for example 600 for five minutes.
* @return This builder.
*/
public CORSConfigBuilder withMaxAge(long seconds) {
this.maxAge = seconds;
return this;
}
/**
* Creates a builder to set CORS configuration. Normally at least {@link #withAllowedOrigins(String...)} will be called.
* @return A new builder to create CORS config with
*/
public static CORSConfigBuilder corsConfig() {
return new CORSConfigBuilder()
.withMaxAge(600);
}
/**
* Creates CORS configuration that disables all CORS requests.
* @return A new builder to create CORS config with
*/
public static CORSConfigBuilder disabled() {
return new CORSConfigBuilder();
}
/**
* Creates a CORS handler from this config.
* This can be used when CORS configuration is needed outside of JAX-RS. Add the created handler to
* a {@link MuServerBuilder} before any other handlers that require CORS config.
* Note that if you only need CORS config for JAX-RS then instead of this method you should pass
* this config to {@link RestHandlerBuilder#withCORS(CORSConfigBuilder)}
* @param allowedMethods The allowed methods for CORS calls
* @return A handler that can be added.
*/
public CORSHandlerBuilder toHandler(Method... allowedMethods) {
return CORSHandlerBuilder.corsHandler().withCORSConfig(this).withAllowedMethods(allowedMethods);
}
/**
* Builds CORS configuration from a builder
* @return An immutable configuration object.
*/
public CORSConfig build() {
return new CORSConfig(allowCredentials, allowedOrigins, allowedOriginRegex, allowedHeaders, exposedHeaders, maxAge);
}
}