/* * The MIT License * * Copyright 2013 Tim Boudreau. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.mastfrog.acteur.headers; import com.google.common.net.MediaType; import com.mastfrog.acteur.util.BasicCredentials; import com.mastfrog.acteur.util.CacheControl; import com.mastfrog.acteur.util.Connection; import com.mastfrog.acteur.util.Realm; import com.mastfrog.util.Checks; import io.netty.handler.codec.http.Cookie; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMessage; import java.net.URI; import java.nio.charset.Charset; import java.util.*; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.Duration; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatterBuilder; /** * A collection of standard HTTP headers and objects that convert between them * and actual header strings and vice versa. Typical usage would be something * like: * <pre> * response.setHeader(Headers.LAST_MODIFIED, new DateTime()); * </pre> This handles conversion between header strings and Java objects * without creating a class which dicatates what headers should be or what they * should look like. * * @author Tim Boudreau */ public final class Headers { private Headers() { } public static final HeaderValueType<DateTime> DATE = new DateTimeHeader(HttpHeaders.Names.DATE.toString()); public static final HeaderValueType<DateTime> LAST_MODIFIED = new DateTimeHeader(HttpHeaders.Names.LAST_MODIFIED.toString()); public static final HeaderValueType<DateTime> EXPIRES = new DateTimeHeader(HttpHeaders.Names.EXPIRES.toString()); public static final HeaderValueType<DateTime> IF_MODIFIED_SINCE = new DateTimeHeader(HttpHeaders.Names.IF_MODIFIED_SINCE.toString()); public static final HeaderValueType<DateTime> IF_UNMODIFIED_SINCE = new DateTimeHeader(HttpHeaders.Names.IF_UNMODIFIED_SINCE.toString()); public static final HeaderValueType<DateTime> RETRY_AFTER_DATE = new DateTimeHeader(HttpHeaders.Names.RETRY_AFTER.toString()); public static final HeaderValueType<Duration> RETRY_AFTER_DURATION = new DurationHeader(HttpHeaders.Names.RETRY_AFTER.toString()); // public static final HeaderValueType<Host> HOST = new HostHeader(HttpHeaders.Names.HOST); public static final HeaderValueType<String> HOST = new HostHeader(HttpHeaders.Names.HOST.toString()); public static final HeaderValueType<MediaType> CONTENT_TYPE = new MediaTypeHeader(); public static final HeaderValueType<String> SERVER = new StringHeader(HttpHeaders.Names.SERVER.toString()); public static final HeaderValueType<HeaderValueType[]> VARY = new VaryHeader(); public static final HeaderValueType<ByteRanges> RANGE = new ByteRangeHeader(HttpHeaders.Names.RANGE.toString()); public static final HeaderValueType<BoundedRange> CONTENT_RANGE = new ContentRangeHeader(HttpHeaders.Names.CONTENT_RANGE.toString()); public static final HeaderValueType<String> ACCEPT = new StringHeader(HttpHeaders.Names.ACCEPT.toString()); public static final HeaderValueType<String> ACCEPT_ENCODING = new StringHeader(HttpHeaders.Names.ACCEPT_ENCODING.toString()); public static final HeaderValueType<String> ACCEPT_RANGES = new StringHeader(HttpHeaders.Names.ACCEPT_RANGES.toString()); public static final HeaderValueType<String> CONTENT_ENCODING = new StringHeader(HttpHeaders.Names.CONTENT_ENCODING.toString()); public static final HeaderValueType<String> USER_AGENT = new StringHeader(HttpHeaders.Names.USER_AGENT.toString()); public static final HeaderValueType<Connection> CONNECTION = new ConnectionHeader(); public static final HeaderValueType<Long> CONTENT_LENGTH = new LongHeader(HttpHeaders.Names.CONTENT_LENGTH.toString()); public static final HeaderValueType<URI> CONTENT_LOCATION = new UriHeader(HttpHeaders.Names.CONTENT_LOCATION.toString()); public static final HeaderValueType<URI> LOCATION = new UriHeader(HttpHeaders.Names.LOCATION.toString()); public static final HeaderValueType<Charset> ACCEPT_CHARSET = new CharsetHeader(HttpHeaders.Names.ACCEPT_CHARSET.toString()); public static final HeaderValueType<Locale> CONTENT_LANGUAGE = new LocaleHeader(HttpHeaders.Names.CONTENT_LANGUAGE.toString()); public static final HeaderValueType<String> ETAG = new ETagHeader(HttpHeaders.Names.ETAG.toString()); public static final HeaderValueType<String> IF_NONE_MATCH = new ETagHeader(HttpHeaders.Names.IF_NONE_MATCH.toString()); public static final HeaderValueType<Duration> AGE = new DurationHeader(HttpHeaders.Names.AGE.toString()); public static final HeaderValueType<Duration> RETRY_AFTER = new DurationHeader(HttpHeaders.Names.RETRY_AFTER.toString()); public static final HeaderValueType<BasicCredentials> AUTHORIZATION = new BasicCredentialsHeader(); public static final HeaderValueType<CacheControl> CACHE_CONTROL = new CacheControlHeader(); public static final HeaderValueType<Realm> WWW_AUTHENTICATE = new AuthHeader(); public static final HeaderValueType<Method[]> ALLOW = new AllowHeader(false); public static final HeaderValueType<Method[]> ACCESS_CONTROL_ALLOW = new AllowHeader(true); @Deprecated public static final HeaderValueType<Cookie> SET_COOKIE = new SetCookieHeader(); public static final HeaderValueType<io.netty.handler.codec.http.cookie.Cookie> SET_COOKIE_B = new SetCookieHeaderNetty428(HttpHeaders.Names.SET_COOKIE); @Deprecated public static final HeaderValueType<Cookie[]> COOKIE = new CookieHeader(); public static final HeaderValueType<io.netty.handler.codec.http.cookie.Cookie[]> COOKIE_B = new CookieHeaderNetty428(); public static final HeaderValueType<String[]> WEBSOCKET_PROTOCOLS = new WebSocketProtocolsHeader(); public static final HeaderValueType<String> WEBSOCKET_PROTOCOL = new StringHeader(HttpHeaders.Names.WEBSOCKET_PROTOCOL); // public static final HeaderValueType<URL> WEBSOCKET_LOCATION = new WebSocketLocationHeader(); public static final HeaderValueType<String> UPGRADE = stringHeader(HttpHeaders.Names.UPGRADE.toString()); public static final HeaderValueType<String> REFERRER = stringHeader(HttpHeaders.Names.REFERER.toString()); public static final HeaderValueType<String> TRANSFER_ENCODING = stringHeader(HttpHeaders.Names.TRANSFER_ENCODING.toString()); public static final HeaderValueType<String> ACCESS_CONTROL_ALLOW_ORIGIN = stringHeader(HttpHeaders.Names.ACCESS_CONTROL_ALLOW_ORIGIN.toString()); public static final HeaderValueType<String> ACCESS_CONTROL_ALLOW_METHODS = stringHeader(HttpHeaders.Names.ACCESS_CONTROL_ALLOW_METHODS.toString()); public static final HeaderValueType<HeaderValueType<?>[]> ACCESS_CONTROL_ALLOW_HEADERS = new HeaderNamesHeader(HttpHeaders.Names.ACCESS_CONTROL_ALLOW_HEADERS); public static final HeaderValueType<Duration> ACCESS_CONTROL_MAX_AGE = new DurationHeader(HttpHeaders.Names.ACCESS_CONTROL_MAX_AGE.toString()); public static HeaderValueType<String> stringHeader(String key) { return new StringHeader(key); } public static <T> T read(HeaderValueType<T> type, HttpMessage msg) { String val = msg.headers().get(type.name()); return val == null ? null : type.toValue(val); } public static <T> String writeIfNotNull(HeaderValueType<T> type, T value, HttpMessage msg) { if (value != null) { return write(type, value, msg); } return null; } public static <T> String write(HeaderValueType<T> type, T value, HttpMessage msg) { Checks.notNull("type", type); Checks.notNull("msg", msg); Checks.notNull("value " + type, value); String val = type.toString(value); msg.headers().add(type.name(), val); return val; } public static final DateTimeFormatter ISO2822DateFormat = new DateTimeFormatterBuilder().appendDayOfWeekShortText() .appendLiteral(", ").appendDayOfMonth(2).appendLiteral(" ") .appendMonthOfYearShortText().appendLiteral(" ") .appendYear(4, 4).appendLiteral(" ").appendHourOfDay(2) .appendLiteral(":").appendMinuteOfHour(2).appendLiteral(":") .appendSecondOfMinute(2).appendLiteral(" ") .appendTimeZoneOffset("GMT", true, 2, 2) // .appendLiteral(" GMT") .toFormatter(); public static String toISO2822Date(DateTime dt) { dt = new DateTime(dt.getMillis(), DateTimeZone.UTC); return dt.toDateTime(DateTimeZone.UTC).toDateTimeISO().toString( ISO2822DateFormat); } public static HeaderValueType<String> custom(String name) { return new StringHeader(name); } }