
io.muserver.CookieBuilder Maven / Gradle / Ivy
Show all versions of mu-server Show documentation
package io.muserver;
import io.netty.handler.codec.http.cookie.CookieHeaderNames;
import io.netty.handler.codec.http.cookie.DefaultCookie;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* A builder to create cookies that will be sent on a Response with {@link MuResponse#addCookie(Cookie)}
*/
public class CookieBuilder {
private String name;
private String value;
private String domain;
private String path;
private long maxAge = DefaultCookie.UNDEFINED_MAX_AGE;
private boolean secure;
private boolean httpOnly;
private CookieHeaderNames.SameSite sameSite = CookieHeaderNames.SameSite.None;
/**
* Sets the name of the cookie.
*
* @param name The name of the cookie
* @return This builder
*/
public CookieBuilder withName(String name) {
Mutils.notNull("name", name);
boolean matches = name.matches("^[0-9A-Za-z!#$%&'*+\\-.^_`|~]+$");
if (!matches) {
throw new IllegalArgumentException("A cookie name can only be alphanumeric ASCII characters or any of \"!#$%&'*+-.^_`|~\" (excluding quotes)");
}
this.name = name;
return this;
}
/**
* Sets the value of the cookie.
* Note that only a subset of ASCII characters are allowed (any other characters must be encoded).
* Consider using {@link #withUrlEncodedValue(String)} instead if you want to use arbitrary values.
*
* @param value The value to use for the cookie, which can be any US-ASCII characters excluding CTLs, whitespace,
* double quotes, comma, semicolon, and backslash.
* @return This builder
* @throws IllegalArgumentException If the value contains illegal characters
*/
public CookieBuilder withValue(String value) {
Mutils.notNull("value", value);
boolean matches = value.matches("^[0-9A-Za-z!#$%&'()*+\\-./:<=>?@\\[\\]^_`{|}~]*$");
if (!matches) {
throw new IllegalArgumentException("A cookie value can only be ASCII characters excluding control characters, whitespace, quotes, commas, semicolons and backslashes. Consider using CookieBuilder.withUrlEncodedValue instead.");
}
this.value = value;
return this;
}
/**
* Sets the value of the cookie by URL Encoding the given value.
*
* @param value A value containing any characters that will be URL Encoded.
* @return This builder
*/
public CookieBuilder withUrlEncodedValue(String value) {
return withValue(Mutils.urlEncode(value));
}
/**
* Sets the host that clients should send the cookie over. By default it is the current domain (but not subdomains).
* To allow sub-domains, specify the current domain (e.g. with request.uri().getHost()
).
*
* @param domain The host part of a URL (without scheme or port), e.g. example.org
* @return This builder
*/
public CookieBuilder withDomain(String domain) {
if (domain != null && domain.contains(":")) {
throw new IllegalArgumentException("The domain value should only be a host name (and should not include the scheme or the port)");
}
this.domain = domain;
return this;
}
/**
* Sets the path prefix that the cookie will be sent with, or null to send to all paths.
*
* @param path A path such as /order
which would cause cookies to be sent with requests
* to paths such as /order
and /order/checkout
etc.
* @return This builder
*/
public CookieBuilder withPath(String path) {
this.path = path;
return this;
}
/**
* Specifies how long the cookie will last for.
* A value of 0 will cause most browsers to delete the cookie immediately.
* Use {@link #makeSessionCookie()} to make this a session cookie that will cause most browsers to delete
* the cookie when they close their browser.
*
* @param maxAge The age to live in seconds.
* @return This builder
*/
public CookieBuilder withMaxAgeInSeconds(long maxAge) {
this.maxAge = maxAge;
return this;
}
/**
* Makes this cookie expire when the browser session expires (which may be when the user closes their
* browser).
* This overwrites any value set with {@link #withMaxAgeInSeconds(long)}
*
* @return This builder
*/
public CookieBuilder makeSessionCookie() {
return withMaxAgeInSeconds(DefaultCookie.UNDEFINED_MAX_AGE);
}
/**
* Instructs clients on whether or not cookies can be sent over non-secure (HTTP) connections.
* It is strongly recommended to use this if your site is HTTPS only as it may prevent private information
* being sent over HTTP.
*
* @param secure true
to make this cookie HTTPS-only, or false
to allow HTTPS and HTTP.
* @return This builder
*/
public CookieBuilder secure(boolean secure) {
this.secure = secure;
return this;
}
/**
* Instructs browsers on whether or not the cookie can be accessed via JavaScript. This is a secure feature
* that should be used unless JavaScript access is required.
*
* @param httpOnly true
to make it so JavaScript cannot access this cookie; otherwise false
* @return This builder
*/
public CookieBuilder httpOnly(boolean httpOnly) {
this.httpOnly = httpOnly;
return this;
}
/**
* Sets the SameSite
property of the cookie. If not set, then None
is used.
* @param sameSiteValue One of Strict
, Lax
or None
* @return This builder
*/
public CookieBuilder withSameSite(String sameSiteValue) {
try {
this.sameSite = CookieHeaderNames.SameSite.valueOf(sameSiteValue);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid SameSite value. It should be one of: " +
Stream.of(CookieHeaderNames.SameSite.values())
.map(CookieHeaderNames.SameSite::name)
.collect(Collectors.joining(", ")));
}
return this;
}
/**
* Creates a new session cookie
*
* @return A builder to create a new cookie;
*/
public static CookieBuilder newCookie() {
return new CookieBuilder();
}
/**
* Creates a new session cookie that is only sent over HTTPS and cannot be accessed with JavaScript
* with a Strict samesite policy applied.
*
* @return A builder to create a new cookie;
*/
public static CookieBuilder newSecureCookie() {
return new CookieBuilder()
.secure(true)
.httpOnly(true)
.withSameSite("Strict");
}
/**
* @return Returns a newly created cookie.
*/
public Cookie build() {
if (Mutils.nullOrEmpty(name)) throw new IllegalStateException("A cookie name must be specified");
if (value == null) throw new IllegalStateException("A cookie value must be specified");
Cookie c = new Cookie(name, value);
c.nettyCookie.setDomain(domain);
c.nettyCookie.setPath(path);
c.nettyCookie.setMaxAge(maxAge);
c.nettyCookie.setSecure(secure);
c.nettyCookie.setHttpOnly(httpOnly);
c.nettyCookie.setSameSite(sameSite);
return c;
}
}