diff --git a/akka-http-core/src/main/java/akka/http/model/japi/ChunkStreamPart.java b/akka-http-core/src/main/java/akka/http/model/japi/ChunkStreamPart.java new file mode 100644 index 0000000000..ace0b4817d --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/ChunkStreamPart.java @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.util.ByteString; + +/** + * Represents part of a stream of incoming data for `Transfer-Encoding: chunked` messages. + */ +public abstract class ChunkStreamPart { + /** + * Returns the byte data of this chunk. Will be non-empty for every regular + * chunk. Will be empty for the last chunk. + */ + public abstract ByteString data(); + + /** + * Returns extensions data for this chunk. + */ + public abstract String extension(); + + /** + * Returns if this is the last chunk + */ + public abstract boolean isLastChunk(); + + /** + * If this is the last chunk, this will return an Iterable of the trailer headers. Otherwise, + * it will be empty. + */ + public abstract Iterable getTrailerHeaders(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/ContentRange.java b/akka-http-core/src/main/java/akka/http/model/japi/ContentRange.java new file mode 100644 index 0000000000..d1b031c79a --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/ContentRange.java @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.http.model.ContentRange$; +import akka.japi.Option; + +public abstract class ContentRange { + public abstract boolean isByteContentRange(); + public abstract boolean isSatisfiable(); + public abstract boolean isOther(); + + public abstract Option getSatisfiableFirst(); + public abstract Option getSatisfiableLast(); + + public abstract Option getOtherValue(); + + public abstract Option getInstanceLength(); + + public static ContentRange create(long first, long last) { + return ContentRange$.MODULE$.apply(first, last); + } + public static ContentRange create(long first, long last, long instanceLength) { + return ContentRange$.MODULE$.apply(first, last, instanceLength); + } + @SuppressWarnings("unchecked") + public static ContentRange create(long first, long last, Option instanceLength) { + return ContentRange$.MODULE$.apply(first, last, ((Option) (Option) instanceLength).asScala()); + } + public static ContentRange createUnsatisfiable(long length) { + return new akka.http.model.ContentRange.Unsatisfiable(length); + } + public static ContentRange createOther(String value) { + return new akka.http.model.ContentRange.Other(value); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/ContentType.java b/akka-http-core/src/main/java/akka/http/model/japi/ContentType.java new file mode 100644 index 0000000000..0660944255 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/ContentType.java @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Represents an Http content-type. A content-type consists of a media-type and an optional charset. + */ +public abstract class ContentType { + /** + * Returns the media-type of the this content-type. + */ + public abstract MediaType mediaType(); + + /** + * Returns if this content-type defines a charset. + */ + public abstract boolean isCharsetDefined(); + + /** + * Returns the charset of this content-type if there is one or throws an exception + * otherwise. + */ + public abstract HttpCharset getDefinedCharset(); + + /** + * Creates a content-type from a media-type and a charset. + */ + public static ContentType create(MediaType mediaType, HttpCharset charset) { + return akka.http.model.ContentType.apply((akka.http.model.MediaType) mediaType, (akka.http.model.HttpCharset) charset); + } + + /** + * Creates a content-type from a media-type without specifying a charset. + */ + public static ContentType create(MediaType mediaType) { + return akka.http.model.ContentType.apply((akka.http.model.MediaType) mediaType); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/DateTime.java b/akka-http-core/src/main/java/akka/http/model/japi/DateTime.java new file mode 100644 index 0000000000..87468f92da --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/DateTime.java @@ -0,0 +1,123 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.japi.Option; + +/** + * Immutable, fast and efficient Date + Time implementation without any dependencies. + * Does not support TimeZones, all DateTime values are always GMT based. + * Note that this implementation discards milliseconds (i.e. rounds down to full seconds). + */ +public abstract class DateTime { + /** + * Returns the year of this instant in GMT. + */ + public abstract int year(); + + /** + * Returns the month of this instant in GMT. + */ + public abstract int month(); + + /** + * Returns the day of this instant in GMT. + */ + public abstract int day(); + + /** + * Returns the hour of this instant in GMT. + */ + public abstract int hour(); + + /** + * Returns the minute of this instant in GMT. + */ + public abstract int minute(); + + /** + * Returns the second of this instant in GMT. + */ + public abstract int second(); + + /** + * Returns the weekday of this instant in GMT. Sunday is 0, Monday is 1, etc. + */ + public abstract int weekday(); + + /** + * Returns this instant as "clicks", i.e. as milliseconds since January 1, 1970, 00:00:00 GMT + */ + public abstract long clicks(); + + /** + * Returns if this instant interpreted as a Date in GMT belongs to a leap year. + */ + public abstract boolean isLeapYear(); + + /** + * Returns the day of the week as a 3 letter abbreviation: + * `Sun`, `Mon`, `Tue`, `Wed`, `Thu`, `Fri` or `Sat` + */ + public abstract String weekdayStr(); + + /** + * Returns the the month as a 3 letter abbreviation: + * `Jan`, `Feb`, `Mar`, `Apr`, `May`, `Jun`, `Jul`, `Aug`, `Sep`, `Oct`, `Nov` or `Dec` + */ + public abstract String monthStr(); + + /** + * Returns a String representation like this: `yyyy-mm-dd` + */ + public abstract String toIsoDateString(); + + /** + * Returns a String representation like this: `yyyy-mm-ddThh:mm:ss` + */ + public abstract String toIsoDateTimeString(); + + /** + * Returns a String representation like this: `yyyy-mm-dd hh:mm:ss` + */ + public abstract String toIsoLikeDateTimeString(); + + /** + * Returns an RFC1123 date string, e.g. `Sun, 06 Nov 1994 08:49:37 GMT` + */ + public abstract String toRfc1123DateTimeString(); + + /** + * Returns a new DateTime instance representing the current instant. + */ + public static DateTime now() { + return akka.http.util.DateTime.now(); + } + + /** + * Returns a new DateTime instance parsed from IsoDateTimeString as Some(dateTime). Returns None if + * parsing has failed. + */ + public static Option fromIsoDateTimeString(String isoDateTimeString) { + return Util.convertOption(akka.http.util.DateTime.fromIsoDateTimeString(isoDateTimeString)); + } + + /** + * Returns a new DateTime instance representing the instant as defined by "clicks" + * i.e. from the number of milliseconds since the start of "the epoch", namely + * January 1, 1970, 00:00:00 GMT. + * Note that this implementation discards milliseconds (i.e. rounds down to full seconds). + */ + public static DateTime create(long clicks) { + return akka.http.util.DateTime.apply(clicks); + } + + /** + * Returns a new DateTime instance by interpreting the given date/time components as an instant in GMT. + */ + public static DateTime create(int year, int month, int day, int hour, int minute, int second) { + return akka.http.util.DateTime.apply(year, month, day, hour, minute, second); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/Host.java b/akka-http-core/src/main/java/akka/http/model/japi/Host.java new file mode 100644 index 0000000000..d225a9fdba --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/Host.java @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.http.model.Uri; + +import java.net.InetAddress; +import java.nio.charset.Charset; + +/** + * Represents a host in a URI or a Host header. The host can either be empty or be represented + * by an IPv4 or IPv6 address or by a host name. + */ +public abstract class Host { + /** + * Returns a String representation of the address. + */ + public abstract String address(); + public abstract boolean isEmpty(); + public abstract boolean isIPv4(); + public abstract boolean isIPv6(); + public abstract boolean isNamedHost(); + + /** + * Returns an Iterable of InetAddresses represented by this Host. If this Host is empty the + * returned Iterable will be empty. If this is an IP address the Iterable will contain this address. + * If this Host is represented by a host name, the name will be looked up and return all found + * addresses for this name. + */ + public abstract Iterable getInetAddresses(); + + /** + * The constant representing an empty Host. + */ + public static final Host EMPTY = akka.http.model.Uri$Host$Empty$.MODULE$; + + /** + * Parse the given Host string using the default charset and parsing-mode. + */ + public static Host create(String string) { + return create(string, Uri.Host$.MODULE$.apply$default$2()); + } + + /** + * Parse the given Host string using the given charset and the default parsing-mode. + */ + public static Host create(String string, Charset charset) { + return Uri.Host$.MODULE$.apply(string, charset, Uri.Host$.MODULE$.apply$default$3()); + } + + /** + * Parse the given Host string using the given charset and parsing-mode. + */ + public static Host create(String string, Charset charset, Uri.ParsingMode parsingMode) { + return Uri.Host$.MODULE$.apply(string, charset, parsingMode); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/Http.java b/akka-http-core/src/main/java/akka/http/model/japi/Http.java new file mode 100644 index 0000000000..6a96163352 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/Http.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.actor.ActorSystem; +import akka.http.HttpExt; + +public final class Http { + private Http(){} + + /** Returns the Http extension for an ActorSystem */ + public static HttpExt get(ActorSystem system) { + return (HttpExt) akka.http.Http.get(system); + } + /** Create a Bind message to send to the Http Manager */ + public static Object bind(String host, int port) { + return Accessors$.MODULE$.Bind(host, port); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpCharset.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpCharset.java new file mode 100644 index 0000000000..1bd92f72a5 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpCharset.java @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Represents a charset in Http. See {@link HttpCharsets} for a set of predefined charsets and + * static constructors to create and register custom charsets. + */ +public abstract class HttpCharset { + /** + * Returns the name of this charset. + */ + public abstract String value(); + + /** + * Creates a range from this charset with qValue = 1. + */ + public HttpCharsetRange toRange() { + return withQValue(1f); + } + + /** + * Creates a range from this charset with the given qValue. + */ + public HttpCharsetRange toRange(float qValue) { + return withQValue(qValue); + } + + /** + * An alias for toRange(float). + */ + public abstract HttpCharsetRange withQValue(float qValue); + + /** + * Returns the predefined (and registered) alias names for this charset. + */ + public abstract Iterable getAliases(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpCharsetRange.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpCharsetRange.java new file mode 100644 index 0000000000..85fb4d8d3d --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpCharsetRange.java @@ -0,0 +1,31 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Represents an Http charset range. This can either be `*` which matches all charsets or a specific + * charset. {@link HttpCharsetRanges} contains static constructors for HttpCharsetRanges. + */ +public abstract class HttpCharsetRange { + /** + * Returns if this range matches all charsets. + */ + public abstract boolean matchesAll(); + + /** + * The qValue for this range. + */ + public abstract float qValue(); + + /** + * Returns if the given charset matches this range. + */ + public abstract boolean matches(HttpCharset charset); + + /** + * Returns a copy of this range with the given qValue. + */ + public abstract HttpCharsetRange withQValue(float qValue); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpCharsetRanges.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpCharsetRanges.java new file mode 100644 index 0000000000..76b4b3a678 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpCharsetRanges.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Contains constructors to create a HttpCharsetRange. + */ +public final class HttpCharsetRanges { + private HttpCharsetRanges() {} + + /** + * A constant representing the range that matches all charsets. + */ + public static final HttpCharsetRange ALL = akka.http.model.HttpCharsetRange.$times$.MODULE$; +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpCharsets.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpCharsets.java new file mode 100644 index 0000000000..eb151901c6 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpCharsets.java @@ -0,0 +1,39 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.http.model.HttpCharsets$; +import akka.japi.Option; + +/** + * Contains a set of predefined charsets. + */ +public final class HttpCharsets { + private HttpCharsets() {} + + public static final HttpCharset US_ASCII = akka.http.model.HttpCharsets.US$minusASCII(); + public static final HttpCharset ISO_8859_1 = akka.http.model.HttpCharsets.ISO$minus8859$minus1(); + public static final HttpCharset UTF_8 = akka.http.model.HttpCharsets.UTF$minus8(); + public static final HttpCharset UTF_16 = akka.http.model.HttpCharsets.UTF$minus16(); + public static final HttpCharset UTF_16BE = akka.http.model.HttpCharsets.UTF$minus16BE(); + public static final HttpCharset UTF_16LE = akka.http.model.HttpCharsets.UTF$minus16LE(); + + /** + * Registers a custom charset. Returns Some(newCharset) if the charset is supported by this JVM. + * Returns None otherwise. + */ + public static Option registerCustom(String value, String... aliases) { + scala.Option custom = akka.http.model.HttpCharset.custom(value, Util.convertArray(aliases)); + if (custom.isDefined()) return Option.some(akka.http.model.HttpCharsets.register(custom.get())); + else return Option.none(); + } + + /** + * Returns Some(charset) if the charset with the given name was found and None otherwise. + */ + public static Option lookup(String name) { + return Util.lookupInRegistry(HttpCharsets$.MODULE$, name); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpEntity.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntity.java new file mode 100644 index 0000000000..9cb5c28ca0 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntity.java @@ -0,0 +1,110 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.http.model.HttpEntity$; +import akka.stream.FlowMaterializer; +import akka.util.ByteString; +import org.reactivestreams.api.Producer; + +import java.io.File; + +/** + * Represents the entity of an Http message. An entity consists of the content-type of the data + * and the actual data itself. Some subtypes of HttpEntity also define the content-length of the + * data. + * + * An HttpEntity can be of several kinds: + * + * - HttpEntity.Empty: the statically known empty entity + * - HttpEntityDefault: the default entity which has a known length and which contains + * a stream of ByteStrings. + * - HttpEntityChunked: represents an entity that is delivered using `Transfer-Encoding: chunked` + * - HttpEntityCloseDelimited: the entity which doesn't have a fixed length but which is delimited by + * closing the connection. + * + * All entity subtypes but HttpEntityCloseDelimited are subtypes of {@link HttpEntityRegular} which + * means they can be used in Http request that disallow close-delimited transfer of the entity. + */ +public abstract class HttpEntity { + /** + * Returns the content-type of this entity + */ + public abstract ContentType contentType(); + + /** + * The empty entity. + */ + public static final HttpEntityStrict EMPTY = HttpEntity$.MODULE$.Empty(); + + /** + * Returns if this entity is known to be empty. Open-ended entity types like + * HttpEntityChunked and HttpCloseDelimited will always return false here. + */ + public abstract boolean isKnownEmpty(); + + /** + * Returns if this entity is a subtype of HttpEntityRegular. + */ + public abstract boolean isRegular(); + + /** + * Returns if this entity is a subtype of HttpEntityChunked. + */ + public abstract boolean isChunked(); + + /** + * Returns if this entity is a subtype of HttpEntityDefault. + */ + public abstract boolean isDefault(); + + /** + * Returns if this entity is a subtype of HttpEntityCloseDelimited. + */ + public abstract boolean isCloseDelimited(); + + /** + * Returns a stream of data bytes this entity consists of. + */ + public abstract Producer getDataBytes(FlowMaterializer materializer); + + public static HttpEntityStrict create(String string) { + return HttpEntity$.MODULE$.apply(string); + } + public static HttpEntityStrict create(byte[] bytes) { + return HttpEntity$.MODULE$.apply(bytes); + } + public static HttpEntityStrict create(ByteString bytes) { + return HttpEntity$.MODULE$.apply(bytes); + } + public static HttpEntityStrict create(ContentType contentType, String string) { + return HttpEntity$.MODULE$.apply((akka.http.model.ContentType) contentType, string); + } + public static HttpEntityStrict create(ContentType contentType, byte[] bytes) { + return HttpEntity$.MODULE$.apply((akka.http.model.ContentType) contentType, bytes); + } + public static HttpEntityStrict create(ContentType contentType, ByteString bytes) { + return HttpEntity$.MODULE$.apply((akka.http.model.ContentType) contentType, bytes); + } + public static HttpEntityRegular create(ContentType contentType, File file) { + return (HttpEntityRegular) HttpEntity$.MODULE$.apply((akka.http.model.ContentType) contentType, file); + } + public static HttpEntityDefault create(ContentType contentType, long contentLength, Producer data) { + return new akka.http.model.HttpEntity.Default((akka.http.model.ContentType) contentType, contentLength, data); + } + public static HttpEntityCloseDelimited createCloseDelimited(ContentType contentType, Producer data) { + return new akka.http.model.HttpEntity.CloseDelimited((akka.http.model.ContentType) contentType, data); + } + public static HttpEntityChunked createChunked(ContentType contentType, Producer chunks) { + return new akka.http.model.HttpEntity.Chunked( + (akka.http.model.ContentType) contentType, + Util.upcastProducer(chunks)); + } + public static HttpEntityChunked createChunked(ContentType contentType, Producer data, FlowMaterializer materializer) { + return akka.http.model.HttpEntity.Chunked$.MODULE$.apply( + (akka.http.model.ContentType) contentType, + data, materializer); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityChunked.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityChunked.java new file mode 100644 index 0000000000..a1d9acfae2 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityChunked.java @@ -0,0 +1,15 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import org.reactivestreams.api.Producer; + +/** + * Represents an entity transferred using `Transfer-Encoding: chunked`. It consists of a + * stream of {@link ChunkStreamPart}. + */ +public abstract class HttpEntityChunked extends HttpEntityRegular { + public abstract Producer getChunks(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityCloseDelimited.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityCloseDelimited.java new file mode 100644 index 0000000000..a5ab33b8ab --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityCloseDelimited.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.util.ByteString; +import org.reactivestreams.api.Producer; + +/** + * Represents an entity without a predetermined content-length. Its length is implicitly + * determined by closing the underlying connection. Therefore, this entity type is only + * available for Http responses. + */ +public abstract class HttpEntityCloseDelimited extends HttpEntity { + public abstract Producer data(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityDefault.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityDefault.java new file mode 100644 index 0000000000..9f35dab0aa --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityDefault.java @@ -0,0 +1,16 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.util.ByteString; +import org.reactivestreams.api.Producer; + +/** + * The default entity type which has a predetermined length and a stream of data bytes. + */ +public abstract class HttpEntityDefault extends HttpEntityRegular { + public abstract long contentLength(); + public abstract Producer data(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityRegular.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityRegular.java new file mode 100644 index 0000000000..f8a2563ef1 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityRegular.java @@ -0,0 +1,14 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.util.ByteString; + +import java.io.File; + +/** + * A marker type that denotes HttpEntity subtypes that can be used in Http requests. + */ +public abstract class HttpEntityRegular extends HttpEntity {} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityStrict.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityStrict.java new file mode 100644 index 0000000000..dd314b8a7e --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpEntityStrict.java @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.util.ByteString; + +/** + * The entity type which consists of a predefined fixed ByteString of data. + */ +public abstract class HttpEntityStrict extends HttpEntityRegular { + public abstract ByteString data(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpHeader.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpHeader.java new file mode 100644 index 0000000000..f55dafdc8b --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpHeader.java @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * The base type representing Http headers. All actual header values will be instances + * of one of the subtypes defined in the `headers` packages. Unknown headers will be subtypes + * of {@link akka.http.model.japi.headers.RawHeader}. + */ +public abstract class HttpHeader { + /** + * Returns the name of the header. + */ + public abstract String name(); + + /** + * Returns the String representation of the value of the header. + */ + public abstract String value(); + + /** + * Returns the lower-cased name of the header. + */ + public abstract String lowercaseName(); + + /** + * Returns true iff nameInLowerCase.equals(lowercaseName()). + */ + public abstract boolean is(String nameInLowerCase); + + /** + * Returns !is(nameInLowerCase). + */ + public abstract boolean isNot(String nameInLowerCase); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpMessage.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpMessage.java new file mode 100644 index 0000000000..122c4fcce9 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpMessage.java @@ -0,0 +1,114 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.japi.Option; +import akka.util.ByteString; + +import java.io.File; + +/** + * The base type for an Http message (request or response). + */ +public interface HttpMessage { + /** + * Is this instance a request. + */ + boolean isRequest(); + + /** + * Is this instance a response. + */ + boolean isResponse(); + + /** + * The protocol of this message. + */ + HttpProtocol protocol(); + + /** + * An iterable containing the headers of this message. + */ + Iterable getHeaders(); + + /** + * Try to find the first header with the given name (case-insensitive) and return + * Some(header), otherwise this method returns None. + */ + Option getHeader(String headerName); + + /** + * Try to find the first header of the given class and return + * Some(header), otherwise this method returns None. + */ + Option getHeader(Class headerClass); + + /** + * The entity of this message. + */ + HttpEntity entity(); + + public static interface MessageTransformations { + /** + * Returns a copy of this message with a new protocol. + */ + Self withProtocol(HttpProtocol protocol); + + /** + * Returns a copy of this message with the given header added to the list of headers. + */ + Self addHeader(HttpHeader header); + + /** + * Returns a copy of this message with the given headers added to the list of headers. + */ + Self addHeaders(Iterable headers); + + /** + * Returns a copy of this message with all headers of the given name (case-insensitively) removed. + */ + Self removeHeader(String headerName); + + /** + * Returns a copy of this message with a new entity. + */ + Self withEntity(HttpEntity entity); + + /** + * Returns a copy of this message with a new entity. + */ + Self withEntity(String string); + + /** + * Returns a copy of Self message with a new entity. + */ + Self withEntity(byte[] bytes); + + /** + * Returns a copy of Self message with a new entity. + */ + Self withEntity(ByteString bytes); + + /** + * Returns a copy of Self message with a new entity. + */ + Self withEntity(ContentType type, String string); + + /** + * Returns a copy of Self message with a new entity. + */ + Self withEntity(ContentType type, byte[] bytes); + + /** + * Returns a copy of Self message with a new entity. + */ + Self withEntity(ContentType type, ByteString bytes); + + /** + * Returns a copy of Self message with a new entity. + */ + Self withEntity(ContentType type, File file); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpMethod.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpMethod.java new file mode 100644 index 0000000000..fc2e18290d --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpMethod.java @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Represents an HTTP request method. See {@link HttpMethods} for a set of predefined methods + * and static constructors to build and register custom ones. + */ +public abstract class HttpMethod { + /** + * Returns the name of the method. + */ + public abstract String value(); + + /** + * Returns if this method is "safe" as defined in + * http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-4.2.1 + */ + public abstract boolean isSafe(); + + /** + * Returns if this method is "idempotent" as defined in + * http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-4.2.2 + */ + public abstract boolean isIdempotent(); + + /** + * Returns if requests with this method may contain an entity. + */ + public abstract boolean isEntityAccepted(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpMethods.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpMethods.java new file mode 100644 index 0000000000..8defa300aa --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpMethods.java @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.japi.Option; +import akka.http.model.HttpMethods$; + +/** + * Contains static constants for predefined method types. + */ +public final class HttpMethods { + private HttpMethods() {} + + public static final HttpMethod CONNECT = akka.http.model.HttpMethods.CONNECT(); + public static final HttpMethod DELETE = akka.http.model.HttpMethods.DELETE(); + public static final HttpMethod GET = akka.http.model.HttpMethods.GET(); + public static final HttpMethod HEAD = akka.http.model.HttpMethods.HEAD(); + public static final HttpMethod OPTIONS = akka.http.model.HttpMethods.OPTIONS(); + public static final HttpMethod PATCH = akka.http.model.HttpMethods.PATCH(); + public static final HttpMethod POST = akka.http.model.HttpMethods.POST(); + public static final HttpMethod PUT = akka.http.model.HttpMethods.PUT(); + public static final HttpMethod TRACE = akka.http.model.HttpMethods.TRACE(); + + /** + * Register a custom method type. + */ + public static HttpMethod registerCustom(String value, boolean safe, boolean idempotent, boolean entityAccepted) { + return akka.http.model.HttpMethods.register(akka.http.model.HttpMethod.custom(value, safe, idempotent, entityAccepted)); + } + + public static Option lookup(String name) { + return Util.lookupInRegistry(HttpMethods$.MODULE$, name); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpProtocol.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpProtocol.java new file mode 100644 index 0000000000..2d0a56d52d --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpProtocol.java @@ -0,0 +1,16 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Represents an Http protocol (currently only HTTP/1.0 or HTTP/1.1). See {@link HttpProtocols} + * for the predefined constants for the supported protocols. + */ +public abstract class HttpProtocol { + /** + * Returns the String representation of this protocol. + */ + public abstract String value(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpProtocols.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpProtocols.java new file mode 100644 index 0000000000..70e5c37cf8 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpProtocols.java @@ -0,0 +1,15 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Contains constants of the supported Http protocols. + */ +public final class HttpProtocols { + private HttpProtocols() {} + + final HttpProtocol HTTP_1_0 = akka.http.model.HttpProtocols.HTTP$div1$u002E0(); + final HttpProtocol HTTP_1_1 = akka.http.model.HttpProtocols.HTTP$div1$u002E1(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpRequest.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpRequest.java new file mode 100644 index 0000000000..1c9f6e6b8c --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpRequest.java @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Represents an Http request. + */ +public abstract class HttpRequest implements HttpMessage, HttpMessage.MessageTransformations { + /** + * Returns the Http method of this request. + */ + public abstract HttpMethod method(); + + /** + * Returns the Uri of this request. + */ + public abstract Uri getUri(); + + /** + * Returns the entity of this request. + */ + public abstract HttpEntityRegular entity(); + + /** + * Returns a copy of this instance with a new method. + */ + public abstract HttpRequest withMethod(HttpMethod method); + + /** + * Returns a copy of this instance with a new Uri. + */ + public abstract HttpRequest withUri(Uri relativeUri); + + /** + * Returns a copy of this instance with a new Uri. + */ + public abstract HttpRequest withUri(String path); + + /** + * Returns a default request to be changed using the `withX` methods. + */ + public static HttpRequest create() { + return Accessors$.MODULE$.HttpRequest(); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/HttpResponse.java b/akka-http-core/src/main/java/akka/http/model/japi/HttpResponse.java new file mode 100644 index 0000000000..5ade0343c8 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/HttpResponse.java @@ -0,0 +1,32 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Represents an Http response. + */ +public abstract class HttpResponse implements HttpMessage, HttpMessage.MessageTransformations { + /** + * Returns the status-code of this response. + */ + public abstract StatusCode status(); + + /** + * Returns a copy of this instance with a new status-code. + */ + public abstract HttpResponse withStatus(StatusCode statusCode); + + /** + * Returns a copy of this instance with a new status-code. + */ + public abstract HttpResponse withStatus(int statusCode); + + /** + * Returns a default response to be changed using the `withX` methods. + */ + public static HttpResponse create() { + return Accessors$.MODULE$.HttpResponse(); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/IncomingConnection.java b/akka-http-core/src/main/java/akka/http/model/japi/IncomingConnection.java new file mode 100644 index 0000000000..6db37fb9d3 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/IncomingConnection.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import org.reactivestreams.api.Consumer; +import org.reactivestreams.api.Producer; + +import java.net.InetSocketAddress; + +/** + * Represents one incoming connection. + */ +public interface IncomingConnection { + /** + * The address of the other peer. + */ + InetSocketAddress remoteAddress(); + + /** + * A stream of requests coming in from the peer. + */ + Producer getRequestProducer(); + + /** + * A consumer of HttpResponses to be sent to the peer. + */ + Consumer getResponseConsumer(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/MediaRange.java b/akka-http-core/src/main/java/akka/http/model/japi/MediaRange.java new file mode 100644 index 0000000000..30d576ed5d --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/MediaRange.java @@ -0,0 +1,39 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import java.util.Map; + +/** + * Represents an Http media-range. A media-range either matches a single media-type + * or it matches all media-types of a given main-type. Each range can specify a qValue + * or other parameters. + */ +public abstract class MediaRange { + /** + * Returns the main-type this media-range matches. + */ + public abstract String mainType(); + + /** + * Returns the qValue of this media-range. + */ + public abstract float qValue(); + + /** + * Checks if this range matches a given media-type. + */ + public abstract boolean matches(MediaType mediaType); + + /** + * Returns a Map of the parameters of this media-range. + */ + public abstract Map getParams(); + + /** + * Returns a copy of this instance with a changed qValue. + */ + public abstract MediaRange withQValue(float qValue); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/MediaRanges.java b/akka-http-core/src/main/java/akka/http/model/japi/MediaRanges.java new file mode 100644 index 0000000000..8d7c19a4ae --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/MediaRanges.java @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import java.util.Map; + +/** + * Contains a set of predefined media-ranges and static methods to create custom ones. + */ +public final class MediaRanges { + private MediaRanges() {} + + public static final MediaRange ALL = akka.http.model.MediaRanges.$times$div$times(); + public static final MediaRange ALL_APPLICATION = akka.http.model.MediaRanges.application$div$times(); + public static final MediaRange ALL_AUDIO = akka.http.model.MediaRanges.audio$div$times(); + public static final MediaRange ALL_IMAGE = akka.http.model.MediaRanges.image$div$times(); + public static final MediaRange ALL_MESSAGE = akka.http.model.MediaRanges.message$div$times(); + public static final MediaRange ALL_MULTIPART = akka.http.model.MediaRanges.multipart$div$times(); + public static final MediaRange ALL_TEXT = akka.http.model.MediaRanges.text$div$times(); + public static final MediaRange ALL_VIDEO = akka.http.model.MediaRanges.video$div$times(); + + /** + * Creates a custom universal media-range for a given main-type. + */ + public static MediaRange create(MediaType mediaType) { + return akka.http.model.MediaRange.apply((akka.http.model.MediaType) mediaType); + } + + /** + * Creates a custom universal media-range for a given main-type and a Map of parameters. + */ + public static MediaRange custom(String mainType, Map parameters) { + return akka.http.model.MediaRange.custom(mainType, Util.convertMapToScala(parameters), 1.0f); + } + + /** + * Creates a custom universal media-range for a given main-type and qValue. + */ + public static MediaRange create(MediaType mediaType, float qValue) { + return akka.http.model.MediaRange.apply((akka.http.model.MediaType) mediaType, qValue); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/MediaType.java b/akka-http-core/src/main/java/akka/http/model/japi/MediaType.java new file mode 100644 index 0000000000..749c92f82f --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/MediaType.java @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Represents an Http media-type. A media-type consists of a main-type and a sub-type. + */ +public abstract class MediaType { + /** + * Returns the main-type of this media-type. + */ + public abstract String mainType(); + + /** + * Returns the sub-type of this media-type. + */ + public abstract String subType(); + + /** + * Creates a media-range from this media-type. + */ + public MediaRange toRange() { + return MediaRanges.create(this); + } + + /** + * Creates a media-range from this media-type with a given qValue. + */ + public MediaRange toRange(float qValue) { + return MediaRanges.create(this, qValue); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/MediaTypes.java b/akka-http-core/src/main/java/akka/http/model/japi/MediaTypes.java new file mode 100644 index 0000000000..cef317ff55 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/MediaTypes.java @@ -0,0 +1,200 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.http.model.MediaTypes$; +import akka.japi.Option; + +import java.util.Map; + +/** + * Contains the set of predefined media-types. + */ +public abstract class MediaTypes { + public static final MediaType APPLICATION_ATOM_XML = akka.http.model.MediaTypes.application$divatom$plusxml(); + public static final MediaType APPLICATION_BASE64 = akka.http.model.MediaTypes.application$divbase64(); + public static final MediaType APPLICATION_EXCEL = akka.http.model.MediaTypes.application$divexcel(); + public static final MediaType APPLICATION_FONT_WOFF = akka.http.model.MediaTypes.application$divfont$minuswoff(); + public static final MediaType APPLICATION_GNUTAR = akka.http.model.MediaTypes.application$divgnutar(); + public static final MediaType APPLICATION_JAVA_ARCHIVE = akka.http.model.MediaTypes.application$divjava$minusarchive(); + public static final MediaType APPLICATION_JAVASCRIPT = akka.http.model.MediaTypes.application$divjavascript(); + public static final MediaType APPLICATION_JSON = akka.http.model.MediaTypes.application$divjson(); + public static final MediaType APPLICATION_JSON_PATCH_JSON = akka.http.model.MediaTypes.application$divjson$minuspatch$plusjson(); + public static final MediaType APPLICATION_LHA = akka.http.model.MediaTypes.application$divlha(); + public static final MediaType APPLICATION_LZX = akka.http.model.MediaTypes.application$divlzx(); + public static final MediaType APPLICATION_MSPOWERPOINT = akka.http.model.MediaTypes.application$divmspowerpoint(); + public static final MediaType APPLICATION_MSWORD = akka.http.model.MediaTypes.application$divmsword(); + public static final MediaType APPLICATION_OCTET_STREAM = akka.http.model.MediaTypes.application$divoctet$minusstream(); + public static final MediaType APPLICATION_PDF = akka.http.model.MediaTypes.application$divpdf(); + public static final MediaType APPLICATION_POSTSCRIPT = akka.http.model.MediaTypes.application$divpostscript(); + public static final MediaType APPLICATION_RSS_XML = akka.http.model.MediaTypes.application$divrss$plusxml(); + public static final MediaType APPLICATION_SOAP_XML = akka.http.model.MediaTypes.application$divsoap$plusxml(); + public static final MediaType APPLICATION_VND_API_JSON = akka.http.model.MediaTypes.application$divvnd$u002Eapi$plusjson(); + public static final MediaType APPLICATION_VND_GOOGLE_EARTH_KML_XML = akka.http.model.MediaTypes.application$divvnd$u002Egoogle$minusearth$u002Ekml$plusxml(); + public static final MediaType APPLICATION_VND_GOOGLE_EARTH_KMZ = akka.http.model.MediaTypes.application$divvnd$u002Egoogle$minusearth$u002Ekmz(); + public static final MediaType APPLICATION_VND_MS_FONTOBJECT = akka.http.model.MediaTypes.application$divvnd$u002Ems$minusfontobject(); + public static final MediaType APPLICATION_VND_OASIS_OPENDOCUMENT_CHART = akka.http.model.MediaTypes.application$divvnd$u002Eoasis$u002Eopendocument$u002Echart(); + public static final MediaType APPLICATION_VND_OASIS_OPENDOCUMENT_DATABASE = akka.http.model.MediaTypes.application$divvnd$u002Eoasis$u002Eopendocument$u002Edatabase(); + public static final MediaType APPLICATION_VND_OASIS_OPENDOCUMENT_FORMULA = akka.http.model.MediaTypes.application$divvnd$u002Eoasis$u002Eopendocument$u002Eformula(); + public static final MediaType APPLICATION_VND_OASIS_OPENDOCUMENT_GRAPHICS = akka.http.model.MediaTypes.application$divvnd$u002Eoasis$u002Eopendocument$u002Egraphics(); + public static final MediaType APPLICATION_VND_OASIS_OPENDOCUMENT_IMAGE = akka.http.model.MediaTypes.application$divvnd$u002Eoasis$u002Eopendocument$u002Eimage(); + public static final MediaType APPLICATION_VND_OASIS_OPENDOCUMENT_PRESENTATION = akka.http.model.MediaTypes.application$divvnd$u002Eoasis$u002Eopendocument$u002Epresentation(); + public static final MediaType APPLICATION_VND_OASIS_OPENDOCUMENT_SPREADSHEET = akka.http.model.MediaTypes.application$divvnd$u002Eoasis$u002Eopendocument$u002Espreadsheet(); + public static final MediaType APPLICATION_VND_OASIS_OPENDOCUMENT_TEXT = akka.http.model.MediaTypes.application$divvnd$u002Eoasis$u002Eopendocument$u002Etext(); + public static final MediaType APPLICATION_VND_OASIS_OPENDOCUMENT_TEXT_MASTER = akka.http.model.MediaTypes.application$divvnd$u002Eoasis$u002Eopendocument$u002Etext$minusmaster(); + public static final MediaType APPLICATION_VND_OASIS_OPENDOCUMENT_TEXT_WEB = akka.http.model.MediaTypes.application$divvnd$u002Eoasis$u002Eopendocument$u002Etext$minusweb(); + public static final MediaType APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_PRESENTATIONML_PRESENTATION = akka.http.model.MediaTypes.application$divvnd$u002Eopenxmlformats$minusofficedocument$u002Epresentationml$u002Epresentation(); + public static final MediaType APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_PRESENTATIONML_SLIDE = akka.http.model.MediaTypes.application$divvnd$u002Eopenxmlformats$minusofficedocument$u002Epresentationml$u002Eslide(); + public static final MediaType APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_PRESENTATIONML_SLIDESHOW = akka.http.model.MediaTypes.application$divvnd$u002Eopenxmlformats$minusofficedocument$u002Epresentationml$u002Eslideshow(); + public static final MediaType APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_PRESENTATIONML_TEMPLATE = akka.http.model.MediaTypes.application$divvnd$u002Eopenxmlformats$minusofficedocument$u002Epresentationml$u002Etemplate(); + public static final MediaType APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_SPREADSHEETML_SHEET = akka.http.model.MediaTypes.application$divvnd$u002Eopenxmlformats$minusofficedocument$u002Espreadsheetml$u002Esheet(); + public static final MediaType APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_SPREADSHEETML_TEMPLATE = akka.http.model.MediaTypes.application$divvnd$u002Eopenxmlformats$minusofficedocument$u002Espreadsheetml$u002Etemplate(); + public static final MediaType APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_WORDPROCESSINGML_DOCUMENT = akka.http.model.MediaTypes.application$divvnd$u002Eopenxmlformats$minusofficedocument$u002Ewordprocessingml$u002Edocument(); + public static final MediaType APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_WORDPROCESSINGML_TEMPLATE = akka.http.model.MediaTypes.application$divvnd$u002Eopenxmlformats$minusofficedocument$u002Ewordprocessingml$u002Etemplate(); + public static final MediaType APPLICATION_X_7Z_COMPRESSED = akka.http.model.MediaTypes.application$divx$minus7z$minuscompressed(); + public static final MediaType APPLICATION_X_ACE_COMPRESSED = akka.http.model.MediaTypes.application$divx$minusace$minuscompressed(); + public static final MediaType APPLICATION_X_APPLE_DISKIMAGE = akka.http.model.MediaTypes.application$divx$minusapple$minusdiskimage(); + public static final MediaType APPLICATION_X_ARC_COMPRESSED = akka.http.model.MediaTypes.application$divx$minusarc$minuscompressed(); + public static final MediaType APPLICATION_X_BZIP = akka.http.model.MediaTypes.application$divx$minusbzip(); + public static final MediaType APPLICATION_X_BZIP2 = akka.http.model.MediaTypes.application$divx$minusbzip2(); + public static final MediaType APPLICATION_X_CHROME_EXTENSION = akka.http.model.MediaTypes.application$divx$minuschrome$minusextension(); + public static final MediaType APPLICATION_X_COMPRESS = akka.http.model.MediaTypes.application$divx$minuscompress(); + public static final MediaType APPLICATION_X_COMPRESSED = akka.http.model.MediaTypes.application$divx$minuscompressed(); + public static final MediaType APPLICATION_X_DEBIAN_PACKAGE = akka.http.model.MediaTypes.application$divx$minusdebian$minuspackage(); + public static final MediaType APPLICATION_X_DVI = akka.http.model.MediaTypes.application$divx$minusdvi(); + public static final MediaType APPLICATION_X_FONT_TRUETYPE = akka.http.model.MediaTypes.application$divx$minusfont$minustruetype(); + public static final MediaType APPLICATION_X_FONT_OPENTYPE = akka.http.model.MediaTypes.application$divx$minusfont$minusopentype(); + public static final MediaType APPLICATION_X_GTAR = akka.http.model.MediaTypes.application$divx$minusgtar(); + public static final MediaType APPLICATION_X_GZIP = akka.http.model.MediaTypes.application$divx$minusgzip(); + public static final MediaType APPLICATION_X_LATEX = akka.http.model.MediaTypes.application$divx$minuslatex(); + public static final MediaType APPLICATION_X_RAR_COMPRESSED = akka.http.model.MediaTypes.application$divx$minusrar$minuscompressed(); + public static final MediaType APPLICATION_X_REDHAT_PACKAGE_MANAGER = akka.http.model.MediaTypes.application$divx$minusredhat$minuspackage$minusmanager(); + public static final MediaType APPLICATION_X_SHOCKWAVE_FLASH = akka.http.model.MediaTypes.application$divx$minusshockwave$minusflash(); + public static final MediaType APPLICATION_X_TAR = akka.http.model.MediaTypes.application$divx$minustar(); + public static final MediaType APPLICATION_X_TEX = akka.http.model.MediaTypes.application$divx$minustex(); + public static final MediaType APPLICATION_X_TEXINFO = akka.http.model.MediaTypes.application$divx$minustexinfo(); + public static final MediaType APPLICATION_X_VRML = akka.http.model.MediaTypes.application$divx$minusvrml(); + public static final MediaType APPLICATION_X_WWW_FORM_URLENCODED = akka.http.model.MediaTypes.application$divx$minuswww$minusform$minusurlencoded(); + public static final MediaType APPLICATION_X_X509_CA_CERT = akka.http.model.MediaTypes.application$divx$minusx509$minusca$minuscert(); + public static final MediaType APPLICATION_X_XPINSTALL = akka.http.model.MediaTypes.application$divx$minusxpinstall(); + public static final MediaType APPLICATION_XHTML_XML = akka.http.model.MediaTypes.application$divxhtml$plusxml(); + public static final MediaType APPLICATION_XML_DTD = akka.http.model.MediaTypes.application$divxml$minusdtd(); + public static final MediaType APPLICATION_XML = akka.http.model.MediaTypes.application$divxml(); + public static final MediaType APPLICATION_ZIP = akka.http.model.MediaTypes.application$divzip(); + public static final MediaType AUDIO_AIFF = akka.http.model.MediaTypes.audio$divaiff(); + public static final MediaType AUDIO_BASIC = akka.http.model.MediaTypes.audio$divbasic(); + public static final MediaType AUDIO_MIDI = akka.http.model.MediaTypes.audio$divmidi(); + public static final MediaType AUDIO_MOD = akka.http.model.MediaTypes.audio$divmod(); + public static final MediaType AUDIO_MPEG = akka.http.model.MediaTypes.audio$divmpeg(); + public static final MediaType AUDIO_OGG = akka.http.model.MediaTypes.audio$divogg(); + public static final MediaType AUDIO_VOC = akka.http.model.MediaTypes.audio$divvoc(); + public static final MediaType AUDIO_VORBIS = akka.http.model.MediaTypes.audio$divvorbis(); + public static final MediaType AUDIO_VOXWARE = akka.http.model.MediaTypes.audio$divvoxware(); + public static final MediaType AUDIO_WAV = akka.http.model.MediaTypes.audio$divwav(); + public static final MediaType AUDIO_X_REALAUDIO = akka.http.model.MediaTypes.audio$divx$minusrealaudio(); + public static final MediaType AUDIO_X_PSID = akka.http.model.MediaTypes.audio$divx$minuspsid(); + public static final MediaType AUDIO_XM = akka.http.model.MediaTypes.audio$divxm(); + public static final MediaType AUDIO_WEBM = akka.http.model.MediaTypes.audio$divwebm(); + public static final MediaType IMAGE_GIF = akka.http.model.MediaTypes.image$divgif(); + public static final MediaType IMAGE_JPEG = akka.http.model.MediaTypes.image$divjpeg(); + public static final MediaType IMAGE_PICT = akka.http.model.MediaTypes.image$divpict(); + public static final MediaType IMAGE_PNG = akka.http.model.MediaTypes.image$divpng(); + public static final MediaType IMAGE_SVG_XML = akka.http.model.MediaTypes.image$divsvg$plusxml(); + public static final MediaType IMAGE_TIFF = akka.http.model.MediaTypes.image$divtiff(); + public static final MediaType IMAGE_X_ICON = akka.http.model.MediaTypes.image$divx$minusicon(); + public static final MediaType IMAGE_X_MS_BMP = akka.http.model.MediaTypes.image$divx$minusms$minusbmp(); + public static final MediaType IMAGE_X_PCX = akka.http.model.MediaTypes.image$divx$minuspcx(); + public static final MediaType IMAGE_X_PICT = akka.http.model.MediaTypes.image$divx$minuspict(); + public static final MediaType IMAGE_X_QUICKTIME = akka.http.model.MediaTypes.image$divx$minusquicktime(); + public static final MediaType IMAGE_X_RGB = akka.http.model.MediaTypes.image$divx$minusrgb(); + public static final MediaType IMAGE_X_XBITMAP = akka.http.model.MediaTypes.image$divx$minusxbitmap(); + public static final MediaType IMAGE_X_XPIXMAP = akka.http.model.MediaTypes.image$divx$minusxpixmap(); + public static final MediaType IMAGE_WEBP = akka.http.model.MediaTypes.image$divwebp(); + public static final MediaType MESSAGE_HTTP = akka.http.model.MediaTypes.message$divhttp(); + public static final MediaType MESSAGE_DELIVERY_STATUS = akka.http.model.MediaTypes.message$divdelivery$minusstatus(); + public static final MediaType MESSAGE_RFC822 = akka.http.model.MediaTypes.message$divrfc822(); + public static final MediaType MULTIPART_MIXED = akka.http.model.MediaTypes.multipart$divmixed(); + public static final MediaType MULTIPART_ALTERNATIVE = akka.http.model.MediaTypes.multipart$divalternative(); + public static final MediaType MULTIPART_RELATED = akka.http.model.MediaTypes.multipart$divrelated(); + public static final MediaType MULTIPART_FORM_DATA = akka.http.model.MediaTypes.multipart$divform$minusdata(); + public static final MediaType MULTIPART_SIGNED = akka.http.model.MediaTypes.multipart$divsigned(); + public static final MediaType MULTIPART_ENCRYPTED = akka.http.model.MediaTypes.multipart$divencrypted(); + public static final MediaType MULTIPART_BYTERANGES = akka.http.model.MediaTypes.multipart$divbyteranges(); + public static final MediaType TEXT_ASP = akka.http.model.MediaTypes.text$divasp(); + public static final MediaType TEXT_CACHE_MANIFEST = akka.http.model.MediaTypes.text$divcache$minusmanifest(); + public static final MediaType TEXT_CALENDAR = akka.http.model.MediaTypes.text$divcalendar(); + public static final MediaType TEXT_CSS = akka.http.model.MediaTypes.text$divcss(); + public static final MediaType TEXT_CSV = akka.http.model.MediaTypes.text$divcsv(); + public static final MediaType TEXT_HTML = akka.http.model.MediaTypes.text$divhtml(); + public static final MediaType TEXT_MCF = akka.http.model.MediaTypes.text$divmcf(); + public static final MediaType TEXT_PLAIN = akka.http.model.MediaTypes.text$divplain(); + public static final MediaType TEXT_RICHTEXT = akka.http.model.MediaTypes.text$divrichtext(); + public static final MediaType TEXT_TAB_SEPARATED_VALUES = akka.http.model.MediaTypes.text$divtab$minusseparated$minusvalues(); + public static final MediaType TEXT_URI_LIST = akka.http.model.MediaTypes.text$divuri$minuslist(); + public static final MediaType TEXT_VND_WAP_WML = akka.http.model.MediaTypes.text$divvnd$u002Ewap$u002Ewml(); + public static final MediaType TEXT_VND_WAP_WMLSCRIPT = akka.http.model.MediaTypes.text$divvnd$u002Ewap$u002Ewmlscript(); + public static final MediaType TEXT_X_ASM = akka.http.model.MediaTypes.text$divx$minusasm(); + public static final MediaType TEXT_X_C = akka.http.model.MediaTypes.text$divx$minusc(); + public static final MediaType TEXT_X_COMPONENT = akka.http.model.MediaTypes.text$divx$minuscomponent(); + public static final MediaType TEXT_X_H = akka.http.model.MediaTypes.text$divx$minush(); + public static final MediaType TEXT_X_JAVA_SOURCE = akka.http.model.MediaTypes.text$divx$minusjava$minussource(); + public static final MediaType TEXT_X_PASCAL = akka.http.model.MediaTypes.text$divx$minuspascal(); + public static final MediaType TEXT_X_SCRIPT = akka.http.model.MediaTypes.text$divx$minusscript(); + public static final MediaType TEXT_X_SCRIPTCSH = akka.http.model.MediaTypes.text$divx$minusscriptcsh(); + public static final MediaType TEXT_X_SCRIPTELISP = akka.http.model.MediaTypes.text$divx$minusscriptelisp(); + public static final MediaType TEXT_X_SCRIPTKSH = akka.http.model.MediaTypes.text$divx$minusscriptksh(); + public static final MediaType TEXT_X_SCRIPTLISP = akka.http.model.MediaTypes.text$divx$minusscriptlisp(); + public static final MediaType TEXT_X_SCRIPTPERL = akka.http.model.MediaTypes.text$divx$minusscriptperl(); + public static final MediaType TEXT_X_SCRIPTPERL_MODULE = akka.http.model.MediaTypes.text$divx$minusscriptperl$minusmodule(); + public static final MediaType TEXT_X_SCRIPTPHYTON = akka.http.model.MediaTypes.text$divx$minusscriptphyton(); + public static final MediaType TEXT_X_SCRIPTREXX = akka.http.model.MediaTypes.text$divx$minusscriptrexx(); + public static final MediaType TEXT_X_SCRIPTSCHEME = akka.http.model.MediaTypes.text$divx$minusscriptscheme(); + public static final MediaType TEXT_X_SCRIPTSH = akka.http.model.MediaTypes.text$divx$minusscriptsh(); + public static final MediaType TEXT_X_SCRIPTTCL = akka.http.model.MediaTypes.text$divx$minusscripttcl(); + public static final MediaType TEXT_X_SCRIPTTCSH = akka.http.model.MediaTypes.text$divx$minusscripttcsh(); + public static final MediaType TEXT_X_SCRIPTZSH = akka.http.model.MediaTypes.text$divx$minusscriptzsh(); + public static final MediaType TEXT_X_SERVER_PARSED_HTML = akka.http.model.MediaTypes.text$divx$minusserver$minusparsed$minushtml(); + public static final MediaType TEXT_X_SETEXT = akka.http.model.MediaTypes.text$divx$minussetext(); + public static final MediaType TEXT_X_SGML = akka.http.model.MediaTypes.text$divx$minussgml(); + public static final MediaType TEXT_X_SPEECH = akka.http.model.MediaTypes.text$divx$minusspeech(); + public static final MediaType TEXT_X_UUENCODE = akka.http.model.MediaTypes.text$divx$minusuuencode(); + public static final MediaType TEXT_X_VCALENDAR = akka.http.model.MediaTypes.text$divx$minusvcalendar(); + public static final MediaType TEXT_X_VCARD = akka.http.model.MediaTypes.text$divx$minusvcard(); + public static final MediaType TEXT_XML = akka.http.model.MediaTypes.text$divxml(); + public static final MediaType VIDEO_AVS_VIDEO = akka.http.model.MediaTypes.video$divavs$minusvideo(); + public static final MediaType VIDEO_DIVX = akka.http.model.MediaTypes.video$divdivx(); + public static final MediaType VIDEO_GL = akka.http.model.MediaTypes.video$divgl(); + public static final MediaType VIDEO_MP4 = akka.http.model.MediaTypes.video$divmp4(); + public static final MediaType VIDEO_MPEG = akka.http.model.MediaTypes.video$divmpeg(); + public static final MediaType VIDEO_OGG = akka.http.model.MediaTypes.video$divogg(); + public static final MediaType VIDEO_QUICKTIME = akka.http.model.MediaTypes.video$divquicktime(); + public static final MediaType VIDEO_X_DV = akka.http.model.MediaTypes.video$divx$minusdv(); + public static final MediaType VIDEO_X_FLV = akka.http.model.MediaTypes.video$divx$minusflv(); + public static final MediaType VIDEO_X_MOTION_JPEG = akka.http.model.MediaTypes.video$divx$minusmotion$minusjpeg(); + public static final MediaType VIDEO_X_MS_ASF = akka.http.model.MediaTypes.video$divx$minusms$minusasf(); + public static final MediaType VIDEO_X_MSVIDEO = akka.http.model.MediaTypes.video$divx$minusmsvideo(); + public static final MediaType VIDEO_X_SGI_MOVIE = akka.http.model.MediaTypes.video$divx$minussgi$minusmovie(); + public static final MediaType VIDEO_WEBM = akka.http.model.MediaTypes.video$divwebm(); + + /** + * Register a custom media type. + */ + public static MediaType registerCustom( + String mainType, + String subType, + boolean compressible, + boolean binary, + Iterable fileExtensions, + Map params) { + return akka.http.model.MediaTypes.register(akka.http.model.MediaType.custom(mainType, subType, compressible, binary, Util.convertIterable(fileExtensions), Util.convertMapToScala(params), false)); + } + + /** + * Looks up a media-type with the given main-type and sub-type. + */ + public static Option lookup(String mainType, String subType) { + return Util., MediaType, akka.http.model.MediaType>lookupInRegistry(MediaTypes$.MODULE$, new scala.Tuple2(mainType, subType)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/RemoteAddress.java b/akka-http-core/src/main/java/akka/http/model/japi/RemoteAddress.java new file mode 100644 index 0000000000..ef32317a74 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/RemoteAddress.java @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.japi.Option; + +import java.net.InetAddress; + +public abstract class RemoteAddress { + public abstract boolean isUnknown(); + + public abstract Option getAddress(); + + public static final RemoteAddress UNKNOWN = akka.http.model.RemoteAddress.Unknown$.MODULE$; + public static RemoteAddress create(InetAddress address) { + return akka.http.model.RemoteAddress.apply(address); + } + public static RemoteAddress create(String address) { + return akka.http.model.RemoteAddress.apply(address); + } + public static RemoteAddress create(byte[] address) { + return akka.http.model.RemoteAddress.apply(address); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/ServerBinding.java b/akka-http-core/src/main/java/akka/http/model/japi/ServerBinding.java new file mode 100644 index 0000000000..4a870ad14e --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/ServerBinding.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import org.reactivestreams.api.Producer; + +import java.net.InetSocketAddress; + +/** + * The binding of a server. Allows access to its own address and to the stream + * of incoming connections. + */ +public interface ServerBinding { + /** + * The local address this server is listening on. + */ + InetSocketAddress localAddress(); + + /** + * The stream of incoming connections. The binding is solved and the listening + * socket closed as soon as all consumer of this streams have cancelled their + * subscription. + */ + Producer getConnectionStream(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/StatusCode.java b/akka-http-core/src/main/java/akka/http/model/japi/StatusCode.java new file mode 100644 index 0000000000..d0ef2ec212 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/StatusCode.java @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +/** + * Represents an Http status-code and message. See {@link StatusCodes} for the set of predefined + * status-codes. + */ +public abstract class StatusCode { + /** + * Returns the numeric code of this status code. + */ + public abstract int intValue(); + + /** + * Returns the reason message for this status code. + */ + public abstract String reason(); + + /** + * Returns the default message to be included as the content of an Http response + * with this status-code. + */ + public abstract String defaultMessage(); + + /** + * Returns if the status-code represents success. + */ + public abstract boolean isSuccess(); + + /** + * Returns if the status-code represents failure. + */ + public abstract boolean isFailure(); + + /** + * Returns if a response with this status-code is allowed to be accompanied with + * a non-empty entity. + */ + public abstract boolean allowsEntity(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/StatusCodes.java b/akka-http-core/src/main/java/akka/http/model/japi/StatusCodes.java new file mode 100644 index 0000000000..1333dd233f --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/StatusCodes.java @@ -0,0 +1,114 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.http.model.StatusCodes$; +import akka.japi.Option; + +/** + * Contains the set of predefined status-codes along with static methods to access and create custom + * status-codes. + */ +public final class StatusCodes { + private StatusCodes() {} + + public static final StatusCode CONTINUE = akka.http.model.StatusCodes.Continue(); + public static final StatusCode SWITCHING_PROTOCOLS = akka.http.model.StatusCodes.SwitchingProtocols(); + public static final StatusCode PROCESSING = akka.http.model.StatusCodes.Processing(); + + public static final StatusCode OK = akka.http.model.StatusCodes.OK(); + public static final StatusCode CREATED = akka.http.model.StatusCodes.Created(); + public static final StatusCode ACCEPTED = akka.http.model.StatusCodes.Accepted(); + public static final StatusCode NON_AUTHORITATIVE_INFORMATION = akka.http.model.StatusCodes.NonAuthoritativeInformation(); + public static final StatusCode NO_CONTENT = akka.http.model.StatusCodes.NoContent(); + public static final StatusCode RESET_CONTENT = akka.http.model.StatusCodes.ResetContent(); + public static final StatusCode PARTIAL_CONTENT = akka.http.model.StatusCodes.PartialContent(); + public static final StatusCode MULTI_STATUS = akka.http.model.StatusCodes.MultiStatus(); + public static final StatusCode ALREADY_REPORTED = akka.http.model.StatusCodes.AlreadyReported(); + public static final StatusCode IMUSED = akka.http.model.StatusCodes.IMUsed(); + + public static final StatusCode MULTIPLE_CHOICES = akka.http.model.StatusCodes.MultipleChoices(); + public static final StatusCode MOVED_PERMANENTLY = akka.http.model.StatusCodes.MovedPermanently(); + public static final StatusCode FOUND = akka.http.model.StatusCodes.Found(); + public static final StatusCode SEE_OTHER = akka.http.model.StatusCodes.SeeOther(); + public static final StatusCode NOT_MODIFIED = akka.http.model.StatusCodes.NotModified(); + public static final StatusCode USE_PROXY = akka.http.model.StatusCodes.UseProxy(); + public static final StatusCode TEMPORARY_REDIRECT = akka.http.model.StatusCodes.TemporaryRedirect(); + public static final StatusCode PERMANENT_REDIRECT = akka.http.model.StatusCodes.PermanentRedirect(); + + public static final StatusCode BAD_REQUEST = akka.http.model.StatusCodes.BadRequest(); + public static final StatusCode UNAUTHORIZED = akka.http.model.StatusCodes.Unauthorized(); + public static final StatusCode PAYMENT_REQUIRED = akka.http.model.StatusCodes.PaymentRequired(); + public static final StatusCode FORBIDDEN = akka.http.model.StatusCodes.Forbidden(); + public static final StatusCode NOT_FOUND = akka.http.model.StatusCodes.NotFound(); + public static final StatusCode METHOD_NOT_ALLOWED = akka.http.model.StatusCodes.MethodNotAllowed(); + public static final StatusCode NOT_ACCEPTABLE = akka.http.model.StatusCodes.NotAcceptable(); + public static final StatusCode PROXY_AUTHENTICATION_REQUIRED = akka.http.model.StatusCodes.ProxyAuthenticationRequired(); + public static final StatusCode REQUEST_TIMEOUT = akka.http.model.StatusCodes.RequestTimeout(); + public static final StatusCode CONFLICT = akka.http.model.StatusCodes.Conflict(); + public static final StatusCode GONE = akka.http.model.StatusCodes.Gone(); + public static final StatusCode LENGTH_REQUIRED = akka.http.model.StatusCodes.LengthRequired(); + public static final StatusCode PRECONDITION_FAILED = akka.http.model.StatusCodes.PreconditionFailed(); + public static final StatusCode REQUEST_ENTITY_TOO_LARGE = akka.http.model.StatusCodes.RequestEntityTooLarge(); + public static final StatusCode REQUEST_URI_TOO_LONG = akka.http.model.StatusCodes.RequestUriTooLong(); + public static final StatusCode UNSUPPORTED_MEDIA_TYPE = akka.http.model.StatusCodes.UnsupportedMediaType(); + public static final StatusCode REQUESTED_RANGE_NOT_SATISFIABLE = akka.http.model.StatusCodes.RequestedRangeNotSatisfiable(); + public static final StatusCode EXPECTATION_FAILED = akka.http.model.StatusCodes.ExpectationFailed(); + public static final StatusCode ENHANCE_YOUR_CALM = akka.http.model.StatusCodes.EnhanceYourCalm(); + public static final StatusCode UNPROCESSABLE_ENTITY = akka.http.model.StatusCodes.UnprocessableEntity(); + public static final StatusCode LOCKED = akka.http.model.StatusCodes.Locked(); + public static final StatusCode FAILED_DEPENDENCY = akka.http.model.StatusCodes.FailedDependency(); + public static final StatusCode UNORDERED_COLLECTION = akka.http.model.StatusCodes.UnorderedCollection(); + public static final StatusCode UPGRADE_REQUIRED = akka.http.model.StatusCodes.UpgradeRequired(); + public static final StatusCode PRECONDITION_REQUIRED = akka.http.model.StatusCodes.PreconditionRequired(); + public static final StatusCode TOO_MANY_REQUESTS = akka.http.model.StatusCodes.TooManyRequests(); + public static final StatusCode REQUEST_HEADER_FIELDS_TOO_LARGE = akka.http.model.StatusCodes.RequestHeaderFieldsTooLarge(); + public static final StatusCode RETRY_WITH = akka.http.model.StatusCodes.RetryWith(); + public static final StatusCode BLOCKED_BY_PARENTAL_CONTROLS = akka.http.model.StatusCodes.BlockedByParentalControls(); + public static final StatusCode UNAVAILABLE_FOR_LEGAL_REASONS = akka.http.model.StatusCodes.UnavailableForLegalReasons(); + + public static final StatusCode INTERNAL_SERVER_ERROR = akka.http.model.StatusCodes.InternalServerError(); + public static final StatusCode NOT_IMPLEMENTED = akka.http.model.StatusCodes.NotImplemented(); + public static final StatusCode BAD_GATEWAY = akka.http.model.StatusCodes.BadGateway(); + public static final StatusCode SERVICE_UNAVAILABLE = akka.http.model.StatusCodes.ServiceUnavailable(); + public static final StatusCode GATEWAY_TIMEOUT = akka.http.model.StatusCodes.GatewayTimeout(); + public static final StatusCode HTTPVERSION_NOT_SUPPORTED = akka.http.model.StatusCodes.HTTPVersionNotSupported(); + public static final StatusCode VARIANT_ALSO_NEGOTIATES = akka.http.model.StatusCodes.VariantAlsoNegotiates(); + public static final StatusCode INSUFFICIENT_STORAGE = akka.http.model.StatusCodes.InsufficientStorage(); + public static final StatusCode LOOP_DETECTED = akka.http.model.StatusCodes.LoopDetected(); + public static final StatusCode BANDWIDTH_LIMIT_EXCEEDED = akka.http.model.StatusCodes.BandwidthLimitExceeded(); + public static final StatusCode NOT_EXTENDED = akka.http.model.StatusCodes.NotExtended(); + public static final StatusCode NETWORK_AUTHENTICATION_REQUIRED = akka.http.model.StatusCodes.NetworkAuthenticationRequired(); + public static final StatusCode NETWORK_READ_TIMEOUT = akka.http.model.StatusCodes.NetworkReadTimeout(); + public static final StatusCode NETWORK_CONNECT_TIMEOUT = akka.http.model.StatusCodes.NetworkConnectTimeout(); + + /** + * Registers a custom status code. + */ + public static StatusCode registerCustom(int intValue, String reason, String defaultMessage, boolean isSuccess, boolean allowsEntity) { + return akka.http.model.StatusCodes.registerCustom(intValue, reason, defaultMessage, isSuccess, allowsEntity); + } + + /** + * Registers a custom status code. + */ + public static StatusCode registerCustom(int intValue, String reason, String defaultMessage) { + return akka.http.model.StatusCodes.registerCustom(intValue, reason, defaultMessage); + } + + /** + * Looks up a status-code by numeric code. Throws an exception if no such status-code is found. + */ + public static StatusCode get(int intValue) { + return akka.http.model.StatusCode.int2StatusCode(intValue); + } + + /** + * Looks up a status-code by numeric code and returns Some(code). Returns None otherwise. + */ + public static Option lookup(int intValue) { + return Util.lookupInRegistry(StatusCodes$.MODULE$, intValue); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/TransferEncoding.java b/akka-http-core/src/main/java/akka/http/model/japi/TransferEncoding.java new file mode 100644 index 0000000000..19704855d9 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/TransferEncoding.java @@ -0,0 +1,20 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import java.util.Map; + +public abstract class TransferEncoding { + public abstract String name(); + + public abstract Map getParams(); + + public static TransferEncoding createExtension(String name) { + return new akka.http.model.TransferEncodings.Extension(name, Util.emptyMap); + } + public static TransferEncoding createExtension(String name, Map params) { + return new akka.http.model.TransferEncodings.Extension(name, Util.convertMapToScala(params)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/TransferEncodings.java b/akka-http-core/src/main/java/akka/http/model/japi/TransferEncodings.java new file mode 100644 index 0000000000..7b9d422167 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/TransferEncodings.java @@ -0,0 +1,14 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +public final class TransferEncodings { + private TransferEncodings() {} + + public static final TransferEncoding CHUNKED = akka.http.model.TransferEncodings.chunked$.MODULE$; + public static final TransferEncoding COMPRESS = akka.http.model.TransferEncodings.compress$.MODULE$; + public static final TransferEncoding DEFLATE = akka.http.model.TransferEncodings.deflate$.MODULE$; + public static final TransferEncoding GZIP = akka.http.model.TransferEncodings.gzip$.MODULE$; +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/Uri.java b/akka-http-core/src/main/java/akka/http/model/japi/Uri.java new file mode 100644 index 0000000000..5960aa887d --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/Uri.java @@ -0,0 +1,191 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.japi.Option; +import akka.parboiled2.ParserInput$; + +import java.nio.charset.Charset; +import java.util.Map; + +/** + * Represents a Uri. Use the `withX` methods to create modified copies of a given instance. + */ +public abstract class Uri { + /** + * Returns if this is an absolute Uri. + */ + public abstract boolean isAbsolute(); + + /** + * Returns if this is a relative Uri. + */ + public abstract boolean isRelative(); + + /** + * Returns if this is an empty Uri. + */ + public abstract boolean isEmpty(); + + /** + * Returns the scheme of this Uri. + */ + public abstract String scheme(); + + /** + * Returns the Host of this Uri. + */ + public abstract Host host(); + + /** + * Returns the port of this Uri. + */ + public abstract int port(); + + /** + * Returns the user-info of this Uri. + */ + public abstract String userInfo(); + + /** + * Returns a String representation of the path of this Uri. + */ + public abstract String path(); + + /** + * Returns the the path segments of this Uri as an Iterable. + */ + public abstract Iterable pathSegments(); + + /** + * Returns a String representation of the query of this Uri. + */ + public abstract String queryString(); + + /** + * Looks up a query parameter of this Uri. + */ + public abstract Option parameter(String key); + + /** + * Returns if the query of this Uri contains a parameter with the given key. + */ + public abstract boolean containsParameter(String key); + + /** + * Returns an Iterable of all query parameters of this Uri. + */ + public abstract Iterable parameters(); + + /** + * Returns a key/value map of the query parameters of this Uri. Use + * the `parameters()` method to returns all parameters if keys may occur + * multiple times. + */ + public abstract Map parameterMap(); + + public static interface Parameter { + String key(); + String value(); + } + + /** + * Returns the fragment part of this Uri. + */ + public abstract Option fragment(); + + /** + * Returns a copy of this instance with a new scheme. + */ + public abstract Uri scheme(String scheme); + + /** + * Returns a copy of this instance with a new Host. + */ + public abstract Uri host(Host host); + + /** + * Returns a copy of this instance with a new host. + */ + public abstract Uri host(String host); + + /** + * Returns a copy of this instance with a new port. + */ + public abstract Uri port(int port); + + /** + * Returns a copy of this instance with new user-info. + */ + public abstract Uri userInfo(String userInfo); + + /** + * Returns a copy of this instance with a new path. + */ + public abstract Uri path(String path); + + /** + * Returns a copy of this instance with a path segment added at the end. + */ + public abstract Uri addPathSegment(String segment); + + /** + * Returns a copy of this instance with a new query. + */ + public abstract Uri query(String query); + + /** + * Returns a copy of this instance that is relative. + */ + public abstract Uri toRelative(); + + /** + * Returns a copy of this instance with a query parameter added. + */ + public abstract Uri addParameter(String key, String value); + + /** + * Returns a copy of this instance with a new fragment. + */ + public abstract Uri fragment(String fragment); + + /** + * Returns a copy of this instance with a new optional fragment. + */ + public abstract Uri fragment(Option fragment); + + public static final akka.http.model.Uri.ParsingMode STRICT = akka.http.model.Uri$ParsingMode$Strict$.MODULE$; + public static final akka.http.model.Uri.ParsingMode RELAXED = akka.http.model.Uri$ParsingMode$Relaxed$.MODULE$; + public static final akka.http.model.Uri.ParsingMode RELAXED_WITH_RAW_QUERY = akka.http.model.Uri$ParsingMode$RelaxedWithRawQuery$.MODULE$; + + /** + * Creates a default Uri to be modified using the modification methods. + */ + public static Uri create() { + return Accessors$.MODULE$.Uri(akka.http.model.Uri.Empty$.MODULE$); + } + + /** + * Returns a Uri created by parsing the given string representation. + */ + public static Uri create(String uri) { + return Accessors$.MODULE$.Uri(akka.http.model.Uri.apply(uri)); + } + + /** + * Returns a Uri created by parsing the given string representation and parsing-mode. + */ + public static Uri create(String uri, akka.http.model.Uri.ParsingMode parsingMode) { + return Accessors$.MODULE$.Uri(akka.http.model.Uri.apply(ParserInput$.MODULE$.apply(uri), parsingMode)); + } + + /** + * Returns a Uri created by parsing the given string representation, charset, and parsing-mode. + */ + public static Uri create(String uri, Charset charset, akka.http.model.Uri.ParsingMode parsingMode) { + return Accessors$.MODULE$.Uri(akka.http.model.Uri.apply(ParserInput$.MODULE$.apply(uri), charset, parsingMode)); + } + +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/Util.java b/akka-http-core/src/main/java/akka/http/model/japi/Util.java new file mode 100644 index 0000000000..f8d05a4247 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/Util.java @@ -0,0 +1,86 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.http.model.*; +import akka.http.util.ObjectRegistry; +import akka.japi.Option; +import org.reactivestreams.api.Producer; +import scala.None; +import scala.None$; +import scala.NotImplementedError; +import scala.collection.immutable.Map$; +import scala.collection.immutable.Seq; + +import java.util.Arrays; +import java.util.Map; + +/** + * Contains internal helper methods. + */ +public abstract class Util { + @SuppressWarnings("unchecked") // no support for covariance of option in Java + public static Option convertOption(scala.Option o) { + return (Option)(Option) akka.japi.Option.fromScalaOption(o); + } + @SuppressWarnings("unchecked") // no support for covariance of Producer in Java + public static Producer convertProducer(Producer p) { + return (Producer)(Producer) p; + } + @SuppressWarnings("unchecked") + public static Producer upcastProducer(Producer p) { + return (Producer)(Producer) p; + } + @SuppressWarnings("unchecked") + public static scala.collection.immutable.Map convertMapToScala(Map map) { + return Map$.MODULE$.apply(scala.collection.JavaConverters.asScalaMapConverter(map).asScala().toSeq()); + } + @SuppressWarnings("unchecked") // contains an upcast + public static scala.Option convertOptionToScala(Option o) { + return ((Option) o).asScala(); + } + + public static final scala.collection.immutable.Map emptyMap = + Map$.MODULE$.empty(); + + public static final None$ noneValue = None$.MODULE$; + @SuppressWarnings("unchecked") + public static scala.Option scalaNone() { + return (scala.Option) noneValue; + } + + @SuppressWarnings("unchecked") + public static Seq convertIterable(Iterable els) { + return scala.collection.JavaConverters.asScalaIterableConverter((Iterable)els).asScala().toVector(); + } + @SuppressWarnings("unchecked") + public static Seq convertArray(T[] els) { + return Util.convertIterable(Arrays.asList(els)); + } + + public static akka.http.model.Uri convertUriToScala(Uri uri) { + return ((JavaUri) uri).uri(); + } + + public static akka.japi.Option lookupInRegistry(ObjectRegistry registry, int key) { + return Util.convertOption(registry.getForKey(key)); + } + public static akka.japi.Option lookupInRegistry(ObjectRegistry registry, String key) { + return Util.lookupInRegistry(registry, key); + } + public static akka.japi.Option lookupInRegistry(ObjectRegistry registry, K key) { + return Util.convertOption(registry.getForKey(key)); + } + + /** + * Temporary replacement for akka.japi.Option.getOrElse until it gets released there. + * + * FIXME: remove in favor of a proper japi.Option.getOrElse + */ + public static B getOrElse(Option option, B defaultValue) { + if (option.isDefined()) return option.get(); + else return defaultValue; + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Accept.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Accept.java new file mode 100644 index 0000000000..7f2b6b73c8 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Accept.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.MediaRange; + +/** + * Model for the `Accept` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.3.2 + */ +public abstract class Accept extends akka.http.model.HttpHeader { + public abstract Iterable getMediaRanges(); + + public static Accept create(MediaRange... mediaRanges) { + return new akka.http.model.headers.Accept(akka.http.model.japi.Util.convertArray(mediaRanges)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptCharset.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptCharset.java new file mode 100644 index 0000000000..dc89ed15e8 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptCharset.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.HttpCharsetRange; + +/** + * Model for the `Accept-Charset` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.3.3 + */ +public abstract class AcceptCharset extends akka.http.model.HttpHeader { + public abstract Iterable getCharsetRanges(); + + public static AcceptCharset create(HttpCharsetRange... charsetRanges) { + return new akka.http.model.headers.Accept$minusCharset(akka.http.model.japi.Util.convertArray(charsetRanges)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptEncoding.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptEncoding.java new file mode 100644 index 0000000000..d4ee31597b --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptEncoding.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Accept-Encoding` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.3.4 + */ +public abstract class AcceptEncoding extends akka.http.model.HttpHeader { + public abstract Iterable getEncodings(); + + public static AcceptEncoding create(HttpEncodingRange... encodings) { + return new akka.http.model.headers.Accept$minusEncoding(akka.http.model.japi.Util.convertArray(encodings)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptLanguage.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptLanguage.java new file mode 100644 index 0000000000..c0e5d2fd77 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptLanguage.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Accept-Language` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.3.5 + */ +public abstract class AcceptLanguage extends akka.http.model.HttpHeader { + public abstract Iterable getLanguages(); + + public static AcceptLanguage create(LanguageRange... languages) { + return new akka.http.model.headers.Accept$minusLanguage(akka.http.model.japi.Util.convertArray(languages)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptRanges.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptRanges.java new file mode 100644 index 0000000000..5d5afba122 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AcceptRanges.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Accept-Ranges` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-26#section-2.3 + */ +public abstract class AcceptRanges extends akka.http.model.HttpHeader { + public abstract Iterable getRangeUnits(); + + public static AcceptRanges create(RangeUnit... rangeUnits) { + return new akka.http.model.headers.Accept$minusRanges(akka.http.model.japi.Util.convertArray(rangeUnits)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowCredentials.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowCredentials.java new file mode 100644 index 0000000000..7cdf049a7b --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowCredentials.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Access-Control-Allow-Credentials` header. + * Specification: http://www.w3.org/TR/cors/#access-control-allow-credentials-response-header + */ +public abstract class AccessControlAllowCredentials extends akka.http.model.HttpHeader { + public abstract boolean allow(); + + public static AccessControlAllowCredentials create(boolean allow) { + return new akka.http.model.headers.Access$minusControl$minusAllow$minusCredentials(allow); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowHeaders.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowHeaders.java new file mode 100644 index 0000000000..9fce96ffef --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowHeaders.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Access-Control-Allow-Headers` header. + * Specification: http://www.w3.org/TR/cors/#access-control-allow-headers-response-header + */ +public abstract class AccessControlAllowHeaders extends akka.http.model.HttpHeader { + public abstract Iterable getHeaders(); + + public static AccessControlAllowHeaders create(String... headers) { + return new akka.http.model.headers.Access$minusControl$minusAllow$minusHeaders(akka.http.model.japi.Util.convertArray(headers)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowMethods.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowMethods.java new file mode 100644 index 0000000000..e357d4c888 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowMethods.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.HttpMethod; + +/** + * Model for the `Access-Control-Allow-Methods` header. + * Specification: http://www.w3.org/TR/cors/#access-control-allow-methods-response-header + */ +public abstract class AccessControlAllowMethods extends akka.http.model.HttpHeader { + public abstract Iterable getMethods(); + + public static AccessControlAllowMethods create(HttpMethod... methods) { + return new akka.http.model.headers.Access$minusControl$minusAllow$minusMethods(akka.http.model.japi.Util.convertArray(methods)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowOrigin.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowOrigin.java new file mode 100644 index 0000000000..7063dd4509 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlAllowOrigin.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Access-Control-Allow-Origin` header. + * Specification: http://www.w3.org/TR/cors/#access-control-allow-origin-response-header + */ +public abstract class AccessControlAllowOrigin extends akka.http.model.HttpHeader { + public abstract HttpOriginRange range(); + + public static AccessControlAllowOrigin create(HttpOriginRange range) { + return new akka.http.model.headers.Access$minusControl$minusAllow$minusOrigin(((akka.http.model.headers.HttpOriginRange) range)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlExposeHeaders.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlExposeHeaders.java new file mode 100644 index 0000000000..c4e5fbc98c --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlExposeHeaders.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Access-Control-Expose-Headers` header. + * Specification: http://www.w3.org/TR/cors/#access-control-expose-headers-response-header + */ +public abstract class AccessControlExposeHeaders extends akka.http.model.HttpHeader { + public abstract Iterable getHeaders(); + + public static AccessControlExposeHeaders create(String... headers) { + return new akka.http.model.headers.Access$minusControl$minusExpose$minusHeaders(akka.http.model.japi.Util.convertArray(headers)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlMaxAge.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlMaxAge.java new file mode 100644 index 0000000000..ec06988a1f --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlMaxAge.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Access-Control-Max-Age` header. + * Specification: http://www.w3.org/TR/cors/#access-control-max-age-response-header + */ +public abstract class AccessControlMaxAge extends akka.http.model.HttpHeader { + public abstract long deltaSeconds(); + + public static AccessControlMaxAge create(long deltaSeconds) { + return new akka.http.model.headers.Access$minusControl$minusMax$minusAge(deltaSeconds); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlRequestHeaders.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlRequestHeaders.java new file mode 100644 index 0000000000..6d997f9928 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlRequestHeaders.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Access-Control-Request-Headers` header. + * Specification: http://www.w3.org/TR/cors/#access-control-request-headers-request-header + */ +public abstract class AccessControlRequestHeaders extends akka.http.model.HttpHeader { + public abstract Iterable getHeaders(); + + public static AccessControlRequestHeaders create(String... headers) { + return new akka.http.model.headers.Access$minusControl$minusRequest$minusHeaders(akka.http.model.japi.Util.convertArray(headers)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlRequestMethod.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlRequestMethod.java new file mode 100644 index 0000000000..bc259e0799 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/AccessControlRequestMethod.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.HttpMethod; + +/** + * Model for the `Access-Control-Request-Method` header. + * Specification: http://www.w3.org/TR/cors/#access-control-request-method-request-header + */ +public abstract class AccessControlRequestMethod extends akka.http.model.HttpHeader { + public abstract HttpMethod method(); + + public static AccessControlRequestMethod create(HttpMethod method) { + return new akka.http.model.headers.Access$minusControl$minusRequest$minusMethod(((akka.http.model.HttpMethod) method)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Allow.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Allow.java new file mode 100644 index 0000000000..0685da1f26 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Allow.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.HttpMethod; + +/** + * Model for the `Allow` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-7.4.1 + */ +public abstract class Allow extends akka.http.model.HttpHeader { + public abstract Iterable getMethods(); + + public static Allow create(HttpMethod... methods) { + return new akka.http.model.headers.Allow(akka.http.model.japi.Util.convertArray(methods)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Authorization.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Authorization.java new file mode 100644 index 0000000000..6a22f24574 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Authorization.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Authorization` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p7-auth-26#section-4.2 + */ +public abstract class Authorization extends akka.http.model.HttpHeader { + public abstract HttpCredentials credentials(); + + public static Authorization create(HttpCredentials credentials) { + return new akka.http.model.headers.Authorization(((akka.http.model.headers.HttpCredentials) credentials)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/BasicHttpCredentials.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/BasicHttpCredentials.java new file mode 100644 index 0000000000..d6f80af49f --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/BasicHttpCredentials.java @@ -0,0 +1,10 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public abstract class BasicHttpCredentials extends akka.http.model.headers.HttpCredentials { + public abstract String username(); + public abstract String password(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ByteRange.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ByteRange.java new file mode 100644 index 0000000000..7fb6854998 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ByteRange.java @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.headers.ByteRange$; +import akka.japi.Option; + +public abstract class ByteRange { + public abstract boolean isSlice(); + public abstract boolean isFromOffset(); + public abstract boolean isSuffix(); + + public abstract Option getSliceFirst(); + public abstract Option getSliceLast(); + public abstract Option getOffset(); + public abstract Option getSuffixLength(); + + public static ByteRange createSlice(long first, long last) { + return ByteRange$.MODULE$.apply(first, last); + } + public static ByteRange createFromOffset(long offset) { + return ByteRange$.MODULE$.fromOffset(offset); + } + public static ByteRange createSuffix(long length) { + return ByteRange$.MODULE$.suffix(length); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheControl.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheControl.java new file mode 100644 index 0000000000..d035651968 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheControl.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Cache-Control` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-26#section-5.2 + */ +public abstract class CacheControl extends akka.http.model.HttpHeader { + public abstract Iterable getDirectives(); + + public static CacheControl create(CacheDirective... directives) { + return new akka.http.model.headers.Cache$minusControl(akka.http.model.japi.Util.convertArray(directives)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheDirective.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheDirective.java new file mode 100644 index 0000000000..397691f545 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheDirective.java @@ -0,0 +1,9 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public interface CacheDirective { + String value(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheDirectives.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheDirectives.java new file mode 100644 index 0000000000..f4d1e6ba59 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheDirectives.java @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public final class CacheDirectives { + private CacheDirectives() {} + + public static CacheDirective MAX_AGE(long deltaSeconds) { + return new akka.http.model.headers.CacheDirectives.max$minusage(deltaSeconds); + } + public static CacheDirective MAX_STALE() { + return new akka.http.model.headers.CacheDirectives.max$minusstale(akka.japi.Option.none().asScala()); + } + public static CacheDirective MAX_STALE(long deltaSeconds) { + return new akka.http.model.headers.CacheDirectives.max$minusstale(akka.japi.Option.some((Object) deltaSeconds).asScala()); + } + public static CacheDirective MIN_FRESH(long deltaSeconds) { + return new akka.http.model.headers.CacheDirectives.min$minusfresh(deltaSeconds); + } + + public static final CacheDirective NO_CACHE = akka.http.model.headers.CacheDirectives.no$minuscache$.MODULE$; + public static final CacheDirective NO_STORE = akka.http.model.headers.CacheDirectives.no$minusstore$.MODULE$; + public static final CacheDirective NO_TRANSFORM = akka.http.model.headers.CacheDirectives.no$minustransform$.MODULE$; + public static final CacheDirective ONLY_IF_CACHED = akka.http.model.headers.CacheDirectives.only$minusif$minuscached$.MODULE$; + public static final CacheDirective MUST_REVALIDATE = akka.http.model.headers.CacheDirectives.must$minusrevalidate$.MODULE$; + + public static CacheDirective NO_CACHE(String... fieldNames) { + return akka.http.model.headers.CacheDirectives.no$minuscache$.MODULE$.apply(fieldNames); + } + public static final CacheDirective PUBLIC = akka.http.model.headers.CacheDirectives.public$.MODULE$; + public static CacheDirective PRIVATE(String... fieldNames) { + return akka.http.model.headers.CacheDirectives.private$.MODULE$.apply(fieldNames); + } + public static final CacheDirective PROXY_REVALIDATE = akka.http.model.headers.CacheDirectives.proxy$minusrevalidate$.MODULE$; + public static CacheDirective S_MAXAGE(long deltaSeconds) { + return new akka.http.model.headers.CacheDirectives.s$minusmaxage(deltaSeconds); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentDisposition.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentDisposition.java new file mode 100644 index 0000000000..545210fff0 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentDisposition.java @@ -0,0 +1,18 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Content-Disposition` header. + * Specification: http://tools.ietf.org/html/rfc6266 + */ +public abstract class ContentDisposition extends akka.http.model.HttpHeader { + public abstract ContentDispositionType dispositionType(); + public abstract java.util.Map getParams(); + + public static ContentDisposition create(ContentDispositionType dispositionType, java.util.Map params) { + return new akka.http.model.headers.Content$minusDisposition(((akka.http.model.headers.ContentDispositionType) dispositionType), akka.http.model.japi.Util.convertMapToScala(params)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentDispositionType.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentDispositionType.java new file mode 100644 index 0000000000..fbb03e5191 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentDispositionType.java @@ -0,0 +1,9 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public interface ContentDispositionType { + String name(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentDispositionTypes.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentDispositionTypes.java new file mode 100644 index 0000000000..2d892e51eb --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentDispositionTypes.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public final class ContentDispositionTypes { + private ContentDispositionTypes() {} + + public static final ContentDispositionType INLINE = akka.http.model.headers.ContentDispositionTypes.inline$.MODULE$; + public static final ContentDispositionType ATTACHMENT = akka.http.model.headers.ContentDispositionTypes.attachment$.MODULE$; + public static final ContentDispositionType FORM_DATA = akka.http.model.headers.ContentDispositionTypes.form$minusdata$.MODULE$; + + public static ContentDispositionType Ext(String name) { + return new akka.http.model.headers.ContentDispositionTypes.Ext(name); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentEncoding.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentEncoding.java new file mode 100644 index 0000000000..6bbaee01c0 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentEncoding.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Content-Encoding` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-3.1.2.2 + */ +public abstract class ContentEncoding extends akka.http.model.HttpHeader { + public abstract Iterable getEncodings(); + + public static ContentEncoding create(HttpEncoding... encodings) { + return new akka.http.model.headers.Content$minusEncoding(akka.http.model.japi.Util.convertArray(encodings)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentRange.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentRange.java new file mode 100644 index 0000000000..ee58f56527 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentRange.java @@ -0,0 +1,18 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Content-Range` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-26#section-4.2 + */ +public abstract class ContentRange extends akka.http.model.HttpHeader { + public abstract RangeUnit rangeUnit(); + public abstract akka.http.model.japi.ContentRange contentRange(); + + public static ContentRange create(RangeUnit rangeUnit, akka.http.model.japi.ContentRange contentRange) { + return new akka.http.model.headers.Content$minusRange(((akka.http.model.headers.RangeUnit) rangeUnit), ((akka.http.model.ContentRange) contentRange)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentType.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentType.java new file mode 100644 index 0000000000..ec52c0cdda --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ContentType.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Content-Type` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-3.1.1.5 + */ +public abstract class ContentType extends akka.http.model.HttpHeader { + public abstract akka.http.model.japi.ContentType contentType(); + + public static ContentType create(akka.http.model.japi.ContentType contentType) { + return new akka.http.model.headers.Content$minusType(((akka.http.model.ContentType) contentType)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Cookie.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Cookie.java new file mode 100644 index 0000000000..90f249b365 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Cookie.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Cookie` header. + * Specification: https://tools.ietf.org/html/rfc6265#section-4.2 + */ +public abstract class Cookie extends akka.http.model.HttpHeader { + public abstract Iterable getCookies(); + + public static Cookie create(HttpCookie... cookies) { + return new akka.http.model.headers.Cookie(akka.http.model.japi.Util.convertArray(cookies)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Date.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Date.java new file mode 100644 index 0000000000..8930a25325 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Date.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.DateTime; + +/** + * Model for the `Date` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-7.1.1.2 + */ +public abstract class Date extends akka.http.model.HttpHeader { + public abstract DateTime date(); + + public static Date create(DateTime date) { + return new akka.http.model.headers.Date(((akka.http.util.DateTime) date)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ETag.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ETag.java new file mode 100644 index 0000000000..f6f95cd9fe --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ETag.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `ETag` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-2.3 + */ +public abstract class ETag extends akka.http.model.HttpHeader { + public abstract EntityTag etag(); + + public static ETag create(EntityTag etag) { + return new akka.http.model.headers.ETag(((akka.http.model.headers.EntityTag) etag)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/EntityTag.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/EntityTag.java new file mode 100644 index 0000000000..743dd68f79 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/EntityTag.java @@ -0,0 +1,20 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public abstract class EntityTag { + public abstract String tag(); + public abstract boolean weak(); + + public static EntityTag create(String tag, boolean weak) { + return new akka.http.model.headers.EntityTag(tag, weak); + } + public static boolean matchesRange(EntityTag eTag, EntityTagRange range, boolean weak) { + return akka.http.model.headers.EntityTag.matchesRange(eTag, range, weak); + } + public static boolean matches(EntityTag eTag, EntityTag other, boolean weak) { + return akka.http.model.headers.EntityTag.matches(eTag, other, weak); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/EntityTagRange.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/EntityTagRange.java new file mode 100644 index 0000000000..f3e798fbde --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/EntityTagRange.java @@ -0,0 +1,14 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.Util; + +public abstract class EntityTagRange { + public static EntityTagRange create(EntityTag... tags) { + return akka.http.model.headers.EntityTagRange.apply(Util.convertArray(tags)); + } + public static final EntityTagRange ALL = akka.http.model.headers.EntityTagRange.$times$.MODULE$; +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Host.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Host.java new file mode 100644 index 0000000000..b032fd11ea --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Host.java @@ -0,0 +1,10 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public abstract class Host extends akka.http.model.HttpHeader { + public abstract akka.http.model.japi.Host host(); + public abstract int port(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpChallenge.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpChallenge.java new file mode 100644 index 0000000000..01083e8392 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpChallenge.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.headers.HttpChallenge$; +import akka.http.model.japi.Util; + +import java.util.Map; + +public abstract class HttpChallenge { + public abstract String scheme(); + public abstract String realm(); + + public abstract Map getParams(); + + public static HttpChallenge create(String scheme, String realm) { + return new akka.http.model.headers.HttpChallenge(scheme, realm, Util.emptyMap); + } + public static HttpChallenge create(String scheme, String realm, Map params) { + return new akka.http.model.headers.HttpChallenge(scheme, realm, Util.convertMapToScala(params)); + } +} \ No newline at end of file diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpCookie.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpCookie.java new file mode 100644 index 0000000000..697ec9f639 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpCookie.java @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.DateTime; +import akka.http.model.japi.Util; +import akka.japi.Option; + +public abstract class HttpCookie { + public abstract String name(); + public abstract String content(); + + public abstract Option getExpires(); + public abstract Option getMaxAge(); + public abstract Option getDomain(); + public abstract Option getPath(); + public abstract boolean secure(); + public abstract boolean httpOnly(); + public abstract Option getExtension(); + + public static HttpCookie create(String name, String content) { + return new akka.http.model.headers.HttpCookie( + name, content, + Util.scalaNone(), Util.scalaNone(), Util.scalaNone(), Util.scalaNone(), + false, false, + Util.scalaNone()); + } + @SuppressWarnings("unchecked") + public static HttpCookie create( + String name, + String content, + Option expires, + Option maxAge, + Option domain, + Option path, + boolean secure, + boolean httpOnly, + Option extension) { + return new akka.http.model.headers.HttpCookie( + name, content, + Util.convertOptionToScala(expires), + ((Option) (Option) maxAge).asScala(), + domain.asScala(), + path.asScala(), + secure, + httpOnly, + extension.asScala()); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpCredentials.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpCredentials.java new file mode 100644 index 0000000000..98bec71f7b --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpCredentials.java @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.Util; + +import java.util.Map; + +public abstract class HttpCredentials { + public abstract String scheme(); + public abstract String token(); + + public abstract Map getParams(); + + public static HttpCredentials create(String scheme, String token) { + return new akka.http.model.headers.GenericHttpCredentials(scheme, token, Util.emptyMap); + } + public static HttpCredentials create(String scheme, String token, Map params) { + return new akka.http.model.headers.GenericHttpCredentials(scheme, token, Util.convertMapToScala(params)); + } + public static BasicHttpCredentials createBasicHttpCredential(String username, String password) { + return new akka.http.model.headers.BasicHttpCredentials(username, password); + } + public static OAuth2BearerToken createOAuth2BearerToken(String token) { + return new akka.http.model.headers.OAuth2BearerToken(token); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpEncoding.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpEncoding.java new file mode 100644 index 0000000000..09e197a266 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpEncoding.java @@ -0,0 +1,9 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public abstract class HttpEncoding { + public abstract String value(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpEncodingRange.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpEncodingRange.java new file mode 100644 index 0000000000..7268901671 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpEncodingRange.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.headers.HttpEncodingRange$; + +public abstract class HttpEncodingRange { + public abstract float qValue(); + public abstract boolean matches(HttpEncoding encoding); + + public abstract HttpEncodingRange withQValue(float qValue); + + public static final HttpEncodingRange ALL = akka.http.model.headers.HttpEncodingRange.$times$.MODULE$; + public static HttpEncodingRange create(HttpEncoding encoding) { + return HttpEncodingRange$.MODULE$.apply((akka.http.model.headers.HttpEncoding) encoding); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpOrigin.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpOrigin.java new file mode 100644 index 0000000000..973d0865b9 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpOrigin.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.headers.HttpOrigin$; + +public abstract class HttpOrigin { + public abstract String scheme(); + public abstract Host host(); + + public static HttpOrigin create(String scheme, Host host) { + return new akka.http.model.headers.HttpOrigin(scheme, (akka.http.model.headers.Host) host); + } + public static HttpOrigin parse(String originString) { + return HttpOrigin$.MODULE$.apply(originString); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpOriginRange.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpOriginRange.java new file mode 100644 index 0000000000..9fc0347191 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/HttpOriginRange.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.headers.HttpOriginRange$; +import akka.http.model.japi.Util; + +public abstract class HttpOriginRange { + public abstract boolean matches(HttpOrigin origin); + + public static final HttpOriginRange ALL = akka.http.model.headers.HttpOriginRange.$times$.MODULE$; + public static HttpOriginRange create(HttpOrigin... origins) { + return HttpOriginRange$.MODULE$.apply(Util.convertArray(origins)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/IfMatch.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/IfMatch.java new file mode 100644 index 0000000000..e4a1b745ff --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/IfMatch.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `If-Match` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-3.1 + */ +public abstract class IfMatch extends akka.http.model.HttpHeader { + public abstract EntityTagRange m(); + + public static IfMatch create(EntityTagRange m) { + return new akka.http.model.headers.If$minusMatch(((akka.http.model.headers.EntityTagRange) m)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/IfModifiedSince.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/IfModifiedSince.java new file mode 100644 index 0000000000..e9db6519e9 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/IfModifiedSince.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.DateTime; + +/** + * Model for the `If-Modified-Since` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-3.3 + */ +public abstract class IfModifiedSince extends akka.http.model.HttpHeader { + public abstract DateTime date(); + + public static IfModifiedSince create(DateTime date) { + return new akka.http.model.headers.If$minusModified$minusSince(((akka.http.util.DateTime) date)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/IfNoneMatch.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/IfNoneMatch.java new file mode 100644 index 0000000000..365b8704ae --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/IfNoneMatch.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `If-None-Match` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-3.2 + */ +public abstract class IfNoneMatch extends akka.http.model.HttpHeader { + public abstract EntityTagRange m(); + + public static IfNoneMatch create(EntityTagRange m) { + return new akka.http.model.headers.If$minusNone$minusMatch(((akka.http.model.headers.EntityTagRange) m)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/IfUnmodifiedSince.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/IfUnmodifiedSince.java new file mode 100644 index 0000000000..28a350c15b --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/IfUnmodifiedSince.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.DateTime; + +/** + * Model for the `If-Unmodified-Since` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-3.4 + */ +public abstract class IfUnmodifiedSince extends akka.http.model.HttpHeader { + public abstract DateTime date(); + + public static IfUnmodifiedSince create(DateTime date) { + return new akka.http.model.headers.If$minusUnmodified$minusSince(((akka.http.util.DateTime) date)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Language.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Language.java new file mode 100644 index 0000000000..7cf51a4815 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Language.java @@ -0,0 +1,14 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.headers.Language$; +import akka.http.model.japi.Util; + +public abstract class Language implements LanguageRange { + public static Language create(String primaryTag, String... subTags) { + return Language$.MODULE$.apply(primaryTag, Util.convertArray(subTags)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/LanguageRange.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/LanguageRange.java new file mode 100644 index 0000000000..cb472a9933 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/LanguageRange.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public interface LanguageRange { + public abstract String primaryTag(); + public abstract float qValue(); + + public abstract Iterable getSubTags(); + public abstract boolean matches(Language language); + + public abstract LanguageRange withQValue(float qValue); + + public static final LanguageRange ALL = akka.http.model.headers.LanguageRange.$times$.MODULE$; +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/LastModified.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/LastModified.java new file mode 100644 index 0000000000..b1ad03be80 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/LastModified.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.DateTime; + +/** + * Model for the `Last-Modified` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-2.2 + */ +public abstract class LastModified extends akka.http.model.HttpHeader { + public abstract DateTime date(); + + public static LastModified create(DateTime date) { + return new akka.http.model.headers.Last$minusModified(((akka.http.util.DateTime) date)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Link.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Link.java new file mode 100644 index 0000000000..eb865e7da9 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Link.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Link` header. + * Specification: http://tools.ietf.org/html/rfc5988#section-5 + */ +public abstract class Link extends akka.http.model.HttpHeader { + public abstract Iterable getValues(); + + public static Link create(LinkValue... values) { + return new akka.http.model.headers.Link(akka.http.model.japi.Util.convertArray(values)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/LinkParam.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/LinkParam.java new file mode 100644 index 0000000000..72ee4212b0 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/LinkParam.java @@ -0,0 +1,14 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.MediaType; +import akka.http.model.japi.Uri; +import akka.http.model.japi.Util; + +public abstract class LinkParam { + public abstract String key(); + public abstract Object value(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/LinkParams.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/LinkParams.java new file mode 100644 index 0000000000..e828a50f44 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/LinkParams.java @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.MediaType; +import akka.http.model.japi.Uri; +import akka.http.model.japi.Util; + +public final class LinkParams { + private LinkParams() {} + + public static final LinkParam next = akka.http.model.headers.LinkParams.next(); + public static final LinkParam prev = akka.http.model.headers.LinkParams.prev(); + public static final LinkParam first = akka.http.model.headers.LinkParams.first(); + public static final LinkParam last = akka.http.model.headers.LinkParams.last(); + + public static LinkParam rel(String value) { + return new akka.http.model.headers.LinkParams.rel(value); + } + public static LinkParam anchor(Uri uri) { + return new akka.http.model.headers.LinkParams.anchor(Util.convertUriToScala(uri)); + } + public static LinkParam rev(String value) { + return new akka.http.model.headers.LinkParams.rev(value); + } + public static LinkParam hreflang(Language language) { + return new akka.http.model.headers.LinkParams.hreflang((akka.http.model.headers.Language) language); + } + public static LinkParam media(String desc) { + return new akka.http.model.headers.LinkParams.media(desc); + } + public static LinkParam title(String title) { + return new akka.http.model.headers.LinkParams.title(title); + } + public static LinkParam title_All(String title) { + return new akka.http.model.headers.LinkParams.title$times(title); + } + public static LinkParam type(MediaType type) { + return new akka.http.model.headers.LinkParams.type((akka.http.model.MediaType) type); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/LinkValue.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/LinkValue.java new file mode 100644 index 0000000000..f4d9107dd4 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/LinkValue.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.Uri; +import akka.http.model.japi.Util; + +public abstract class LinkValue { + public abstract Uri getUri(); + public abstract Iterable getParams(); + + public static LinkValue create(Uri uri, LinkParam... params) { + return new akka.http.model.headers.LinkValue( + Util.convertUriToScala(uri), + Util.convertArray(params)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Location.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Location.java new file mode 100644 index 0000000000..70e0130de2 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Location.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +import akka.http.model.japi.Uri; + +/** + * Model for the `Location` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-7.1.2 + */ +public abstract class Location extends akka.http.model.HttpHeader { + public abstract Uri getUri(); + + public static Location create(Uri uri) { + return new akka.http.model.headers.Location(akka.http.model.japi.Util.convertUriToScala(uri)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/OAuth2BearerToken.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/OAuth2BearerToken.java new file mode 100644 index 0000000000..c9c306c549 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/OAuth2BearerToken.java @@ -0,0 +1,9 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public abstract class OAuth2BearerToken extends akka.http.model.headers.HttpCredentials { + public abstract String token(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Origin.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Origin.java new file mode 100644 index 0000000000..d9c5c0f36c --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Origin.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Origin` header. + * Specification: http://tools.ietf.org/html/rfc6454#section-7 + */ +public abstract class Origin extends akka.http.model.HttpHeader { + public abstract Iterable getOrigins(); + + public static Origin create(HttpOrigin... origins) { + return new akka.http.model.headers.Origin(akka.http.model.japi.Util.convertArray(origins)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ProductVersion.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ProductVersion.java new file mode 100644 index 0000000000..3b51382d79 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ProductVersion.java @@ -0,0 +1,18 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public abstract class ProductVersion { + public abstract String product(); + public abstract String version(); + public abstract String comment(); + + public static ProductVersion create(String product, String version, String comment) { + return new akka.http.model.headers.ProductVersion(product, version, comment); + } + public static ProductVersion create(String product, String version) { + return create(product, version, ""); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ProxyAuthenticate.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ProxyAuthenticate.java new file mode 100644 index 0000000000..d11c3b99d0 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ProxyAuthenticate.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Proxy-Authenticate` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p7-auth-26#section-4.3 + */ +public abstract class ProxyAuthenticate extends akka.http.model.HttpHeader { + public abstract Iterable getChallenges(); + + public static ProxyAuthenticate create(HttpChallenge... challenges) { + return new akka.http.model.headers.Proxy$minusAuthenticate(akka.http.model.japi.Util.convertArray(challenges)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/ProxyAuthorization.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/ProxyAuthorization.java new file mode 100644 index 0000000000..251bfc907d --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/ProxyAuthorization.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Proxy-Authorization` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p7-auth-26#section-4.4 + */ +public abstract class ProxyAuthorization extends akka.http.model.HttpHeader { + public abstract HttpCredentials credentials(); + + public static ProxyAuthorization create(HttpCredentials credentials) { + return new akka.http.model.headers.Proxy$minusAuthorization(((akka.http.model.headers.HttpCredentials) credentials)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Range.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Range.java new file mode 100644 index 0000000000..fd34908057 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Range.java @@ -0,0 +1,18 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Range` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-26#section-3.1 + */ +public abstract class Range extends akka.http.model.HttpHeader { + public abstract RangeUnit rangeUnit(); + public abstract Iterable getRanges(); + + public static Range create(RangeUnit rangeUnit, ByteRange... ranges) { + return new akka.http.model.headers.Range(((akka.http.model.headers.RangeUnit) rangeUnit), akka.http.model.japi.Util.convertArray(ranges)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/RangeUnit.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/RangeUnit.java new file mode 100644 index 0000000000..433815750b --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/RangeUnit.java @@ -0,0 +1,13 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public abstract class RangeUnit { + public abstract String name(); + + public static RangeUnit create(String name) { + return new akka.http.model.headers.RangeUnits.Other(name); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/RangeUnits.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/RangeUnits.java new file mode 100644 index 0000000000..95e04325dc --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/RangeUnits.java @@ -0,0 +1,11 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public final class RangeUnits { + private RangeUnits() {} + + public static final RangeUnit BYTES = akka.http.model.headers.RangeUnits.Bytes$.MODULE$; +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/RawHeader.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/RawHeader.java new file mode 100644 index 0000000000..debb8c1220 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/RawHeader.java @@ -0,0 +1,10 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +public abstract class RawHeader extends akka.http.model.HttpHeader { + public abstract String name(); + public abstract String value(); +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/RawRequestURI.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/RawRequestURI.java new file mode 100644 index 0000000000..0fd3f02518 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/RawRequestURI.java @@ -0,0 +1,18 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Raw-Request-URI` header. + * Custom header we use for transporting the raw request URI either to the application (server-side) + * or to the request rendering stage (client-side). + */ +public abstract class RawRequestURI extends akka.http.model.HttpHeader { + public abstract String uri(); + + public static RawRequestURI create(String uri) { + return new akka.http.model.headers.Raw$minusRequest$minusURI(uri); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/RemoteAddress.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/RemoteAddress.java new file mode 100644 index 0000000000..7ee0f87482 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/RemoteAddress.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Remote-Address` header. + * Custom header we use for optionally transporting the peer's IP in an HTTP header. + */ +public abstract class RemoteAddress extends akka.http.model.HttpHeader { + public abstract akka.http.model.japi.RemoteAddress address(); + + public static RemoteAddress create(akka.http.model.japi.RemoteAddress address) { + return new akka.http.model.headers.Remote$minusAddress(((akka.http.model.RemoteAddress) address)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/Server.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/Server.java new file mode 100644 index 0000000000..5b646a5b26 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/Server.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Server` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-7.4.2 + */ +public abstract class Server extends akka.http.model.HttpHeader { + public abstract Iterable getProducts(); + + public static Server create(ProductVersion... products) { + return new akka.http.model.headers.Server(akka.http.model.japi.Util.convertArray(products)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/SetCookie.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/SetCookie.java new file mode 100644 index 0000000000..2bfc3a7d1d --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/SetCookie.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Set-Cookie` header. + * Specification: https://tools.ietf.org/html/rfc6265 + */ +public abstract class SetCookie extends akka.http.model.HttpHeader { + public abstract HttpCookie cookie(); + + public static SetCookie create(HttpCookie cookie) { + return new akka.http.model.headers.Set$minusCookie(((akka.http.model.headers.HttpCookie) cookie)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/TransferEncoding.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/TransferEncoding.java new file mode 100644 index 0000000000..6c6086dc96 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/TransferEncoding.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `Transfer-Encoding` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-26#section-3.3.1 + */ +public abstract class TransferEncoding extends akka.http.model.HttpHeader { + public abstract Iterable getEncodings(); + + public static TransferEncoding create(akka.http.model.japi.TransferEncoding... encodings) { + return new akka.http.model.headers.Transfer$minusEncoding(akka.http.model.japi.Util.convertArray(encodings)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/UserAgent.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/UserAgent.java new file mode 100644 index 0000000000..3e9cfb45ed --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/UserAgent.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `User-Agent` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.5.3 + */ +public abstract class UserAgent extends akka.http.model.HttpHeader { + public abstract Iterable getProducts(); + + public static UserAgent create(ProductVersion... products) { + return new akka.http.model.headers.User$minusAgent(akka.http.model.japi.Util.convertArray(products)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/WWWAuthenticate.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/WWWAuthenticate.java new file mode 100644 index 0000000000..aac65e27f1 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/WWWAuthenticate.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `WWW-Authenticate` header. + * Specification: http://tools.ietf.org/html/draft-ietf-httpbis-p7-auth-26#section-4.1 + */ +public abstract class WWWAuthenticate extends akka.http.model.HttpHeader { + public abstract Iterable getChallenges(); + + public static WWWAuthenticate create(HttpChallenge... challenges) { + return new akka.http.model.headers.WWW$minusAuthenticate(akka.http.model.japi.Util.convertArray(challenges)); + } +} diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/XForwardedFor.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/XForwardedFor.java new file mode 100644 index 0000000000..b7933860da --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/XForwardedFor.java @@ -0,0 +1,17 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi.headers; + +/** + * Model for the `X-Forwarded-For` header. + * Specification: http://en.wikipedia.org/wiki/X-Forwarded-For + */ +public abstract class XForwardedFor extends akka.http.model.HttpHeader { + public abstract Iterable getAddresses(); + + public static XForwardedFor create(akka.http.model.japi.RemoteAddress... addresses) { + return new akka.http.model.headers.X$minusForwarded$minusFor(akka.http.model.japi.Util.convertArray(addresses)); + } +} diff --git a/akka-http-core/src/main/scala/akka/http/Http.scala b/akka-http-core/src/main/scala/akka/http/Http.scala index ac41267a26..22274d7c6a 100644 --- a/akka-http-core/src/main/scala/akka/http/Http.scala +++ b/akka-http-core/src/main/scala/akka/http/Http.scala @@ -12,7 +12,7 @@ import akka.io.Inet import akka.stream.MaterializerSettings import akka.http.client.{ HttpClientProcessor, ClientConnectionSettings } import akka.http.server.ServerSettings -import akka.http.model.{ HttpResponse, HttpRequest } +import akka.http.model.{ HttpResponse, HttpRequest, japi } import akka.http.util._ import akka.actor._ @@ -110,11 +110,19 @@ object Http extends ExtensionKey[HttpExt] { } final case class ServerBinding(localAddress: InetSocketAddress, - connectionStream: Producer[IncomingConnection]) + connectionStream: Producer[IncomingConnection]) extends model.japi.ServerBinding { + /** Java API */ + def getConnectionStream: Producer[japi.IncomingConnection] = connectionStream.asInstanceOf[Producer[japi.IncomingConnection]] + } final case class IncomingConnection(remoteAddress: InetSocketAddress, requestProducer: Producer[HttpRequest], - responseConsumer: Consumer[HttpResponse]) + responseConsumer: Consumer[HttpResponse]) extends model.japi.IncomingConnection { + /** Java API */ + def getRequestProducer: Producer[japi.HttpRequest] = requestProducer.asInstanceOf[Producer[japi.HttpRequest]] + /** Java API */ + def getResponseConsumer: Consumer[japi.HttpResponse] = responseConsumer.asInstanceOf[Consumer[japi.HttpResponse]] + } case object BindFailedException extends SingletonException diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/ContentRange.scala b/akka-http-core/src/main/scala/akka/http/model/ContentRange.scala similarity index 55% rename from akka-http-core/src/main/scala/akka/http/model/headers/ContentRange.scala rename to akka-http-core/src/main/scala/akka/http/model/ContentRange.scala index ff1a6e224a..256001dcad 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/ContentRange.scala +++ b/akka-http-core/src/main/scala/akka/http/model/ContentRange.scala @@ -2,14 +2,30 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package akka.http.model.headers +package akka.http.model + +import java.{ lang ⇒ jl } import akka.http.util.{ Rendering, ValueRenderable } -sealed trait ContentRange extends ValueRenderable +import akka.http.model.japi.JavaMapping.Implicits._ + +sealed trait ContentRange extends japi.ContentRange with ValueRenderable { + // default implementations to override + def isSatisfiable: Boolean = false + def isOther: Boolean = false + def getSatisfiableFirst: akka.japi.Option[jl.Long] = akka.japi.Option.none + def getSatisfiableLast: akka.japi.Option[jl.Long] = akka.japi.Option.none + def getOtherValue: akka.japi.Option[String] = akka.japi.Option.none +} sealed trait ByteContentRange extends ContentRange { def instanceLength: Option[Long] + + /** Java API */ + def isByteContentRange: Boolean = true + /** Java API */ + def getInstanceLength: akka.japi.Option[jl.Long] = instanceLength.asJava } // http://tools.ietf.org/html/rfc7233#section-4.2 @@ -29,6 +45,13 @@ object ContentRange { r ~~ first ~~ '-' ~~ last ~~ '/' if (instanceLength.isDefined) r ~~ instanceLength.get else r ~~ '*' } + + /** Java API */ + override def isSatisfiable: Boolean = true + /** Java API */ + override def getSatisfiableFirst: akka.japi.Option[jl.Long] = akka.japi.Option.some(first) + /** Java API */ + override def getSatisfiableLast: akka.japi.Option[jl.Long] = akka.japi.Option.some(last) } /** @@ -44,5 +67,12 @@ object ContentRange { */ final case class Other(override val value: String) extends ContentRange { def render[R <: Rendering](r: R): r.type = r ~~ value + + /** Java API */ + def isByteContentRange = false + /** Java API */ + def getInstanceLength: akka.japi.Option[jl.Long] = akka.japi.Option.none + /** Java API */ + override def getOtherValue: akka.japi.Option[String] = akka.japi.Option.some(value) } } \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/model/ContentType.scala b/akka-http-core/src/main/scala/akka/http/model/ContentType.scala index 4e312177a4..f48ed2ad9c 100644 --- a/akka-http-core/src/main/scala/akka/http/model/ContentType.scala +++ b/akka-http-core/src/main/scala/akka/http/model/ContentType.scala @@ -24,7 +24,7 @@ object ContentTypeRange { implicit def apply(mediaRange: MediaRange): ContentTypeRange = apply(mediaRange, HttpCharsetRange.`*`) } -final case class ContentType(mediaType: MediaType, definedCharset: Option[HttpCharset]) extends ValueRenderable { +final case class ContentType(mediaType: MediaType, definedCharset: Option[HttpCharset]) extends japi.ContentType with ValueRenderable { def render[R <: Rendering](r: R): r.type = definedCharset match { case Some(cs) ⇒ r ~~ mediaType ~~ ContentType.`; charset=` ~~ cs case _ ⇒ r ~~ mediaType @@ -40,6 +40,9 @@ final case class ContentType(mediaType: MediaType, definedCharset: Option[HttpCh if (noCharsetDefined || charset != definedCharset.get) copy(definedCharset = Some(charset)) else this def withoutDefinedCharset = if (isCharsetDefined) copy(definedCharset = None) else this + + /** Java API */ + def getDefinedCharset: japi.HttpCharset = definedCharset.getOrElse(null) } object ContentType { diff --git a/akka-http-core/src/main/scala/akka/http/model/HttpCharset.scala b/akka-http-core/src/main/scala/akka/http/model/HttpCharset.scala index 940e76c2a7..8a8909cdff 100644 --- a/akka-http-core/src/main/scala/akka/http/model/HttpCharset.scala +++ b/akka-http-core/src/main/scala/akka/http/model/HttpCharset.scala @@ -8,14 +8,21 @@ import language.implicitConversions import scala.collection.immutable import java.nio.charset.Charset import akka.http.util._ +import java.lang.Iterable /** * A charset range as encountered in `Accept-Charset`. Can either be a single charset, or `*` * if all charsets are supported and optionally a qValue for selecting this choice. */ -sealed abstract class HttpCharsetRange extends ValueRenderable with WithQValue[HttpCharsetRange] { +sealed abstract class HttpCharsetRange extends japi.HttpCharsetRange with ValueRenderable with WithQValue[HttpCharsetRange] { def qValue: Float def matches(charset: HttpCharset): Boolean + + /** Java API */ + def matches(charset: japi.HttpCharset): Boolean = { + import japi.JavaMapping.Implicits._ + matches(charset.asScala) + } } object HttpCharsetRange { @@ -23,6 +30,8 @@ object HttpCharsetRange { require(0.0f <= qValue && qValue <= 1.0f, "qValue must be >= 0 and <= 1.0") final def render[R <: Rendering](r: R): r.type = if (qValue < 1.0f) r ~~ "*;q=" ~~ qValue else r ~~ '*' def matches(charset: HttpCharset) = true + def matchesAll: Boolean = true + def withQValue(qValue: Float) = if (qValue == 1.0f) `*` else if (qValue != this.qValue) `*`(qValue.toFloat) else this } @@ -31,6 +40,8 @@ object HttpCharsetRange { final case class One(charset: HttpCharset, qValue: Float) extends HttpCharsetRange { require(0.0f <= qValue && qValue <= 1.0f, "qValue must be >= 0 and <= 1.0") def matches(charset: HttpCharset) = this.charset.value.equalsIgnoreCase(charset.value) + def matchesAll: Boolean = false + def withQValue(qValue: Float) = One(charset, qValue) def render[R <: Rendering](r: R): r.type = if (qValue < 1.0f) r ~~ charset ~~ ";q=" ~~ qValue else r ~~ charset } @@ -40,7 +51,7 @@ object HttpCharsetRange { } final case class HttpCharset private[http] (override val value: String)(val aliases: immutable.Seq[String]) - extends SingletonValueRenderable with WithQValue[HttpCharsetRange] { + extends japi.HttpCharset with SingletonValueRenderable with WithQValue[HttpCharsetRange] { @transient private[this] var _nioCharset: Charset = Charset.forName(value) def nioCharset: Charset = _nioCharset @@ -50,6 +61,12 @@ final case class HttpCharset private[http] (override val value: String)(val alia } def withQValue(qValue: Float): HttpCharsetRange = HttpCharsetRange(this, qValue.toFloat) + + /** Java API */ + def getAliases: Iterable[String] = { + import collection.JavaConverters._ + aliases.asJava + } } object HttpCharset { diff --git a/akka-http-core/src/main/scala/akka/http/model/HttpEntity.scala b/akka-http-core/src/main/scala/akka/http/model/HttpEntity.scala index 0d302e514b..486370414a 100644 --- a/akka-http-core/src/main/scala/akka/http/model/HttpEntity.scala +++ b/akka-http-core/src/main/scala/akka/http/model/HttpEntity.scala @@ -9,16 +9,19 @@ import java.io.File import org.reactivestreams.api.Producer import scala.collection.immutable import akka.util.ByteString + import akka.stream.{ TimerTransformer, FlowMaterializer } import akka.stream.scaladsl.Flow import akka.stream.impl.{ EmptyProducer, SynchronousProducerFromIterable } +import java.lang.Iterable +import japi.JavaMapping.Implicits._ import scala.concurrent.{ ExecutionContext, Future } import scala.concurrent.duration.FiniteDuration /** * Models the entity (aka "body" or "content) of an HTTP message. */ -sealed trait HttpEntity { +sealed trait HttpEntity extends japi.HttpEntity { /** * Determines whether this entity is known to be empty. */ @@ -57,6 +60,15 @@ sealed trait HttpEntity { s"HttpEntity.toStrict timed out after $timeout while still waiting for outstanding data") }) .toFuture(materializer) + + /** Java API */ + def getDataBytes(materializer: FlowMaterializer): Producer[ByteString] = dataBytes(materializer) + + // default implementations, should be overridden + def isCloseDelimited: Boolean = false + def isDefault: Boolean = false + def isChunked: Boolean = false + def isRegular: Boolean = false } object HttpEntity { @@ -89,7 +101,9 @@ object HttpEntity { * it is either chunked or defines a content-length that is known a-priori. * Close-delimited entities are not `Regular` as they exists primarily for backwards compatibility with HTTP/1.0. */ - sealed trait Regular extends HttpEntity + sealed trait Regular extends japi.HttpEntityRegular with HttpEntity { + override def isRegular: Boolean = true + } // TODO: re-establish serializability // TODO: equal/hashcode ? @@ -99,7 +113,7 @@ object HttpEntity { * @param contentType * @param data */ - final case class Strict(contentType: ContentType, data: ByteString) extends Regular { + final case class Strict(contentType: ContentType, data: ByteString) extends japi.HttpEntityStrict with Regular { def isKnownEmpty: Boolean = data.isEmpty def dataBytes(materializer: FlowMaterializer): Producer[ByteString] = SynchronousProducerFromIterable(data :: Nil) @@ -113,9 +127,10 @@ object HttpEntity { */ final case class Default(contentType: ContentType, contentLength: Long, - data: Producer[ByteString]) extends Regular { + data: Producer[ByteString]) extends japi.HttpEntityDefault with Regular { require(contentLength > 0, "contentLength must be positive (use `HttpEntity.empty(contentType)` for empty entities)") def isKnownEmpty = false + override def isDefault: Boolean = true def dataBytes(materializer: FlowMaterializer): Producer[ByteString] = data } @@ -125,8 +140,9 @@ object HttpEntity { * The content-length of such responses is unknown at the time the response headers have been received. * Note that this type of HttpEntity cannot be used for HttpRequests! */ - final case class CloseDelimited(contentType: ContentType, data: Producer[ByteString]) extends HttpEntity { + final case class CloseDelimited(contentType: ContentType, data: Producer[ByteString]) extends japi.HttpEntityCloseDelimited with HttpEntity { def isKnownEmpty = data eq EmptyProducer + override def isCloseDelimited: Boolean = true def dataBytes(materializer: FlowMaterializer): Producer[ByteString] = data } @@ -134,11 +150,15 @@ object HttpEntity { /** * The model for the entity of a chunked HTTP message (with `Transfer-Encoding: chunked`). */ - final case class Chunked(contentType: ContentType, chunks: Producer[ChunkStreamPart]) extends Regular { + final case class Chunked(contentType: ContentType, chunks: Producer[ChunkStreamPart]) extends japi.HttpEntityChunked with Regular { def isKnownEmpty = chunks eq EmptyProducer + override def isChunked: Boolean = true def dataBytes(materializer: FlowMaterializer): Producer[ByteString] = Flow(chunks).map(_.data).filter(_.nonEmpty).toProducer(materializer) + + /** Java API */ + def getChunks: Producer[japi.ChunkStreamPart] = chunks.asInstanceOf[Producer[japi.ChunkStreamPart]] } object Chunked { /** @@ -153,7 +173,7 @@ object HttpEntity { * An element of the HttpEntity data stream. * Can be either a `Chunk` or a `LastChunk`. */ - sealed trait ChunkStreamPart { + sealed abstract class ChunkStreamPart extends japi.ChunkStreamPart { def data: ByteString def extension: String def isLastChunk: Boolean @@ -170,6 +190,8 @@ object HttpEntity { final case class Chunk(data: ByteString, extension: String = "") extends ChunkStreamPart { require(data.nonEmpty, "An HttpEntity.Chunk must have non-empty data") def isLastChunk = false + + def getTrailerHeaders: Iterable[japi.HttpHeader] = java.util.Collections.emptyList[japi.HttpHeader] } object Chunk { def apply(string: String): Chunk = apply(ByteString(string)) @@ -184,6 +206,9 @@ object HttpEntity { case class LastChunk(extension: String = "", trailer: immutable.Seq[HttpHeader] = Nil) extends ChunkStreamPart { def data = ByteString.empty def isLastChunk = true + + /** Java API */ + def getTrailerHeaders: Iterable[japi.HttpHeader] = trailer.asJava } object LastChunk extends LastChunk("", Nil) } \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/model/HttpHeader.scala b/akka-http-core/src/main/scala/akka/http/model/HttpHeader.scala index 1e0d9ac975..1e43725377 100644 --- a/akka-http-core/src/main/scala/akka/http/model/HttpHeader.scala +++ b/akka-http-core/src/main/scala/akka/http/model/HttpHeader.scala @@ -10,7 +10,7 @@ import akka.http.util.ToStringRenderable * The model of an HTTP header. In its most basic form headers are simple name-value pairs. Header names * are compared in a case-insensitive way. */ -abstract class HttpHeader extends ToStringRenderable { +abstract class HttpHeader extends japi.HttpHeader with ToStringRenderable { def name: String def value: String def lowercaseName: String diff --git a/akka-http-core/src/main/scala/akka/http/model/HttpMessage.scala b/akka-http-core/src/main/scala/akka/http/model/HttpMessage.scala index 166640f594..8ba6c51d6a 100644 --- a/akka-http-core/src/main/scala/akka/http/model/HttpMessage.scala +++ b/akka-http-core/src/main/scala/akka/http/model/HttpMessage.scala @@ -12,11 +12,12 @@ import headers._ import scala.concurrent.duration.FiniteDuration import akka.stream.FlowMaterializer import scala.concurrent.{ ExecutionContext, Future } +import akka.util.ByteString /** * Common base class of HttpRequest and HttpResponse. */ -sealed abstract class HttpMessage { +sealed trait HttpMessage extends japi.HttpMessage { type Self <: HttpMessage def isRequest: Boolean @@ -42,7 +43,7 @@ sealed abstract class HttpMessage { } /** Returns a copy of this message with the entity set to the given one. */ - def withEntity(entity: HttpEntity): Self + def withEntity(entity: japi.HttpEntity): Self /** Returns a sharable and serializable copy of this message with a strict entity. */ def toStrict(timeout: FiniteDuration, materializer: FlowMaterializer)(implicit ec: ExecutionContext): Future[Self] = @@ -67,7 +68,7 @@ sealed abstract class HttpMessage { } /** Returns the first header of the given type if there is one */ - def header[T <: HttpHeader: ClassTag]: Option[T] = { + def header[T <: japi.HttpHeader: ClassTag]: Option[T] = { val erasure = classTag[T].runtimeClass headers.find(erasure.isInstance).asInstanceOf[Option[T]] } @@ -78,6 +79,33 @@ sealed abstract class HttpMessage { * - HttpResponse and the server will close the connection after this response */ def connectionCloseExpected: Boolean = HttpMessage.connectionCloseExpected(protocol, header[Connection]) + + def addHeader(header: japi.HttpHeader): Self = mapHeaders(_ :+ header.asInstanceOf[HttpHeader]) + def removeHeader(headerName: String): Self = { + val lowerHeaderName = headerName.toLowerCase() + mapHeaders(_.filterNot(_.is(lowerHeaderName))) + } + + def withEntity(string: String): Self = withEntity(HttpEntity(string)) + def withEntity(bytes: Array[Byte]): Self = withEntity(HttpEntity(bytes)) + def withEntity(bytes: ByteString): Self = withEntity(HttpEntity(bytes)) + def withEntity(contentType: japi.ContentType, string: String): Self = withEntity(HttpEntity(contentType.asInstanceOf[ContentType], string)) + def withEntity(contentType: japi.ContentType, bytes: Array[Byte]): Self = withEntity(HttpEntity(contentType.asInstanceOf[ContentType], bytes)) + def withEntity(contentType: japi.ContentType, bytes: ByteString): Self = withEntity(HttpEntity(contentType.asInstanceOf[ContentType], bytes)) + def withEntity(contentType: japi.ContentType, file: java.io.File): Self = withEntity(HttpEntity(contentType.asInstanceOf[ContentType], file)) + + import collection.JavaConverters._ + /** Java API */ + def getHeaders: java.lang.Iterable[japi.HttpHeader] = (headers: immutable.Seq[japi.HttpHeader]).asJava + /** Java API */ + def getHeader[T <: japi.HttpHeader](headerClass: Class[T]): akka.japi.Option[T] = header(ClassTag(headerClass)) + /** Java API */ + def getHeader(headerName: String): akka.japi.Option[japi.HttpHeader] = { + val lowerCased = headerName.toLowerCase + headers.find(_.is(lowerCased)) + } + /** Java API */ + def addHeaders(headers: java.lang.Iterable[japi.HttpHeader]): Self = mapHeaders(_ ++ headers.asScala.asInstanceOf[Iterable[HttpHeader]]) } object HttpMessage { @@ -95,7 +123,7 @@ final case class HttpRequest(method: HttpMethod = HttpMethods.GET, uri: Uri = Uri./, headers: immutable.Seq[HttpHeader] = Nil, entity: HttpEntity.Regular = HttpEntity.Empty, - protocol: HttpProtocol = HttpProtocols.`HTTP/1.1`) extends HttpMessage { + protocol: HttpProtocol = HttpProtocols.`HTTP/1.1`) extends japi.HttpRequest with HttpMessage { require(!uri.isEmpty, "An HttpRequest must not have an empty Uri") require(entity.isKnownEmpty || method.isEntityAccepted, "Requests with this method must have an empty entity") require(protocol == HttpProtocols.`HTTP/1.1` || !entity.isInstanceOf[HttpEntity.Chunked], @@ -235,7 +263,7 @@ final case class HttpRequest(method: HttpMethod = HttpMethods.GET, def withHeaders(headers: immutable.Seq[HttpHeader]): HttpRequest = if (headers eq this.headers) this else copy(headers = headers) - def withEntity(entity: HttpEntity): HttpRequest = + def withEntity(entity: japi.HttpEntity): HttpRequest = if (entity ne this.entity) entity match { case x: HttpEntity.Regular ⇒ copy(entity = x) case _ ⇒ throw new IllegalArgumentException("entity must be HttpEntity.Regular") @@ -248,6 +276,15 @@ final case class HttpRequest(method: HttpMethod = HttpMethods.GET, case _ ⇒ throw new IllegalArgumentException("entity must be HttpEntity.Regular") } else this + + def withMethod(method: akka.http.model.japi.HttpMethod): HttpRequest = copy(method = method.asInstanceOf[HttpMethod]) + def withProtocol(protocol: akka.http.model.japi.HttpProtocol): HttpRequest = copy(protocol = protocol.asInstanceOf[HttpProtocol]) + def withUri(path: String): HttpRequest = copy(uri = Uri(path)) + + /** Java API */ + def getUri: japi.Uri = japi.Accessors.Uri(uri) + /** Java API */ + def withUri(relativeUri: akka.http.model.japi.Uri): HttpRequest = copy(uri = relativeUri.asInstanceOf[japi.JavaUri].uri) } object HttpRequest { @@ -280,7 +317,7 @@ object HttpRequest { final case class HttpResponse(status: StatusCode = StatusCodes.OK, headers: immutable.Seq[HttpHeader] = Nil, entity: HttpEntity = HttpEntity.Empty, - protocol: HttpProtocol = HttpProtocols.`HTTP/1.1`) extends HttpMessage { + protocol: HttpProtocol = HttpProtocols.`HTTP/1.1`) extends japi.HttpResponse with HttpMessage { type Self = HttpResponse def isRequest = false @@ -289,8 +326,12 @@ final case class HttpResponse(status: StatusCode = StatusCodes.OK, def withHeaders(headers: immutable.Seq[HttpHeader]) = if (headers eq this.headers) this else copy(headers = headers) - def withEntity(entity: HttpEntity) = if (entity eq this.entity) this else copy(entity = entity) + def withEntity(entity: japi.HttpEntity) = if (entity eq this.entity) this else copy(entity = entity.asInstanceOf[HttpEntity]) def withHeadersAndEntity(headers: immutable.Seq[HttpHeader], entity: HttpEntity) = if ((headers eq this.headers) && (entity eq this.entity)) this else copy(headers = headers, entity = entity) + + def withProtocol(protocol: akka.http.model.japi.HttpProtocol): akka.http.model.japi.HttpResponse = copy(protocol = protocol.asInstanceOf[HttpProtocol]) + def withStatus(statusCode: Int): akka.http.model.japi.HttpResponse = copy(status = statusCode) + def withStatus(statusCode: akka.http.model.japi.StatusCode): akka.http.model.japi.HttpResponse = copy(status = statusCode.asInstanceOf[StatusCode]) } \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/model/HttpMethod.scala b/akka-http-core/src/main/scala/akka/http/model/HttpMethod.scala index 058352cfcd..1c0e9a05b1 100644 --- a/akka-http-core/src/main/scala/akka/http/model/HttpMethod.scala +++ b/akka-http-core/src/main/scala/akka/http/model/HttpMethod.scala @@ -17,7 +17,7 @@ final case class HttpMethod private[http] (override val value: String, fingerprint: Int, isSafe: Boolean, isIdempotent: Boolean, - isEntityAccepted: Boolean) extends SingletonValueRenderable { + isEntityAccepted: Boolean) extends japi.HttpMethod with SingletonValueRenderable { def name = value override def hashCode(): Int = fingerprint diff --git a/akka-http-core/src/main/scala/akka/http/model/HttpProtocol.scala b/akka-http-core/src/main/scala/akka/http/model/HttpProtocol.scala index 296552d024..ac25b4dcc2 100644 --- a/akka-http-core/src/main/scala/akka/http/model/HttpProtocol.scala +++ b/akka-http-core/src/main/scala/akka/http/model/HttpProtocol.scala @@ -7,7 +7,7 @@ package akka.http.model import akka.http.util.{ SingletonValueRenderable, ObjectRegistry } /** The protocol of an HTTP message */ -final case class HttpProtocol private[http] (override val value: String) extends SingletonValueRenderable +final case class HttpProtocol private[http] (override val value: String) extends japi.HttpProtocol with SingletonValueRenderable object HttpProtocols extends ObjectRegistry[String, HttpProtocol] { private def register(p: HttpProtocol): HttpProtocol = register(p.value, p) diff --git a/akka-http-core/src/main/scala/akka/http/model/MediaType.scala b/akka-http-core/src/main/scala/akka/http/model/MediaType.scala index d5f8d4a0f7..0978474cbe 100644 --- a/akka-http-core/src/main/scala/akka/http/model/MediaType.scala +++ b/akka-http-core/src/main/scala/akka/http/model/MediaType.scala @@ -7,8 +7,9 @@ package akka.http.model import language.implicitConversions import scala.collection.immutable import akka.http.util._ +import java.util -sealed abstract class MediaRange extends Renderable with WithQValue[MediaRange] { +sealed abstract class MediaRange extends japi.MediaRange with Renderable with WithQValue[MediaRange] { def value: String def mainType: String def params: Map[String, String] @@ -32,6 +33,17 @@ sealed abstract class MediaRange extends Renderable with WithQValue[MediaRange] * Constructs a `ContentTypeRange` from this instance and the given charset. */ def withCharset(charsetRange: HttpCharsetRange): ContentTypeRange = ContentTypeRange(this, charsetRange) + + /** Java API */ + def getParams: util.Map[String, String] = { + import collection.JavaConverters._ + params.asJava + } + /** Java API */ + def matches(mediaType: japi.MediaType): Boolean = { + import japi.JavaMapping.Implicits._ + matches(mediaType.asScala) + } } object MediaRange { @@ -139,7 +151,7 @@ sealed abstract case class MediaType private[http] (value: String)(val mainType: val binary: Boolean, val fileExtensions: immutable.Seq[String], val params: Map[String, String]) - extends LazyValueBytesRenderable with WithQValue[MediaRange] { + extends japi.MediaType with LazyValueBytesRenderable with WithQValue[MediaRange] { def isApplication = false def isAudio = false def isImage = false diff --git a/akka-http-core/src/main/scala/akka/http/model/MultipartContent.scala b/akka-http-core/src/main/scala/akka/http/model/MultipartContent.scala index addf5864e4..e95f1ed186 100644 --- a/akka-http-core/src/main/scala/akka/http/model/MultipartContent.scala +++ b/akka-http-core/src/main/scala/akka/http/model/MultipartContent.scala @@ -55,8 +55,8 @@ final case class BodyPart(entity: HttpEntity, headers: immutable.Seq[HttpHeader] def dispositionParameterValue(parameter: String): Option[String] = headers.collectFirst { - case `Content-Disposition`(ContentDispositionTypes.`form-data`, parameters) if parameters.contains(parameter) ⇒ - parameters(parameter) + case `Content-Disposition`(ContentDispositionTypes.`form-data`, params) if params.contains(parameter) ⇒ + params(parameter) } def contentRange: Option[ContentRange] = diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/RemoteAddress.scala b/akka-http-core/src/main/scala/akka/http/model/RemoteAddress.scala similarity index 74% rename from akka-http-core/src/main/scala/akka/http/model/headers/RemoteAddress.scala rename to akka-http-core/src/main/scala/akka/http/model/RemoteAddress.scala index a255174166..c358d481af 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/RemoteAddress.scala +++ b/akka-http-core/src/main/scala/akka/http/model/RemoteAddress.scala @@ -2,24 +2,34 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package akka.http.model.headers +package akka.http.model import java.net.{ UnknownHostException, InetAddress } import akka.http.util._ -sealed abstract class RemoteAddress extends ValueRenderable { +import japi.JavaMapping.Implicits._ + +sealed abstract class RemoteAddress extends japi.RemoteAddress with ValueRenderable { def toOption: Option[InetAddress] + def isUnknown: Boolean + + /** Java API */ + def getAddress: akka.japi.Option[InetAddress] = toOption.asJava } object RemoteAddress { case object Unknown extends RemoteAddress { def toOption = None def render[R <: Rendering](r: R): r.type = r ~~ "unknown" + + def isUnknown = true } final case class IP(ip: InetAddress) extends RemoteAddress { def toOption: Option[InetAddress] = Some(ip) def render[R <: Rendering](r: R): r.type = r ~~ ip.getHostAddress + + def isUnknown = false } def apply(s: String): RemoteAddress = diff --git a/akka-http-core/src/main/scala/akka/http/model/StatusCode.scala b/akka-http-core/src/main/scala/akka/http/model/StatusCode.scala index e28bc59bf8..fcb1db21a2 100644 --- a/akka-http-core/src/main/scala/akka/http/model/StatusCode.scala +++ b/akka-http-core/src/main/scala/akka/http/model/StatusCode.scala @@ -8,7 +8,7 @@ import language.implicitConversions import akka.http.util._ /** The result status code of an HTTP response. */ -sealed abstract class StatusCode extends LazyValueBytesRenderable { +sealed abstract class StatusCode extends japi.StatusCode with LazyValueBytesRenderable { def intValue: Int def value: String = intValue.toString + ' ' + reason def reason: String diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/TransferEncoding.scala b/akka-http-core/src/main/scala/akka/http/model/TransferEncoding.scala similarity index 78% rename from akka-http-core/src/main/scala/akka/http/model/headers/TransferEncoding.scala rename to akka-http-core/src/main/scala/akka/http/model/TransferEncoding.scala index d8e23ff8bc..69339d2c02 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/TransferEncoding.scala +++ b/akka-http-core/src/main/scala/akka/http/model/TransferEncoding.scala @@ -2,13 +2,17 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package akka.http.model.headers +package akka.http.model import akka.http.util.{ Rendering, SingletonValueRenderable, Renderable } -sealed trait TransferEncoding extends Renderable { +import akka.http.model.japi.JavaMapping.Implicits._ + +sealed abstract class TransferEncoding extends japi.TransferEncoding with Renderable { def name: String def params: Map[String, String] + + def getParams: java.util.Map[String, String] = params.asJava } object TransferEncodings { diff --git a/akka-http-core/src/main/scala/akka/http/model/Uri.scala b/akka-http-core/src/main/scala/akka/http/model/Uri.scala index c4f6081c2f..1044ce7dbc 100644 --- a/akka-http-core/src/main/scala/akka/http/model/Uri.scala +++ b/akka-http-core/src/main/scala/akka/http/model/Uri.scala @@ -5,7 +5,7 @@ package akka.http.model import language.implicitConversions -import java.lang.{ StringBuilder ⇒ JStringBuilder } +import java.lang.{ StringBuilder ⇒ JStringBuilder, Iterable } import java.nio.charset.Charset import scala.annotation.tailrec import scala.collection.{ immutable, mutable, LinearSeqOptimized } @@ -305,13 +305,25 @@ object Uri { val Empty = Authority(Host.Empty) } - sealed abstract class Host { + sealed abstract class Host extends japi.Host { def address: String def isEmpty: Boolean def toOption: Option[NonEmptyHost] def inetAddresses: immutable.Seq[InetAddress] + def equalsIgnoreCase(other: Host): Boolean override def toString() = UriRendering.HostRenderer.render(new StringRendering, this).get + + // default implementations + def isNamedHost: Boolean = false + def isIPv6: Boolean = false + def isIPv4: Boolean = false + + /** Java API */ + def getInetAddresses: Iterable[InetAddress] = { + import akka.http.model.japi.JavaMapping.Implicits._ + inetAddresses.asJava + } } object Host { case object Empty extends Host { @@ -345,6 +357,7 @@ object Uri { case _ ⇒ false } + override def isIPv4: Boolean = true def inetAddresses = immutable.Seq(InetAddress.getByAddress(bytes.toArray)) } object IPv4Host { @@ -362,6 +375,7 @@ object Uri { case _ ⇒ false } + override def isIPv6: Boolean = true def inetAddresses = immutable.Seq(InetAddress.getByAddress(bytes.toArray)) } object IPv6Host { @@ -381,6 +395,7 @@ object Uri { case _ ⇒ false } + override def isNamedHost: Boolean = true def inetAddresses = InetAddress.getAllByName(address).toList } diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/ByteRange.scala b/akka-http-core/src/main/scala/akka/http/model/headers/ByteRange.scala index 65e15acfdf..35037f5139 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/ByteRange.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/ByteRange.scala @@ -2,11 +2,32 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package akka.http.model.headers +package akka.http.model +package headers import akka.http.util.{ Rendering, ValueRenderable } +import akka.japi.{ Option ⇒ JOption } +import java.{ lang ⇒ jl } -sealed trait ByteRange extends ValueRenderable +sealed abstract class ByteRange extends japi.headers.ByteRange with ValueRenderable { + /** Java API */ + def getSliceFirst: JOption[jl.Long] = JOption.none + /** Java API */ + def getSliceLast: JOption[jl.Long] = JOption.none + /** Java API */ + def getOffset: JOption[jl.Long] = JOption.none + /** Java API */ + def getSuffixLength: JOption[jl.Long] = JOption.none + + /** Java API */ + def isSlice: Boolean = false + + /** Java API */ + def isFromOffset: Boolean = false + + /** Java API */ + def isSuffix: Boolean = false +} object ByteRange { def apply(first: Long, last: Long) = Slice(first, last) @@ -16,15 +37,32 @@ object ByteRange { final case class Slice(first: Long, last: Long) extends ByteRange { require(0 <= first && first <= last, "first must be >= 0 and <= last") def render[R <: Rendering](r: R): r.type = r ~~ first ~~ '-' ~~ last + + /** Java API */ + override def isSlice: Boolean = true + /** Java API */ + override def getSliceFirst: JOption[jl.Long] = JOption.some(first) + /** Java API */ + override def getSliceLast: JOption[jl.Long] = JOption.some(last) } final case class FromOffset(offset: Long) extends ByteRange { require(0 <= offset, "offset must be >= 0") def render[R <: Rendering](r: R): r.type = r ~~ offset ~~ '-' + + /** Java API */ + override def isFromOffset: Boolean = true + /** Java API */ + override def getOffset: JOption[jl.Long] = JOption.some(offset) } final case class Suffix(length: Long) extends ByteRange { require(0 <= length, "length must be >= 0") def render[R <: Rendering](r: R): r.type = r ~~ '-' ~~ length + + /** Java API */ + override def isSuffix: Boolean = true + /** Java API */ + override def getSuffixLength: JOption[jl.Long] = JOption.some(length) } } \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/CacheDirective.scala b/akka-http-core/src/main/scala/akka/http/model/headers/CacheDirective.scala index eae35f51e6..45f8da5260 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/CacheDirective.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/CacheDirective.scala @@ -2,13 +2,14 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package akka.http.model.headers +package akka.http.model +package headers -import scala.annotation.tailrec +import scala.annotation.{ varargs, tailrec } import scala.collection.immutable import akka.http.util._ -sealed trait CacheDirective extends Renderable { +sealed trait CacheDirective extends Renderable with japi.headers.CacheDirective { def value: String } @@ -67,7 +68,7 @@ object CacheDirectives { // http://tools.ietf.org/html/rfc7234#section-5.2.1.4 case object `no-cache` extends SingletonValueRenderable with RequestDirective with ResponseDirective { - def apply(fieldNames: String*): `no-cache` = apply(immutable.Seq(fieldNames: _*)) + @varargs def apply(fieldNames: String*): `no-cache` = apply(immutable.Seq(fieldNames: _*)) } // http://tools.ietf.org/html/rfc7234#section-5.2.1.5 @@ -93,7 +94,7 @@ object CacheDirectives { // http://tools.ietf.org/html/rfc7234#section-5.2.2.6 final case class `private`(fieldNames: immutable.Seq[String]) extends FieldNamesDirective with ResponseDirective object `private` { - def apply(fieldNames: String*): `private` = apply(immutable.Seq(fieldNames: _*)) + @varargs def apply(fieldNames: String*): `private` = apply(immutable.Seq(fieldNames: _*)) } // http://tools.ietf.org/html/rfc7234#section-5.2.2.7 diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/ContentDispositionType.scala b/akka-http-core/src/main/scala/akka/http/model/headers/ContentDispositionType.scala index a185f3d287..4d0e1462e8 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/ContentDispositionType.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/ContentDispositionType.scala @@ -2,11 +2,12 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package akka.http.model.headers +package akka.http.model +package headers import akka.http.util.{ Rendering, SingletonValueRenderable, Renderable } -sealed trait ContentDispositionType extends Renderable +sealed trait ContentDispositionType extends Renderable with japi.headers.ContentDispositionType object ContentDispositionTypes { protected abstract class Predefined extends ContentDispositionType with SingletonValueRenderable { diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/EntityTag.scala b/akka-http-core/src/main/scala/akka/http/model/headers/EntityTag.scala index 1f9259bb31..477cff0a28 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/EntityTag.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/EntityTag.scala @@ -2,12 +2,13 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package akka.http.model.headers +package akka.http.model +package headers import scala.collection.immutable import akka.http.util.{ Renderer, Rendering, ValueRenderable } -final case class EntityTag(tag: String, weak: Boolean = false) extends ValueRenderable { +final case class EntityTag(tag: String, weak: Boolean = false) extends japi.headers.EntityTag with ValueRenderable { def render[R <: Rendering](r: R): r.type = if (weak) r ~~ "W/" ~~#! tag else r ~~#! tag } @@ -20,7 +21,7 @@ object EntityTag { other.tag == eTag.tag && (weak || !other.weak && !eTag.weak) } -sealed abstract class EntityTagRange extends ValueRenderable +sealed abstract class EntityTagRange extends japi.headers.EntityTagRange with ValueRenderable object EntityTagRange { def apply(tags: EntityTag*) = Default(immutable.Seq(tags: _*)) diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/HttpChallenge.scala b/akka-http-core/src/main/scala/akka/http/model/headers/HttpChallenge.scala index 2d93c9f29a..6d27935ad4 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/HttpChallenge.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/HttpChallenge.scala @@ -6,13 +6,19 @@ package akka.http.model package headers import akka.http.util._ +import java.util + +import akka.http.model.japi.JavaMapping.Implicits._ final case class HttpChallenge(scheme: String, realm: String, - params: Map[String, String] = Map.empty) extends ValueRenderable { + params: Map[String, String] = Map.empty) extends japi.headers.HttpChallenge with ValueRenderable { def render[R <: Rendering](r: R): r.type = { r ~~ scheme ~~ " realm=" ~~# realm if (params.nonEmpty) params.foreach { case (k, v) ⇒ r ~~ ',' ~~ k ~~ '=' ~~# v } r } + + /** Java API */ + def getParams: util.Map[String, String] = params.asJava } diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/HttpCookie.scala b/akka-http-core/src/main/scala/akka/http/model/headers/HttpCookie.scala index eb96eeb86b..e1d6431604 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/HttpCookie.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/HttpCookie.scala @@ -7,6 +7,9 @@ package headers import akka.parboiled2.CharPredicate import akka.http.util._ +import akka.japi.{ Option ⇒ JOption } + +import akka.http.model.japi.JavaMapping.Implicits._ // see http://tools.ietf.org/html/rfc6265 final case class HttpCookie( @@ -18,7 +21,7 @@ final case class HttpCookie( path: Option[String] = None, secure: Boolean = false, httpOnly: Boolean = false, - extension: Option[String] = None) extends ValueRenderable { + extension: Option[String] = None) extends japi.headers.HttpCookie with ValueRenderable { import HttpCookie._ @@ -40,6 +43,17 @@ final case class HttpCookie( if (extension.isDefined) r ~~ ';' ~~ ' ' ~~ extension.get r } + + /** Java API */ + def getExtension: JOption[String] = extension.asJava + /** Java API */ + def getPath: JOption[String] = path.asJava + /** Java API */ + def getDomain: JOption[String] = domain.asJava + /** Java API */ + def getMaxAge: JOption[java.lang.Long] = maxAge.asJava + /** Java API */ + def getExpires: JOption[japi.DateTime] = expires.asJava } object HttpCookie { diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/HttpCredentials.scala b/akka-http-core/src/main/scala/akka/http/model/headers/HttpCredentials.scala index b8a7975a1a..8c0438423b 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/HttpCredentials.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/HttpCredentials.scala @@ -9,13 +9,18 @@ import akka.parboiled2.util.Base64 import akka.http.model.HttpCharsets._ import akka.http.util.{ Rendering, ValueRenderable } -sealed trait HttpCredentials extends ValueRenderable { +import akka.http.model.japi.JavaMapping.Implicits._ + +sealed abstract class HttpCredentials extends japi.headers.HttpCredentials with ValueRenderable { def scheme: String def token: String def params: Map[String, String] + + /** Java API */ + def getParams: java.util.Map[String, String] = params.asJava } -final case class BasicHttpCredentials(username: String, password: String) extends HttpCredentials { +final case class BasicHttpCredentials(username: String, password: String) extends japi.headers.BasicHttpCredentials { val cookie = { val userPass = username + ':' + password val bytes = userPass.getBytes(`ISO-8859-1`.nioCharset) @@ -39,7 +44,7 @@ object BasicHttpCredentials { } } -final case class OAuth2BearerToken(token: String) extends HttpCredentials { +final case class OAuth2BearerToken(token: String) extends japi.headers.OAuth2BearerToken { def render[R <: Rendering](r: R): r.type = r ~~ "Bearer " ~~ token def scheme: String = "Bearer" @@ -48,7 +53,6 @@ final case class OAuth2BearerToken(token: String) extends HttpCredentials { final case class GenericHttpCredentials(scheme: String, token: String, params: Map[String, String] = Map.empty) extends HttpCredentials { - def render[R <: Rendering](r: R): r.type = { r ~~ scheme if (!token.isEmpty) r ~~ ' ' ~~ token diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/HttpEncoding.scala b/akka-http-core/src/main/scala/akka/http/model/headers/HttpEncoding.scala index 24bc3fdefd..c7dbaba2d8 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/HttpEncoding.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/HttpEncoding.scala @@ -7,10 +7,14 @@ package headers import language.implicitConversions import akka.http.util._ +import akka.http.model.japi.JavaMapping.Implicits._ -sealed abstract class HttpEncodingRange extends ValueRenderable with WithQValue[HttpEncodingRange] { +sealed abstract class HttpEncodingRange extends japi.headers.HttpEncodingRange with ValueRenderable with WithQValue[HttpEncodingRange] { def qValue: Float def matches(encoding: HttpEncoding): Boolean + + /** Java API */ + def matches(encoding: japi.headers.HttpEncoding): Boolean = matches(encoding.asScala) } object HttpEncodingRange { @@ -34,7 +38,7 @@ object HttpEncodingRange { def apply(encoding: HttpEncoding, qValue: Float): HttpEncodingRange = One(encoding, qValue) } -final case class HttpEncoding private[http] (value: String) extends LazyValueBytesRenderable with WithQValue[HttpEncodingRange] { +final case class HttpEncoding private[http] (value: String) extends japi.headers.HttpEncoding with LazyValueBytesRenderable with WithQValue[HttpEncodingRange] { def withQValue(qValue: Float): HttpEncodingRange = HttpEncodingRange(this, qValue.toFloat) } diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/HttpOrigin.scala b/akka-http-core/src/main/scala/akka/http/model/headers/HttpOrigin.scala index 0b92fc2b6f..08e42a0ab2 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/HttpOrigin.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/HttpOrigin.scala @@ -11,8 +11,13 @@ import akka.parboiled2.UTF8 import akka.http.model.parser.UriParser import akka.http.util._ -abstract class HttpOriginRange extends ValueRenderable { +import akka.http.model.japi.JavaMapping.Implicits._ + +abstract class HttpOriginRange extends japi.headers.HttpOriginRange with ValueRenderable { def matches(origin: HttpOrigin): Boolean + + /** Java API */ + def matches(origin: japi.headers.HttpOrigin): Boolean = matches(origin.asScala) } object HttpOriginRange { case object `*` extends HttpOriginRange { @@ -28,7 +33,7 @@ object HttpOriginRange { } } -final case class HttpOrigin(scheme: String, host: Host) extends ValueRenderable { +final case class HttpOrigin(scheme: String, host: Host) extends japi.headers.HttpOrigin with ValueRenderable { def render[R <: Rendering](r: R): r.type = host.renderValue(r ~~ scheme ~~ "://") } object HttpOrigin { diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/LanguageRange.scala b/akka-http-core/src/main/scala/akka/http/model/headers/LanguageRange.scala index ed923424b3..2f61225c7d 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/LanguageRange.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/LanguageRange.scala @@ -8,7 +8,9 @@ package headers import scala.collection.immutable import akka.http.util._ -sealed abstract class LanguageRange extends ValueRenderable with WithQValue[LanguageRange] { +import akka.http.model.japi.JavaMapping.Implicits._ + +sealed trait LanguageRange extends japi.headers.LanguageRange with ValueRenderable with WithQValue[LanguageRange] { def qValue: Float def primaryTag: String def subTags: immutable.Seq[String] @@ -19,6 +21,10 @@ sealed abstract class LanguageRange extends ValueRenderable with WithQValue[Lang if (qValue < 1.0f) r ~~ ";q=" ~~ qValue r } + + /** Java API */ + def matches(language: japi.headers.Language): Boolean = matches(language.asScala) + def getSubTags: java.lang.Iterable[String] = subTags.asJava } object LanguageRange { case class `*`(qValue: Float) extends LanguageRange { @@ -32,10 +38,11 @@ object LanguageRange { object `*` extends `*`(1.0f) } -final case class Language(primaryTag: String, subTags: immutable.Seq[String], qValue: Float = 1.0f) extends LanguageRange { +final case class Language(primaryTag: String, subTags: immutable.Seq[String], qValue: Float = 1.0f) extends japi.headers.Language with LanguageRange { require(0.0f <= qValue && qValue <= 1.0f, "qValue must be >= 0 and <= 1.0") def matches(lang: Language): Boolean = lang.primaryTag == this.primaryTag && lang.subTags == this.subTags - def withQValue(qValue: Float) = Language(primaryTag, subTags, qValue) + def withQValue(qValue: Float): Language = Language(primaryTag, subTags, qValue) + override def withQValue(qValue: Double): Language = withQValue(qValue.toFloat) } object Language { def apply(primaryTag: String, subTags: String*) = new Language(primaryTag, immutable.Seq(subTags: _*)) diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/LinkValue.scala b/akka-http-core/src/main/scala/akka/http/model/headers/LinkValue.scala index 007e99a641..891cb70b37 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/LinkValue.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/LinkValue.scala @@ -10,19 +10,27 @@ import akka.parboiled2.CharPredicate import akka.http.util._ import UriRendering.UriRenderer -final case class LinkValue(uri: Uri, params: immutable.Seq[LinkParam]) extends ValueRenderable { +import akka.http.model.japi.JavaMapping.Implicits._ + +final case class LinkValue(uri: Uri, params: immutable.Seq[LinkParam]) extends japi.headers.LinkValue with ValueRenderable { def render[R <: Rendering](r: R): r.type = { r ~~ '<' ~~ uri ~~ '>' if (params.nonEmpty) r ~~ "; " ~~ params r } + + def getUri: japi.Uri = uri.asJava + def getParams: java.lang.Iterable[japi.headers.LinkParam] = params.asJava } object LinkValue { def apply(uri: Uri, params: LinkParam*): LinkValue = apply(uri, immutable.Seq(params: _*)) } -sealed abstract class LinkParam extends ToStringRenderable +sealed abstract class LinkParam extends japi.headers.LinkParam with ToStringRenderable { + val key: String = getClass.getSimpleName + def value: AnyRef +} object LinkParam { implicit val paramsRenderer: Renderer[immutable.Seq[LinkParam]] = Renderer.seqRenderer(separator = "; ") } @@ -47,6 +55,8 @@ object LinkParams { // http://tools.ietf.org/html/rfc5988#section-5.2 final case class anchor(uri: Uri) extends LinkParam { + def value: AnyRef = uri + def render[R <: Rendering](r: R): r.type = r ~~ "anchor=\"" ~~ uri ~~ '"' } @@ -61,11 +71,15 @@ object LinkParams { // http://tools.ietf.org/html/rfc5988#section-5.4 final case class hreflang(lang: Language) extends LinkParam { + def value: AnyRef = lang + def render[R <: Rendering](r: R): r.type = r ~~ "hreflang=" ~~ lang } // http://tools.ietf.org/html/rfc5988#section-5.4 final case class media(desc: String) extends LinkParam { + def value: AnyRef = desc + def render[R <: Rendering](r: R): r.type = { r ~~ "media=" if (reserved matchesAny desc) r ~~ '"' ~~ desc ~~ '"' else r ~~ desc @@ -74,11 +88,15 @@ object LinkParams { // http://tools.ietf.org/html/rfc5988#section-5.4 final case class title(title: String) extends LinkParam { + def value: AnyRef = title + def render[R <: Rendering](r: R): r.type = r ~~ "title=\"" ~~ title ~~ '"' } // http://tools.ietf.org/html/rfc5988#section-5.4 final case class `title*`(title: String) extends LinkParam { + def value: AnyRef = title + def render[R <: Rendering](r: R): r.type = { r ~~ "title*=" if (reserved matchesAny title) r ~~ '"' ~~ title ~~ '"' else r ~~ title @@ -87,6 +105,8 @@ object LinkParams { // http://tools.ietf.org/html/rfc5988#section-5.4 final case class `type`(mediaType: MediaType) extends LinkParam { + def value: AnyRef = mediaType + def render[R <: Rendering](r: R): r.type = { r ~~ "type=" if (reserved matchesAny mediaType.value) r ~~ '"' ~~ mediaType.value ~~ '"' else r ~~ mediaType.value diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/ProductVersion.scala b/akka-http-core/src/main/scala/akka/http/model/headers/ProductVersion.scala index f39dac733b..9b4eeb59fe 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/ProductVersion.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/ProductVersion.scala @@ -4,13 +4,15 @@ package akka.http.model.headers +import akka.http.model.japi + import scala.collection.immutable import scala.util.{ Failure, Success } import akka.parboiled2.ParseError import akka.http.model.parser.HeaderParser import akka.http.util._ -final case class ProductVersion(product: String = "", version: String = "", comment: String = "") extends ValueRenderable { +final case class ProductVersion(product: String = "", version: String = "", comment: String = "") extends japi.headers.ProductVersion with ValueRenderable { def render[R <: Rendering](r: R): r.type = { r ~~ product if (!version.isEmpty) r ~~ '/' ~~ version diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/RangeUnit.scala b/akka-http-core/src/main/scala/akka/http/model/headers/RangeUnit.scala index c122e9f25b..5ca0802070 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/RangeUnit.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/RangeUnit.scala @@ -2,14 +2,19 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package akka.http.model.headers +package akka.http.model +package headers import akka.http.util.{ Rendering, ValueRenderable } -sealed trait RangeUnit extends ValueRenderable +sealed abstract class RangeUnit extends japi.headers.RangeUnit with ValueRenderable { + def name: String +} object RangeUnits { object Bytes extends RangeUnit { + def name = "Bytes" + def render[R <: Rendering](r: R): r.type = r ~~ "bytes" } diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/headers.scala b/akka-http-core/src/main/scala/akka/http/model/headers/headers.scala index 443a20244f..1ad9a94b43 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/headers.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/headers.scala @@ -10,199 +10,40 @@ import scala.annotation.{ tailrec, implicitNotFound } import scala.collection.immutable import akka.http.util._ -object AllowProtectedHeaderCreation { +object ProtectedHeaderCreation { @implicitNotFound("Headers of this type are managed automatically by akka-http-core. If you are sure that creating " + - "instances manually is required in your use case `import AllowProtectedHeaderCreation.enable` to override this warning.") + "instances manually is required in your use case `import HttpHeaders.ProtectedHeaderCreation.enable` to override " + + "this warning.") sealed trait Enabled implicit def enable: Enabled = null } -import AllowProtectedHeaderCreation.enable +import ProtectedHeaderCreation.enable sealed abstract class ModeledCompanion extends Renderable { val name = getClass.getSimpleName.replace("$minus", "-").dropRight(1) // trailing $ val lowercaseName = name.toLowerCase private[this] val nameBytes = name.getAsciiBytes - final def render[R <: Rendering](r: R): r.type = r ~~ nameBytes ~~ ':' ~~ ' ' + def render[R <: Rendering](r: R): r.type = r ~~ nameBytes ~~ ':' ~~ ' ' } -sealed abstract class ModeledHeader extends HttpHeader with Serializable { +sealed trait ModeledHeader extends HttpHeader with Serializable { def name: String = companion.name def value: String = renderValue(new StringRendering).get def lowercaseName: String = companion.lowercaseName - final def render[R <: Rendering](r: R): r.type = renderValue(r ~~ companion) - protected def renderValue[R <: Rendering](r: R): r.type + def render[R <: Rendering](r: R): r.type = renderValue(r ~~ companion) + def renderValue[R <: Rendering](r: R): r.type protected def companion: ModeledCompanion } -// http://tools.ietf.org/html/rfc7231#section-5.3.2 -object Accept extends ModeledCompanion { - def apply(mediaRanges: MediaRange*): Accept = apply(immutable.Seq(mediaRanges: _*)) - private[http] implicit val rangesRenderer = Renderer.defaultSeqRenderer[MediaRange] // cache -} -final case class Accept(mediaRanges: immutable.Seq[MediaRange]) extends ModeledHeader { - import Accept.rangesRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ mediaRanges - protected def companion = Accept -} - -// http://tools.ietf.org/html/rfc7231#section-5.3.3 -object `Accept-Charset` extends ModeledCompanion { - def apply(first: HttpCharsetRange, more: HttpCharsetRange*): `Accept-Charset` = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val rangesRenderer = Renderer.defaultSeqRenderer[HttpCharsetRange] // cache -} -final case class `Accept-Charset`(charsetRanges: immutable.Seq[HttpCharsetRange]) extends ModeledHeader { - require(charsetRanges.nonEmpty, "charsetRanges must not be empty") - import `Accept-Charset`.rangesRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ charsetRanges - protected def companion = `Accept-Charset` -} - -// http://tools.ietf.org/html/rfc7231#section-5.3.4 -object `Accept-Encoding` extends ModeledCompanion { - def apply(encodings: HttpEncodingRange*): `Accept-Encoding` = apply(immutable.Seq(encodings: _*)) - private[http] implicit val rangesRenderer = Renderer.defaultSeqRenderer[HttpEncodingRange] // cache -} -final case class `Accept-Encoding`(encodings: immutable.Seq[HttpEncodingRange]) extends ModeledHeader { - import `Accept-Encoding`.rangesRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ encodings - protected def companion = `Accept-Encoding` -} - -// http://tools.ietf.org/html/rfc7231#section-5.3.5 -object `Accept-Language` extends ModeledCompanion { - def apply(first: LanguageRange, more: LanguageRange*): `Accept-Language` = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val rangesRenderer = Renderer.defaultSeqRenderer[LanguageRange] // cache -} -final case class `Accept-Language`(languages: immutable.Seq[LanguageRange]) extends ModeledHeader { - require(languages.nonEmpty, "languages must not be empty") - import `Accept-Language`.rangesRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ languages - protected def companion = `Accept-Language` -} - -// http://tools.ietf.org/html/rfc7233#section-2.3 -object `Accept-Ranges` extends ModeledCompanion { - def apply(rangeUnits: RangeUnit*): `Accept-Ranges` = apply(immutable.Seq(rangeUnits: _*)) - private[http] implicit val rangeUnitsRenderer = Renderer.defaultSeqRenderer[RangeUnit] // cache -} -final case class `Accept-Ranges`(rangeUnits: immutable.Seq[RangeUnit]) extends ModeledHeader { - import `Accept-Ranges`.rangeUnitsRenderer - protected def renderValue[R <: Rendering](r: R): r.type = if (rangeUnits.isEmpty) r ~~ "none" else r ~~ rangeUnits - protected def companion = `Accept-Ranges` -} - -// http://www.w3.org/TR/cors/#access-control-allow-credentials-response-header -object `Access-Control-Allow-Credentials` extends ModeledCompanion -final case class `Access-Control-Allow-Credentials`(allow: Boolean) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ allow.toString - protected def companion = `Access-Control-Allow-Credentials` -} - -// http://www.w3.org/TR/cors/#access-control-allow-headers-response-header -object `Access-Control-Allow-Headers` extends ModeledCompanion { - def apply(headers: String*): `Access-Control-Allow-Headers` = apply(immutable.Seq(headers: _*)) - private[http] implicit val headersRenderer = Renderer.defaultSeqRenderer[String] -} -final case class `Access-Control-Allow-Headers`(headers: immutable.Seq[String]) extends ModeledHeader { - import `Access-Control-Allow-Headers`.headersRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ headers - protected def companion = `Access-Control-Allow-Headers` -} - -// http://www.w3.org/TR/cors/#access-control-allow-methods-response-header -object `Access-Control-Allow-Methods` extends ModeledCompanion { - def apply(methods: HttpMethod*): `Access-Control-Allow-Methods` = apply(immutable.Seq(methods: _*)) - private[http] implicit val methodsRenderer = Renderer.defaultSeqRenderer[HttpMethod] -} -final case class `Access-Control-Allow-Methods`(methods: immutable.Seq[HttpMethod]) extends ModeledHeader { - import `Access-Control-Allow-Methods`.methodsRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ methods - protected def companion = `Access-Control-Allow-Methods` -} - -// http://www.w3.org/TR/cors/#access-control-allow-origin-response-header -object `Access-Control-Allow-Origin` extends ModeledCompanion -final case class `Access-Control-Allow-Origin`(range: HttpOriginRange) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ range - protected def companion = `Access-Control-Allow-Origin` -} - -// http://www.w3.org/TR/cors/#access-control-expose-headers-response-header -object `Access-Control-Expose-Headers` extends ModeledCompanion { - def apply(headers: String*): `Access-Control-Expose-Headers` = apply(immutable.Seq(headers: _*)) - private[http] implicit val headersRenderer = Renderer.defaultSeqRenderer[String] -} -final case class `Access-Control-Expose-Headers`(headers: immutable.Seq[String]) extends ModeledHeader { - import `Access-Control-Expose-Headers`.headersRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ headers - protected def companion = `Access-Control-Expose-Headers` -} - -// http://www.w3.org/TR/cors/#access-control-max-age-response-header -object `Access-Control-Max-Age` extends ModeledCompanion -final case class `Access-Control-Max-Age`(deltaSeconds: Long) extends ModeledHeader { - require(deltaSeconds >= 0, "deltaSeconds must be >= 0") - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ deltaSeconds - protected def companion = `Access-Control-Max-Age` -} - -// http://www.w3.org/TR/cors/#access-control-request-headers-request-header -object `Access-Control-Request-Headers` extends ModeledCompanion { - def apply(headers: String*): `Access-Control-Request-Headers` = apply(immutable.Seq(headers: _*)) - private[http] implicit val headersRenderer = Renderer.defaultSeqRenderer[String] -} -final case class `Access-Control-Request-Headers`(headers: immutable.Seq[String]) extends ModeledHeader { - import `Access-Control-Request-Headers`.headersRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ headers - protected def companion = `Access-Control-Request-Headers` -} - -// http://www.w3.org/TR/cors/#access-control-request-method-request-header -object `Access-Control-Request-Method` extends ModeledCompanion -final case class `Access-Control-Request-Method`(method: HttpMethod) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ method - protected def companion = `Access-Control-Request-Method` -} - -// http://tools.ietf.org/html/rfc7231#section-7.4.1 -object Allow extends ModeledCompanion { - def apply(methods: HttpMethod*): Allow = apply(immutable.Seq(methods: _*)) - private[http] implicit val methodsRenderer = Renderer.defaultSeqRenderer[HttpMethod] -} -final case class Allow(methods: immutable.Seq[HttpMethod]) extends ModeledHeader { - import Allow.methodsRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ methods - protected def companion = Allow -} - -// http://tools.ietf.org/html/rfc7235#section-4.2 -object Authorization extends ModeledCompanion -final case class Authorization(credentials: HttpCredentials) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ credentials - protected def companion = Authorization -} - -// http://tools.ietf.org/html/rfc7234#section-5.2 -object `Cache-Control` extends ModeledCompanion { - def apply(first: CacheDirective, more: CacheDirective*): `Cache-Control` = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val directivesRenderer = Renderer.defaultSeqRenderer[CacheDirective] // cache -} -final case class `Cache-Control`(directives: immutable.Seq[CacheDirective]) extends ModeledHeader { - require(directives.nonEmpty, "directives must not be empty") - import `Cache-Control`.directivesRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ directives - protected def companion = `Cache-Control` -} - -// http://tools.ietf.org/html/rfc7230#section-6.1 +// http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-26#section-6.1 object Connection extends ModeledCompanion { def apply(first: String, more: String*): Connection = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val tokensRenderer = Renderer.defaultSeqRenderer[String] // cache + implicit val tokensRenderer = Renderer.defaultSeqRenderer[String] // cache } final case class Connection(tokens: immutable.Seq[String]) extends ModeledHeader { require(tokens.nonEmpty, "tokens must not be empty") import Connection.tokensRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ tokens + def renderValue[R <: Rendering](r: R): r.type = r ~~ tokens def hasClose = has("close") def hasKeepAlive = has("keep-alive") @tailrec private def has(item: String, ix: Int = 0): Boolean = @@ -213,145 +54,46 @@ final case class Connection(tokens: immutable.Seq[String]) extends ModeledHeader protected def companion = Connection } -// http://tools.ietf.org/html/rfc6266 -object `Content-Disposition` extends ModeledCompanion -final case class `Content-Disposition`(dispositionType: ContentDispositionType, params: Map[String, String] = Map.empty) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = { - r ~~ dispositionType - params foreach { case (k, v) ⇒ r ~~ "; " ~~ k ~~ '=' ~~# v } - r - } - protected def companion = `Content-Disposition` -} - -// http://tools.ietf.org/html/rfc7231#section-3.1.2.2 -object `Content-Encoding` extends ModeledCompanion { - def apply(first: HttpEncoding, more: HttpEncoding*): `Content-Encoding` = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val encodingsRenderer = Renderer.defaultSeqRenderer[HttpEncoding] // cache -} -final case class `Content-Encoding`(encodings: immutable.Seq[HttpEncoding]) extends ModeledHeader { - require(encodings.nonEmpty, "encodings must not be empty") - import `Content-Encoding`.encodingsRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ encodings - protected def companion = `Content-Encoding` -} - -// http://tools.ietf.org/html/rfc7230#section-3.3.2 +// http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-26#section-3.3.2 object `Content-Length` extends ModeledCompanion -final case class `Content-Length`(length: Long)(implicit ev: AllowProtectedHeaderCreation.Enabled) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ length +final case class `Content-Length`(length: Long)(implicit ev: ProtectedHeaderCreation.Enabled) extends ModeledHeader { + def renderValue[R <: Rendering](r: R): r.type = r ~~ length protected def companion = `Content-Length` } -// http://tools.ietf.org/html/rfc7233#section-4.2 -object `Content-Range` extends ModeledCompanion { - def apply(byteContentRange: ByteContentRange): `Content-Range` = apply(RangeUnits.Bytes, byteContentRange) -} -final case class `Content-Range`(rangeUnit: RangeUnit, contentRange: ContentRange) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ rangeUnit ~~ ' ' ~~ contentRange - protected def companion = `Content-Range` -} - -// http://tools.ietf.org/html/rfc7231#section-3.1.1.5 -object `Content-Type` extends ModeledCompanion -final case class `Content-Type`(contentType: ContentType)(implicit ev: AllowProtectedHeaderCreation.Enabled) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ contentType - protected def companion = `Content-Type` -} - -// https://tools.ietf.org/html/rfc6265#section-4.2 -object Cookie extends ModeledCompanion { - def apply(first: HttpCookie, more: HttpCookie*): Cookie = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val cookieNameValueOnlyRenderer: Renderer[HttpCookie] = new Renderer[HttpCookie] { - def render[R <: Rendering](r: R, c: HttpCookie): r.type = r ~~ c.name ~~ '=' ~~ c.content - } - private[http] implicit val cookiesRenderer: Renderer[immutable.Seq[HttpCookie]] = Renderer.seqRenderer(separator = "; ") // cache -} -final case class Cookie(cookies: immutable.Seq[HttpCookie]) extends ModeledHeader { - import Cookie.cookiesRenderer - require(cookies.nonEmpty, "cookies must not be empty") - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ cookies - protected def companion = Cookie -} - -// http://tools.ietf.org/html/rfc7231#section-7.1.1.2 -object Date extends ModeledCompanion -final case class Date(date: DateTime)(implicit ev: AllowProtectedHeaderCreation.Enabled) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = date.renderRfc1123DateTimeString(r) - protected def companion = Date -} - -// http://tools.ietf.org/html/rfc7232#section-2.3 -object ETag extends ModeledCompanion { - def apply(tag: String, weak: Boolean = false): ETag = ETag(EntityTag(tag, weak)) -} -final case class ETag(etag: EntityTag) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ etag - protected def companion = ETag -} - -// http://tools.ietf.org/html/rfc7231#section-5.1.1 +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.1.1 object Expect extends ModeledCompanion { val `100-continue` = new Expect() {} } sealed abstract case class Expect private () extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ "100-continue" + def renderValue[R <: Rendering](r: R): r.type = r ~~ "100-continue" protected def companion = Expect } -// http://tools.ietf.org/html/rfc7230#section-5.4 +// http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-26#section-5.4 object Host extends ModeledCompanion { def apply(address: InetSocketAddress): Host = apply(address.getHostName, address.getPort) // TODO: upgrade to `getHostString` once we are on JDK7 def apply(host: String): Host = apply(host, 0) def apply(host: String, port: Int): Host = apply(Uri.Host(host), port) val empty = Host("") } -final case class Host(host: Uri.Host, port: Int = 0) extends ModeledHeader { +final case class Host(host: Uri.Host, port: Int = 0) extends japi.headers.Host with ModeledHeader { import UriRendering.HostRenderer require((port >> 16) == 0, "Illegal port: " + port) def isEmpty = host.isEmpty - def equalsIgnoreCase(other: Host): Boolean = host.equalsIgnoreCase(other.host) && port == other.port - protected[akka] def renderValue[R <: Rendering](r: R): r.type = if (port > 0) r ~~ host ~~ ':' ~~ port else r ~~ host + def renderValue[R <: Rendering](r: R): r.type = if (port > 0) r ~~ host ~~ ':' ~~ port else r ~~ host protected def companion = Host + def equalsIgnoreCase(other: Host): Boolean = host.equalsIgnoreCase(other.host) && port == other.port } -// http://tools.ietf.org/html/rfc7232#section-3.1 -object `If-Match` extends ModeledCompanion { - val `*` = `If-Match`(EntityTagRange.`*`) - def apply(first: EntityTag, more: EntityTag*): `If-Match` = - `If-Match`(EntityTagRange(first +: more: _*)) -} -final case class `If-Match`(m: EntityTagRange) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ m - protected def companion = `If-Match` -} - -// http://tools.ietf.org/html/rfc7232#section-3.3 -object `If-Modified-Since` extends ModeledCompanion -final case class `If-Modified-Since`(date: DateTime) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = date.renderRfc1123DateTimeString(r) - protected def companion = `If-Modified-Since` -} - -// http://tools.ietf.org/html/rfc7232#section-3.2 -object `If-None-Match` extends ModeledCompanion { - val `*` = `If-None-Match`(EntityTagRange.`*`) - def apply(first: EntityTag, more: EntityTag*): `If-None-Match` = - `If-None-Match`(EntityTagRange(first +: more: _*)) -} -final case class `If-None-Match`(m: EntityTagRange) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ m - protected def companion = `If-None-Match` -} - -// http://tools.ietf.org/html/rfc7232#section-3.5 -// http://tools.ietf.org/html/rfc7233#section-3.2 +// http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-3.5 +// http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-26#section-3.2 object `If-Range` extends ModeledCompanion { def apply(tag: EntityTag): `If-Range` = apply(Left(tag)) def apply(timestamp: DateTime): `If-Range` = apply(Right(timestamp)) } final case class `If-Range`(entityTagOrDateTime: Either[EntityTag, DateTime]) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = + def renderValue[R <: Rendering](r: R): r.type = entityTagOrDateTime match { case Left(tag) ⇒ r ~~ tag case Right(dateTime) ⇒ dateTime.renderRfc1123DateTimeString(r) @@ -359,169 +101,516 @@ final case class `If-Range`(entityTagOrDateTime: Either[EntityTag, DateTime]) ex protected def companion = `If-Range` } -// http://tools.ietf.org/html/rfc7232#section-3.4 +// FIXME: resurrect SSL-Session-Info header once akka.io.SslTlsSupport supports it +final case class RawHeader(name: String, value: String) extends japi.headers.RawHeader { + val lowercaseName = name.toLowerCase + def render[R <: Rendering](r: R): r.type = r ~~ name ~~ ':' ~~ ' ' ~~ value +} + +import japi.JavaMapping.Implicits._ + +// AUTO-GENERATED + +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.3.2 +object Accept extends ModeledCompanion { + def apply(mediaRanges: MediaRange*): Accept = apply(immutable.Seq(mediaRanges: _*)) + implicit val mediaRangesRenderer = Renderer.defaultSeqRenderer[MediaRange] // cache +} +final case class Accept(mediaRanges: immutable.Seq[MediaRange]) extends japi.headers.Accept with ModeledHeader { + import Accept.mediaRangesRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ mediaRanges + protected def companion = Accept + + /** Java API */ + def getMediaRanges = mediaRanges.asJava +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.3.3 +object `Accept-Charset` extends ModeledCompanion { + def apply(charsetRanges: HttpCharsetRange*): `Accept-Charset` = apply(immutable.Seq(charsetRanges: _*)) + implicit val charsetRangesRenderer = Renderer.defaultSeqRenderer[HttpCharsetRange] // cache +} +final case class `Accept-Charset`(charsetRanges: immutable.Seq[HttpCharsetRange]) extends japi.headers.AcceptCharset with ModeledHeader { + import `Accept-Charset`.charsetRangesRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ charsetRanges + protected def companion = `Accept-Charset` + + /** Java API */ + def getCharsetRanges = charsetRanges.asJava +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.3.4 +object `Accept-Encoding` extends ModeledCompanion { + def apply(encodings: HttpEncodingRange*): `Accept-Encoding` = apply(immutable.Seq(encodings: _*)) + implicit val encodingsRenderer = Renderer.defaultSeqRenderer[HttpEncodingRange] // cache +} +final case class `Accept-Encoding`(encodings: immutable.Seq[HttpEncodingRange]) extends japi.headers.AcceptEncoding with ModeledHeader { + import `Accept-Encoding`.encodingsRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ encodings + protected def companion = `Accept-Encoding` + + /** Java API */ + def getEncodings = encodings.asJava +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.3.5 +object `Accept-Language` extends ModeledCompanion { + def apply(languages: LanguageRange*): `Accept-Language` = apply(immutable.Seq(languages: _*)) + implicit val languagesRenderer = Renderer.defaultSeqRenderer[LanguageRange] // cache +} +final case class `Accept-Language`(languages: immutable.Seq[LanguageRange]) extends japi.headers.AcceptLanguage with ModeledHeader { + import `Accept-Language`.languagesRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ languages + protected def companion = `Accept-Language` + + /** Java API */ + def getLanguages = languages.asJava +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-26#section-2.3 +object `Accept-Ranges` extends ModeledCompanion { + def apply(rangeUnits: RangeUnit*): `Accept-Ranges` = apply(immutable.Seq(rangeUnits: _*)) + implicit val rangeUnitsRenderer = Renderer.defaultSeqRenderer[RangeUnit] // cache +} +final case class `Accept-Ranges`(rangeUnits: immutable.Seq[RangeUnit]) extends japi.headers.AcceptRanges with ModeledHeader { + import `Accept-Ranges`.rangeUnitsRenderer + def renderValue[R <: Rendering](r: R): r.type = if (rangeUnits.isEmpty) r ~~ "none" else r ~~ rangeUnits + protected def companion = `Accept-Ranges` + + /** Java API */ + def getRangeUnits = rangeUnits.asJava +} + +// http://www.w3.org/TR/cors/#access-control-allow-credentials-response-header +object `Access-Control-Allow-Credentials` extends ModeledCompanion +final case class `Access-Control-Allow-Credentials`(allow: Boolean) extends japi.headers.AccessControlAllowCredentials with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ allow.toString + protected def companion = `Access-Control-Allow-Credentials` +} + +// http://www.w3.org/TR/cors/#access-control-allow-headers-response-header +object `Access-Control-Allow-Headers` extends ModeledCompanion { + def apply(headers: String*): `Access-Control-Allow-Headers` = apply(immutable.Seq(headers: _*)) + implicit val headersRenderer = Renderer.defaultSeqRenderer[String] // cache +} +final case class `Access-Control-Allow-Headers`(headers: immutable.Seq[String]) extends japi.headers.AccessControlAllowHeaders with ModeledHeader { + import `Access-Control-Allow-Headers`.headersRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ headers + protected def companion = `Access-Control-Allow-Headers` + + /** Java API */ + def getHeaders = headers.asJava +} + +// http://www.w3.org/TR/cors/#access-control-allow-methods-response-header +object `Access-Control-Allow-Methods` extends ModeledCompanion { + def apply(methods: HttpMethod*): `Access-Control-Allow-Methods` = apply(immutable.Seq(methods: _*)) + implicit val methodsRenderer = Renderer.defaultSeqRenderer[HttpMethod] // cache +} +final case class `Access-Control-Allow-Methods`(methods: immutable.Seq[HttpMethod]) extends japi.headers.AccessControlAllowMethods with ModeledHeader { + import `Access-Control-Allow-Methods`.methodsRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ methods + protected def companion = `Access-Control-Allow-Methods` + + /** Java API */ + def getMethods = methods.asJava +} + +// http://www.w3.org/TR/cors/#access-control-allow-origin-response-header +object `Access-Control-Allow-Origin` extends ModeledCompanion +final case class `Access-Control-Allow-Origin`(range: HttpOriginRange) extends japi.headers.AccessControlAllowOrigin with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ range + protected def companion = `Access-Control-Allow-Origin` +} + +// http://www.w3.org/TR/cors/#access-control-expose-headers-response-header +object `Access-Control-Expose-Headers` extends ModeledCompanion { + def apply(headers: String*): `Access-Control-Expose-Headers` = apply(immutable.Seq(headers: _*)) + implicit val headersRenderer = Renderer.defaultSeqRenderer[String] // cache +} +final case class `Access-Control-Expose-Headers`(headers: immutable.Seq[String]) extends japi.headers.AccessControlExposeHeaders with ModeledHeader { + import `Access-Control-Expose-Headers`.headersRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ headers + protected def companion = `Access-Control-Expose-Headers` + + /** Java API */ + def getHeaders = headers.asJava +} + +// http://www.w3.org/TR/cors/#access-control-max-age-response-header +object `Access-Control-Max-Age` extends ModeledCompanion +final case class `Access-Control-Max-Age`(deltaSeconds: Long) extends japi.headers.AccessControlMaxAge with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ deltaSeconds + protected def companion = `Access-Control-Max-Age` +} + +// http://www.w3.org/TR/cors/#access-control-request-headers-request-header +object `Access-Control-Request-Headers` extends ModeledCompanion { + def apply(headers: String*): `Access-Control-Request-Headers` = apply(immutable.Seq(headers: _*)) + implicit val headersRenderer = Renderer.defaultSeqRenderer[String] // cache +} +final case class `Access-Control-Request-Headers`(headers: immutable.Seq[String]) extends japi.headers.AccessControlRequestHeaders with ModeledHeader { + import `Access-Control-Request-Headers`.headersRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ headers + protected def companion = `Access-Control-Request-Headers` + + /** Java API */ + def getHeaders = headers.asJava +} + +// http://www.w3.org/TR/cors/#access-control-request-method-request-header +object `Access-Control-Request-Method` extends ModeledCompanion +final case class `Access-Control-Request-Method`(method: HttpMethod) extends japi.headers.AccessControlRequestMethod with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ method + protected def companion = `Access-Control-Request-Method` +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-7.4.1 +object Allow extends ModeledCompanion { + def apply(methods: HttpMethod*): Allow = apply(immutable.Seq(methods: _*)) + implicit val methodsRenderer = Renderer.defaultSeqRenderer[HttpMethod] // cache +} +final case class Allow(methods: immutable.Seq[HttpMethod]) extends japi.headers.Allow with ModeledHeader { + import Allow.methodsRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ methods + protected def companion = Allow + + /** Java API */ + def getMethods = methods.asJava +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p7-auth-26#section-4.2 +object Authorization extends ModeledCompanion +final case class Authorization(credentials: HttpCredentials) extends japi.headers.Authorization with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ credentials + protected def companion = Authorization +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-26#section-5.2 +object `Cache-Control` extends ModeledCompanion { + def apply(directives: CacheDirective*): `Cache-Control` = apply(immutable.Seq(directives: _*)) + implicit val directivesRenderer = Renderer.defaultSeqRenderer[CacheDirective] // cache +} +final case class `Cache-Control`(directives: immutable.Seq[CacheDirective]) extends japi.headers.CacheControl with ModeledHeader { + import `Cache-Control`.directivesRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ directives + protected def companion = `Cache-Control` + + /** Java API */ + def getDirectives = directives.asJava +} + +// http://tools.ietf.org/html/rfc6266 +object `Content-Disposition` extends ModeledCompanion +final case class `Content-Disposition`(dispositionType: ContentDispositionType, params: Map[String, String] = Map.empty) extends japi.headers.ContentDisposition with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = { r ~~ dispositionType; params foreach { case (k, v) ⇒ r ~~ "; " ~~ k ~~ '=' ~~# v }; r } + protected def companion = `Content-Disposition` + + /** Java API */ + def getParams = params.asJava +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-3.1.2.2 +object `Content-Encoding` extends ModeledCompanion { + def apply(encodings: HttpEncoding*): `Content-Encoding` = apply(immutable.Seq(encodings: _*)) + implicit val encodingsRenderer = Renderer.defaultSeqRenderer[HttpEncoding] // cache +} +final case class `Content-Encoding`(encodings: immutable.Seq[HttpEncoding]) extends japi.headers.ContentEncoding with ModeledHeader { + import `Content-Encoding`.encodingsRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ encodings + protected def companion = `Content-Encoding` + + /** Java API */ + def getEncodings = encodings.asJava +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-26#section-4.2 +object `Content-Range` extends ModeledCompanion { + def apply(byteContentRange: ByteContentRange): `Content-Range` = apply(RangeUnits.Bytes, byteContentRange) + +} +final case class `Content-Range`(rangeUnit: RangeUnit, contentRange: ContentRange) extends japi.headers.ContentRange with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ rangeUnit ~~ ' ' ~~ contentRange + protected def companion = `Content-Range` +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-3.1.1.5 +object `Content-Type` extends ModeledCompanion +final case class `Content-Type`(contentType: ContentType) extends japi.headers.ContentType with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ contentType + protected def companion = `Content-Type` +} + +// https://tools.ietf.org/html/rfc6265#section-4.2 +object Cookie extends ModeledCompanion { + implicit val cookieNameValueOnlyRenderer: Renderer[HttpCookie] = new Renderer[HttpCookie] { + def render[R <: Rendering](r: R, c: HttpCookie): r.type = r ~~ c.name ~~ '=' ~~ c.content + } + + def apply(cookies: HttpCookie*): Cookie = apply(immutable.Seq(cookies: _*)) + implicit val cookiesRenderer = Renderer.seqRenderer[HttpCookie](separator = "; ") // cache +} +final case class Cookie(cookies: immutable.Seq[HttpCookie]) extends japi.headers.Cookie with ModeledHeader { + import Cookie.cookiesRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ cookies + protected def companion = Cookie + + /** Java API */ + def getCookies = cookies.asJava +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-7.1.1.2 +object Date extends ModeledCompanion +final case class Date(date: DateTime) extends japi.headers.Date with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = date.renderRfc1123DateTimeString(r) + protected def companion = Date +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-2.3 +object ETag extends ModeledCompanion { + def apply(tag: String, weak: Boolean = false): ETag = ETag(EntityTag(tag, weak)) + +} +final case class ETag(etag: EntityTag) extends japi.headers.ETag with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ etag + protected def companion = ETag +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-3.1 +object `If-Match` extends ModeledCompanion { + val `*` = `If-Match`(EntityTagRange.`*`) + def apply(first: EntityTag, more: EntityTag*): `If-Match` = + `If-Match`(EntityTagRange(first +: more: _*)) + +} +final case class `If-Match`(m: EntityTagRange) extends japi.headers.IfMatch with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ m + protected def companion = `If-Match` +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-3.3 +object `If-Modified-Since` extends ModeledCompanion +final case class `If-Modified-Since`(date: DateTime) extends japi.headers.IfModifiedSince with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = date.renderRfc1123DateTimeString(r) + protected def companion = `If-Modified-Since` +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-3.2 +object `If-None-Match` extends ModeledCompanion { + val `*` = `If-None-Match`(EntityTagRange.`*`) + def apply(first: EntityTag, more: EntityTag*): `If-None-Match` = + `If-None-Match`(EntityTagRange(first +: more: _*)) + +} +final case class `If-None-Match`(m: EntityTagRange) extends japi.headers.IfNoneMatch with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ m + protected def companion = `If-None-Match` +} + +// http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-3.4 object `If-Unmodified-Since` extends ModeledCompanion -final case class `If-Unmodified-Since`(date: DateTime) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = date.renderRfc1123DateTimeString(r) +final case class `If-Unmodified-Since`(date: DateTime) extends japi.headers.IfUnmodifiedSince with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = date.renderRfc1123DateTimeString(r) protected def companion = `If-Unmodified-Since` } -// http://tools.ietf.org/html/rfc7232#section-2.2 +// http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-2.2 object `Last-Modified` extends ModeledCompanion -final case class `Last-Modified`(date: DateTime) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = date.renderRfc1123DateTimeString(r) +final case class `Last-Modified`(date: DateTime) extends japi.headers.LastModified with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = date.renderRfc1123DateTimeString(r) protected def companion = `Last-Modified` } // http://tools.ietf.org/html/rfc5988#section-5 object Link extends ModeledCompanion { def apply(uri: Uri, first: LinkParam, more: LinkParam*): Link = apply(immutable.Seq(LinkValue(uri, first +: more: _*))) + def apply(values: LinkValue*): Link = apply(immutable.Seq(values: _*)) - private[http] implicit val valuesRenderer = Renderer.defaultSeqRenderer[LinkValue] + implicit val valuesRenderer = Renderer.defaultSeqRenderer[LinkValue] // cache } -final case class Link(values: immutable.Seq[LinkValue]) extends ModeledHeader { +final case class Link(values: immutable.Seq[LinkValue]) extends japi.headers.Link with ModeledHeader { import Link.valuesRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ values + def renderValue[R <: Rendering](r: R): r.type = r ~~ values protected def companion = Link + + /** Java API */ + def getValues = values.asJava } -// http://tools.ietf.org/html/rfc7231#section-7.1.2 +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-7.1.2 object Location extends ModeledCompanion -final case class Location(uri: Uri) extends ModeledHeader { - import UriRendering.UriRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ uri +final case class Location(uri: Uri) extends japi.headers.Location with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = { import UriRendering.UriRenderer; r ~~ uri } protected def companion = Location + + /** Java API */ + def getUri = uri.asJava } // http://tools.ietf.org/html/rfc6454#section-7 object Origin extends ModeledCompanion { - def apply(first: HttpOrigin, more: HttpOrigin*): Origin = apply(immutable.Seq(first +: more: _*)) + def apply(origins: HttpOrigin*): Origin = apply(immutable.Seq(origins: _*)) } -final case class Origin(origins: immutable.Seq[HttpOrigin]) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ origins +final case class Origin(origins: immutable.Seq[HttpOrigin]) extends japi.headers.Origin with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ origins protected def companion = Origin + + /** Java API */ + def getOrigins = origins.asJava } -// http://tools.ietf.org/html/rfc7233#section-3.1 -object Range extends ModeledCompanion { - def apply(first: ByteRange, more: ByteRange*): Range = apply(immutable.Seq(first +: more: _*)) - def apply(ranges: immutable.Seq[ByteRange]): Range = Range(RangeUnits.Bytes, ranges) - private[http] implicit val rangesRenderer = Renderer.defaultSeqRenderer[ByteRange] // cache -} -final case class Range(rangeUnit: RangeUnit, ranges: immutable.Seq[ByteRange]) extends ModeledHeader { - import Range.rangesRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ rangeUnit ~~ '=' ~~ ranges - protected def companion = Range -} - -// http://tools.ietf.org/html/rfc7235#section-4.3 +// http://tools.ietf.org/html/draft-ietf-httpbis-p7-auth-26#section-4.3 object `Proxy-Authenticate` extends ModeledCompanion { - def apply(first: HttpChallenge, more: HttpChallenge*): `Proxy-Authenticate` = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val challengesRenderer = Renderer.defaultSeqRenderer[HttpChallenge] // cache + def apply(challenges: HttpChallenge*): `Proxy-Authenticate` = apply(immutable.Seq(challenges: _*)) + implicit val challengesRenderer = Renderer.defaultSeqRenderer[HttpChallenge] // cache } -final case class `Proxy-Authenticate`(challenges: immutable.Seq[HttpChallenge]) extends ModeledHeader { - require(challenges.nonEmpty, "challenges must not be empty") +final case class `Proxy-Authenticate`(challenges: immutable.Seq[HttpChallenge]) extends japi.headers.ProxyAuthenticate with ModeledHeader { import `Proxy-Authenticate`.challengesRenderer - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ challenges + def renderValue[R <: Rendering](r: R): r.type = r ~~ challenges protected def companion = `Proxy-Authenticate` + + /** Java API */ + def getChallenges = challenges.asJava } -// http://tools.ietf.org/html/rfc7235#section-4.4 +// http://tools.ietf.org/html/draft-ietf-httpbis-p7-auth-26#section-4.4 object `Proxy-Authorization` extends ModeledCompanion -final case class `Proxy-Authorization`(credentials: HttpCredentials) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ credentials +final case class `Proxy-Authorization`(credentials: HttpCredentials) extends japi.headers.ProxyAuthorization with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ credentials protected def companion = `Proxy-Authorization` } -// custom header we use for transporting the raw request URI either to the application (server-side) -// or to the request rendering stage (client-side) +// http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-26#section-3.1 +object Range extends ModeledCompanion { + def apply(first: ByteRange, more: ByteRange*): Range = apply(immutable.Seq(first +: more: _*)) + def apply(ranges: immutable.Seq[ByteRange]): Range = Range(RangeUnits.Bytes, ranges) + + implicit val rangesRenderer = Renderer.defaultSeqRenderer[ByteRange] // cache +} +final case class Range(rangeUnit: RangeUnit, ranges: immutable.Seq[ByteRange]) extends japi.headers.Range with ModeledHeader { + import Range.rangesRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ rangeUnit ~~ '=' ~~ ranges + protected def companion = Range + + /** Java API */ + def getRanges = ranges.asJava +} + object `Raw-Request-URI` extends ModeledCompanion -final case class `Raw-Request-URI`(uri: String) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ uri +final case class `Raw-Request-URI`(uri: String) extends japi.headers.RawRequestURI with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ uri protected def companion = `Raw-Request-URI` } -// custom header we use for optionally transporting the peer's IP in an HTTP header -object `Remote-Address` extends ModeledCompanion { - def apply(address: String): `Remote-Address` = apply(RemoteAddress(address)) -} -final case class `Remote-Address`(address: RemoteAddress) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ address +object `Remote-Address` extends ModeledCompanion +final case class `Remote-Address`(address: RemoteAddress) extends japi.headers.RemoteAddress with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ address protected def companion = `Remote-Address` } -// http://tools.ietf.org/html/rfc7231#section-7.4.2 +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-7.4.2 object Server extends ModeledCompanion { def apply(products: String): Server = apply(ProductVersion.parseMultiple(products)) - def apply(first: ProductVersion, more: ProductVersion*): Server = apply(immutable.Seq(first +: more: _*)) + + def apply(products: ProductVersion*): Server = apply(immutable.Seq(products: _*)) + implicit val productsRenderer = Renderer.seqRenderer[ProductVersion](separator = " ") // cache } -final case class Server(products: immutable.Seq[ProductVersion])(implicit ev: AllowProtectedHeaderCreation.Enabled) extends ModeledHeader { - require(products.nonEmpty, "products must not be empty") - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ products +final case class Server(products: immutable.Seq[ProductVersion]) extends japi.headers.Server with ModeledHeader { + import Server.productsRenderer + def renderValue[R <: Rendering](r: R): r.type = r ~~ products protected def companion = Server + + /** Java API */ + def getProducts = products.asJava } // https://tools.ietf.org/html/rfc6265 object `Set-Cookie` extends ModeledCompanion -final case class `Set-Cookie`(cookie: HttpCookie) extends ModeledHeader { - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ cookie +final case class `Set-Cookie`(cookie: HttpCookie) extends japi.headers.SetCookie with ModeledHeader { + + def renderValue[R <: Rendering](r: R): r.type = r ~~ cookie protected def companion = `Set-Cookie` } -// http://tools.ietf.org/html/rfc7230#section-3.3.1 +// http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-26#section-3.3.1 object `Transfer-Encoding` extends ModeledCompanion { - def apply(first: TransferEncoding, more: TransferEncoding*): `Transfer-Encoding` = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val encodingsRenderer = Renderer.defaultSeqRenderer[TransferEncoding] // cache + def apply(encodings: TransferEncoding*): `Transfer-Encoding` = apply(immutable.Seq(encodings: _*)) + implicit val encodingsRenderer = Renderer.defaultSeqRenderer[TransferEncoding] // cache } -final case class `Transfer-Encoding`(encodings: immutable.Seq[TransferEncoding])(implicit ev: AllowProtectedHeaderCreation.Enabled) extends ModeledHeader { +final case class `Transfer-Encoding`(encodings: immutable.Seq[TransferEncoding]) extends japi.headers.TransferEncoding with ModeledHeader { import `Transfer-Encoding`.encodingsRenderer - require(encodings.nonEmpty, "encodings must not be empty") def hasChunked: Boolean = encodings contains TransferEncodings.chunked - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ encodings + def renderValue[R <: Rendering](r: R): r.type = r ~~ encodings protected def companion = `Transfer-Encoding` + + /** Java API */ + def getEncodings = encodings.asJava } -// http://tools.ietf.org/html/rfc7231#section-5.5.3 +// http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-26#section-5.5.3 object `User-Agent` extends ModeledCompanion { def apply(products: String): `User-Agent` = apply(ProductVersion.parseMultiple(products)) - def apply(first: ProductVersion, more: ProductVersion*): `User-Agent` = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val productsRenderer = Renderer.seqRenderer[String](separator = " ") // cache + + def apply(products: ProductVersion*): `User-Agent` = apply(immutable.Seq(products: _*)) + implicit val productsRenderer = Renderer.seqRenderer[ProductVersion](separator = " ") // cache } -final case class `User-Agent`(products: immutable.Seq[ProductVersion])(implicit ev: AllowProtectedHeaderCreation.Enabled) extends ModeledHeader { +final case class `User-Agent`(products: immutable.Seq[ProductVersion]) extends japi.headers.UserAgent with ModeledHeader { import `User-Agent`.productsRenderer - require(products.nonEmpty, "products must not be empty") - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ products + def renderValue[R <: Rendering](r: R): r.type = r ~~ products protected def companion = `User-Agent` + + /** Java API */ + def getProducts = products.asJava } -// http://tools.ietf.org/html/rfc7235#section-4.1 +// http://tools.ietf.org/html/draft-ietf-httpbis-p7-auth-26#section-4.1 object `WWW-Authenticate` extends ModeledCompanion { - def apply(first: HttpChallenge, more: HttpChallenge*): `WWW-Authenticate` = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val challengesRenderer = Renderer.defaultSeqRenderer[HttpChallenge] // cache + def apply(challenges: HttpChallenge*): `WWW-Authenticate` = apply(immutable.Seq(challenges: _*)) + implicit val challengesRenderer = Renderer.defaultSeqRenderer[HttpChallenge] // cache } -final case class `WWW-Authenticate`(challenges: immutable.Seq[HttpChallenge]) extends ModeledHeader { +final case class `WWW-Authenticate`(challenges: immutable.Seq[HttpChallenge]) extends japi.headers.WWWAuthenticate with ModeledHeader { import `WWW-Authenticate`.challengesRenderer - require(challenges.nonEmpty, "challenges must not be empty") - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ challenges + def renderValue[R <: Rendering](r: R): r.type = r ~~ challenges protected def companion = `WWW-Authenticate` + + /** Java API */ + def getChallenges = challenges.asJava } // http://en.wikipedia.org/wiki/X-Forwarded-For object `X-Forwarded-For` extends ModeledCompanion { def apply(first: String, more: String*): `X-Forwarded-For` = apply(immutable.Seq((first +: more).map(RemoteAddress.apply): _*)) - def apply(first: RemoteAddress, more: RemoteAddress*): `X-Forwarded-For` = apply(immutable.Seq(first +: more: _*)) - private[http] implicit val addressesRenderer = Renderer.defaultSeqRenderer[RemoteAddress] + + def apply(addresses: RemoteAddress*): `X-Forwarded-For` = apply(immutable.Seq(addresses: _*)) + implicit val addressesRenderer = Renderer.defaultSeqRenderer[RemoteAddress] // cache } -final case class `X-Forwarded-For`(addresses: immutable.Seq[RemoteAddress]) extends ModeledHeader { +final case class `X-Forwarded-For`(addresses: immutable.Seq[RemoteAddress]) extends japi.headers.XForwardedFor with ModeledHeader { import `X-Forwarded-For`.addressesRenderer - require(addresses.nonEmpty, "addresses must not be empty") - protected def renderValue[R <: Rendering](r: R): r.type = r ~~ addresses + def renderValue[R <: Rendering](r: R): r.type = r ~~ addresses protected def companion = `X-Forwarded-For` + + /** Java API */ + def getAddresses = addresses.asJava } -// FIXME: resurrect SSL-Session-Info header once akka.io.SslTlsSupport supports it -final case class RawHeader(name: String, value: String) extends HttpHeader { - val lowercaseName = name.toLowerCase - def render[R <: Rendering](r: R): r.type = r ~~ name ~~ ':' ~~ ' ' ~~ value -} diff --git a/akka-http-core/src/main/scala/akka/http/model/japi/Accessors.scala b/akka-http-core/src/main/scala/akka/http/model/japi/Accessors.scala new file mode 100644 index 0000000000..2a720755c8 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/model/japi/Accessors.scala @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi + +import akka.http.{ HttpExt, model } +import akka.actor.ActorSystem +import java.net.InetSocketAddress + +/** + * INTERNAL API + * + * Accessors for constructors with default arguments to be used from the Java implementation + */ +private[http] object Accessors { + /** INTERNAL API */ + private[http] def HttpRequest(): HttpRequest = model.HttpRequest() + /** INTERNAL API */ + private[http] def HttpResponse(): HttpResponse = model.HttpResponse() + + /** INTERNAL API */ + private[http] def Uri(uri: model.Uri): Uri = JavaUri(uri) + /** INTERNAL API */ + private[http] def Bind(host: String, port: Int): AnyRef = akka.http.Http.Bind(host, port) +} diff --git a/akka-http-core/src/main/scala/akka/http/model/japi/JavaMapping.scala b/akka-http-core/src/main/scala/akka/http/model/japi/JavaMapping.scala new file mode 100644 index 0000000000..a75f8b31b9 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/model/japi/JavaMapping.scala @@ -0,0 +1,158 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi + +import scala.collection.immutable +import scala.reflect.ClassTag + +import akka.http.model +import java.{ util ⇒ ju, lang ⇒ jl } +import akka.japi +import java.net.InetAddress + +/** INTERNAL API */ +trait J2SMapping[J] { + type S + def toScala(javaObject: J): S +} +/** INTERNAL API */ +object J2SMapping { + implicit def fromJavaMapping[J](implicit mapping: JavaMapping[J, _]): J2SMapping[J] { type S = mapping.S } = mapping + + implicit def seqMapping[J](implicit mapping: J2SMapping[J]): J2SMapping[Seq[J]] { type S = immutable.Seq[mapping.S] } = + new J2SMapping[Seq[J]] { + type S = immutable.Seq[mapping.S] + def toScala(javaObject: Seq[J]): S = javaObject.map(mapping.toScala(_)).toList + } +} +/** INTERNAL API */ +trait S2JMapping[S] { + type J + def toJava(scalaObject: S): J +} +/** INTERNAL API */ +object S2JMapping { + implicit def fromJavaMapping[S](implicit mapping: JavaMapping[_, S]): S2JMapping[S] { type J = mapping.J } = mapping +} + +/** INTERNAL API */ +trait JavaMapping[_J, _S] extends J2SMapping[_J] with S2JMapping[_S] { + type J = _J + type S = _S +} +/** INTERNAL API */ +object JavaMapping { + trait AsScala[S] { + def asScala: S + } + trait AsJava[J] { + def asJava: J + } + + object Implicits { + import scala.language.implicitConversions + + implicit def convertToScala[J](j: J)(implicit mapping: J2SMapping[J]): mapping.S = mapping.toScala(j) + implicit def convertSeqToScala[J](j: Seq[J])(implicit mapping: J2SMapping[J]): immutable.Seq[mapping.S] = + j.map(mapping.toScala(_)).toList + + implicit def AddAsScala[J](javaObject: J)(implicit mapping: J2SMapping[J]): AsScala[mapping.S] = new AsScala[mapping.S] { + def asScala = convertToScala(javaObject) + } + implicit def AddAsJava[S](scalaObject: S)(implicit mapping: S2JMapping[S]): AsJava[mapping.J] = new AsJava[mapping.J] { + def asJava = mapping.toJava(scalaObject) + } + } + + implicit def iterableMapping[_J, _S](implicit mapping: JavaMapping[_J, _S]): JavaMapping[jl.Iterable[_J], immutable.Seq[_S]] = + new JavaMapping[jl.Iterable[_J], immutable.Seq[_S]] { + import collection.JavaConverters._ + + def toJava(scalaObject: immutable.Seq[_S]): jl.Iterable[_J] = scalaObject.map(mapping.toJava(_)).asJavaCollection + def toScala(javaObject: jl.Iterable[_J]): immutable.Seq[_S] = + Implicits.convertSeqToScala(iterableAsScalaIterableConverter(javaObject).asScala.toSeq) + } + implicit def map[K, V]: JavaMapping[ju.Map[K, V], immutable.Map[K, V]] = + new JavaMapping[ju.Map[K, V], immutable.Map[K, V]] { + import scala.collection.JavaConverters._ + def toScala(javaObject: ju.Map[K, V]): immutable.Map[K, V] = javaObject.asScala.toMap + def toJava(scalaObject: immutable.Map[K, V]): ju.Map[K, V] = scalaObject.asJava + } + implicit def option[_J, _S](implicit mapping: JavaMapping[_J, _S]): JavaMapping[akka.japi.Option[_J], Option[_S]] = + new JavaMapping[akka.japi.Option[_J], Option[_S]] { + def toScala(javaObject: japi.Option[_J]): Option[_S] = javaObject.asScala.map(mapping.toScala(_)) + def toJava(scalaObject: Option[_S]): japi.Option[_J] = japi.Option.fromScalaOption(scalaObject.map(mapping.toJava(_))) + } + + implicit object StringIdentity extends Identity[String] + + implicit object LongMapping extends JavaMapping[jl.Long, Long] { + def toScala(javaObject: jl.Long): Long = javaObject + def toJava(scalaObject: Long): jl.Long = scalaObject + } + implicit object InetAddressIdentity extends Identity[InetAddress] + + class Identity[T] extends JavaMapping[T, T] { + def toScala(javaObject: T): T = javaObject + def toJava(scalaObject: T): T = scalaObject + } + class Inherited[J <: AnyRef, S <: J](implicit classTag: ClassTag[S]) extends JavaMapping[J, S] { + def toJava(scalaObject: S): J = scalaObject + def toScala(javaObject: J): S = cast[S](javaObject) + } + + implicit object DateTime extends Inherited[DateTime, akka.http.util.DateTime] + + implicit object ContentType extends Inherited[ContentType, model.ContentType] + implicit object Host extends Inherited[Host, model.Uri.Host] + implicit object HttpCharset extends Inherited[HttpCharset, model.HttpCharset] + implicit object HttpCharsetRange extends Inherited[HttpCharsetRange, model.HttpCharsetRange] + implicit object HttpEntity extends Inherited[HttpEntity, model.HttpEntity] + implicit object HttpEntityRegular extends Inherited[HttpEntityRegular, model.HttpEntity.Regular] + implicit object HttpHeader extends Inherited[HttpHeader, model.HttpHeader] + implicit object HttpMethod extends Inherited[HttpMethod, model.HttpMethod] + implicit object HttpProtocol extends Inherited[HttpProtocol, model.HttpProtocol] + implicit object HttpRequest extends Inherited[HttpRequest, model.HttpRequest] + implicit object HttpResponse extends Inherited[HttpResponse, model.HttpResponse] + implicit object MediaRange extends Inherited[MediaRange, model.MediaRange] + implicit object MediaType extends Inherited[MediaType, model.MediaType] + implicit object StatusCode extends Inherited[StatusCode, model.StatusCode] + + implicit object ContentRange extends Inherited[ContentRange, model.ContentRange] + implicit object RemoteAddress extends Inherited[RemoteAddress, model.RemoteAddress] + implicit object TransferEncoding extends Inherited[TransferEncoding, model.TransferEncoding] + + implicit object ByteRange extends Inherited[headers.ByteRange, model.headers.ByteRange] + implicit object CacheDirective extends Inherited[headers.CacheDirective, model.headers.CacheDirective] + implicit object ContentDispositionType extends Inherited[headers.ContentDispositionType, model.headers.ContentDispositionType] + implicit object EntityTag extends Inherited[headers.EntityTag, model.headers.EntityTag] + implicit object EntityTagRange extends Inherited[headers.EntityTagRange, model.headers.EntityTagRange] + implicit object HttpChallenge extends Inherited[headers.HttpChallenge, model.headers.HttpChallenge] + implicit object HttpCookie extends Inherited[headers.HttpCookie, model.headers.HttpCookie] + implicit object HttpCredentials extends Inherited[headers.HttpCredentials, model.headers.HttpCredentials] + implicit object HttpEncoding extends Inherited[headers.HttpEncoding, model.headers.HttpEncoding] + implicit object HttpEncodingRange extends Inherited[headers.HttpEncodingRange, model.headers.HttpEncodingRange] + implicit object HttpOrigin extends Inherited[headers.HttpOrigin, model.headers.HttpOrigin] + implicit object HttpOriginRange extends Inherited[headers.HttpOriginRange, model.headers.HttpOriginRange] + implicit object Language extends Inherited[headers.Language, model.headers.Language] + implicit object LanguageRange extends Inherited[headers.LanguageRange, model.headers.LanguageRange] + implicit object LinkParam extends Inherited[headers.LinkParam, model.headers.LinkParam] + implicit object LinkValue extends Inherited[headers.LinkValue, model.headers.LinkValue] + implicit object ProductVersion extends Inherited[headers.ProductVersion, model.headers.ProductVersion] + implicit object RangeUnit extends Inherited[headers.RangeUnit, model.headers.RangeUnit] + + implicit object Uri extends JavaMapping[Uri, model.Uri] { + def toScala(javaObject: Uri): Uri.S = cast[JavaUri](javaObject).uri + def toJava(scalaObject: model.Uri): Uri.J = Accessors.Uri(scalaObject) + } + + private def cast[T](obj: AnyRef)(implicit classTag: ClassTag[T]): T = + try classTag.runtimeClass.cast(obj).asInstanceOf[T] + catch { + case exp: ClassCastException ⇒ + throw new IllegalArgumentException(s"Illegal custom subclass of $classTag. " + + s"Please use only the provided factories in akka.http.model.japi.Http") + } +} diff --git a/akka-http-core/src/main/scala/akka/http/model/japi/JavaUri.scala b/akka-http-core/src/main/scala/akka/http/model/japi/JavaUri.scala new file mode 100644 index 0000000000..050668f2b6 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/model/japi/JavaUri.scala @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi + +import java.{ util ⇒ ju, lang ⇒ jl } + +import akka.http.model +import akka.japi.Option +import scala.annotation.tailrec + +import JavaMapping.Implicits._ + +/** INTERNAL API */ +protected[model] case class JavaUri(uri: model.Uri) extends Uri { + def isRelative: Boolean = uri.isRelative + def isAbsolute: Boolean = uri.isAbsolute + def isEmpty: Boolean = uri.isEmpty + + def scheme(): String = uri.scheme + def host(): Host = uri.authority.host + def port(): Int = uri.authority.port + def userInfo(): String = uri.authority.userinfo + + def path(): String = uri.path.toString + + import collection.JavaConverters._ + def pathSegments(): jl.Iterable[String] = { + import model.Uri.Path + import Path._ + def gatherSegments(path: Path): List[String] = path match { + case Empty ⇒ Nil + case Segment(head, tail) ⇒ head :: gatherSegments(tail) + case Slash(tail) ⇒ gatherSegments(tail) + } + gatherSegments(uri.path).asJava + } + + def queryString(): String = uri.query.toString + + def parameterMap(): ju.Map[String, String] = uri.query.toMap.asJava + def parameters(): jl.Iterable[Uri.Parameter] = uri.query.map(t ⇒ Param(t._1, t._2): Uri.Parameter).toIterable.asJava + def containsParameter(key: String): Boolean = uri.query.get(key).isDefined + def parameter(key: String): Option[String] = uri.query.get(key) + + case class Param(key: String, value: String) extends Uri.Parameter + + def fragment: Option[String] = uri.fragment + + // Modification methods + + def t(f: model.Uri ⇒ model.Uri): Uri = JavaUri(f(uri)) + + def scheme(scheme: String): Uri = t(_.withScheme(scheme)) + + def host(host: Host): Uri = t(_.withHost(host.asScala)) + def host(host: String): Uri = t(_.withHost(host)) + def port(port: Int): Uri = t(_.withPort(port)) + def userInfo(userInfo: String): Uri = t(_.withUserInfo(userInfo)) + + def path(path: String): Uri = t(_.withPath(model.Uri.Path(path))) + + def toRelative: Uri = t(_.toRelative) + + def query(query: String): Uri = t(_.withQuery(query)) + def addParameter(key: String, value: String): Uri = t { u ⇒ + u.withQuery(((key -> value) +: u.query.reverse).reverse) + } + + def addPathSegment(segment: String): Uri = t { u ⇒ + import model.Uri.Path + import Path._ + + @tailrec def endsWithSlash(path: Path): Boolean = path match { + case Empty ⇒ false + case Slash(Empty) ⇒ true + case Slash(tail) ⇒ endsWithSlash(tail) + case Segment(head, tail) ⇒ endsWithSlash(tail) + } + + val newPath = + if (endsWithSlash(u.path)) u.path ++ Path(segment) + else u.path ++ Path./(segment) + + u.withPath(newPath) + } + + def fragment(fragment: Option[String]): Uri = t(_.copy(fragment = fragment)) + def fragment(fragment: String): Uri = t(_.withFragment(fragment)) +} \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/model/parser/AcceptHeader.scala b/akka-http-core/src/main/scala/akka/http/model/parser/AcceptHeader.scala index f62012f875..0e58662d5f 100644 --- a/akka-http-core/src/main/scala/akka/http/model/parser/AcceptHeader.scala +++ b/akka-http-core/src/main/scala/akka/http/model/parser/AcceptHeader.scala @@ -13,7 +13,6 @@ private[parser] trait AcceptHeader { this: Parser with CommonRules with CommonAc // http://tools.ietf.org/html/rfc7231#section-5.3.2 def accept = rule { - zeroOrMore(`media-range-decl`).separatedBy(listSep) ~ EOI ~> (Accept(_)) } diff --git a/akka-http-core/src/main/scala/akka/http/util/DateTime.scala b/akka-http-core/src/main/scala/akka/http/util/DateTime.scala index dcaa701f67..44c2e36cd8 100644 --- a/akka-http-core/src/main/scala/akka/http/util/DateTime.scala +++ b/akka-http-core/src/main/scala/akka/http/util/DateTime.scala @@ -17,7 +17,7 @@ final case class DateTime private (year: Int, // the year second: Int, // the second of the minute. The first second is 0. weekday: Int, // the day of the week. Sunday is 0. clicks: Long, // milliseconds since January 1, 1970, 00:00:00 GMT - isLeapYear: Boolean) extends Ordered[DateTime] with Renderable { + isLeapYear: Boolean) extends akka.http.model.japi.DateTime with Ordered[DateTime] with Renderable { /** * The day of the week as a 3 letter abbreviation: * `Sun`, `Mon`, `Tue`, `Wed`, `Thu`, `Fri` or `Sat` diff --git a/akka-http-core/src/test/java/akka/http/model/japi/JavaApiTestCases.java b/akka-http-core/src/test/java/akka/http/model/japi/JavaApiTestCases.java new file mode 100644 index 0000000000..432489be86 --- /dev/null +++ b/akka-http-core/src/test/java/akka/http/model/japi/JavaApiTestCases.java @@ -0,0 +1,64 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import akka.http.model.japi.headers.Authorization; +import akka.http.model.japi.headers.HttpCredentials; + +public class JavaApiTestCases { + /** Builds a request for use on the client side */ + public static HttpRequest buildRequest() { + return + HttpRequest.create() + .withMethod(HttpMethods.POST) + .withUri("/send"); + } + + /** A simple handler for an Http server */ + public static HttpResponse handleRequest(HttpRequest request) { + if (request.method() == HttpMethods.GET) { + Uri uri = request.getUri(); + if (uri.path().equals("/hello")) { + String name = Util.getOrElse(uri.parameter("name"), "Mister X"); + + return + HttpResponse.create() + .withEntity("Hello " + name + "!"); + } else + return + HttpResponse.create() + .withStatus(404) + .withEntity("Not found"); + } else + return + HttpResponse.create() + .withStatus(StatusCodes.METHOD_NOT_ALLOWED) + .withEntity("Unsupported method"); + } + + /** Adds authentication to an existing request */ + public static HttpRequest addAuthentication(HttpRequest request) { + return request + .addHeader(Authorization.create(HttpCredentials.createBasicHttpCredential("username", "password"))); + } + + /** Removes cookies from an existing request */ + public static HttpRequest removeCookies(HttpRequest request) { + return request.removeHeader("Cookie"); + } + + /** Build a uri to send a form */ + public static Uri createUriForOrder(String orderId, String price, String amount) { + return Uri.create() + .path("/order") + .addParameter("orderId", orderId) + .addParameter("price", price) + .addParameter("amount", amount); + } + + public static Uri addSessionId(Uri uri) { + return uri.addParameter("session", "abcdefghijkl"); + } +} diff --git a/akka-http-core/src/test/java/akka/http/model/japi/JavaTestServer.java b/akka-http-core/src/test/java/akka/http/model/japi/JavaTestServer.java new file mode 100644 index 0000000000..b93d952db1 --- /dev/null +++ b/akka-http-core/src/test/java/akka/http/model/japi/JavaTestServer.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi; + +import static akka.pattern.Patterns.ask; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.dispatch.Foreach; +import akka.japi.Function; +import akka.japi.Procedure; +import akka.stream.FlowMaterializer; +import akka.stream.MaterializerSettings; +import akka.stream.javadsl.Flow; +import scala.concurrent.Future; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public abstract class JavaTestServer { + public static void main(String[] args) throws IOException, InterruptedException { + ActorSystem system = ActorSystem.create(); + + MaterializerSettings settings = MaterializerSettings.create(); + final FlowMaterializer materializer = FlowMaterializer.create(settings, system); + + ActorRef httpManager = Http.get(system).manager(); + Future binding = ask(httpManager, Http.bind("localhost", 8080), 1000); + binding.foreach(new Foreach() { + @Override + public void each(Object result) throws Throwable { + ServerBinding binding = (ServerBinding) result; + System.out.println("Bound to " + binding.localAddress()); + + Flow.create(binding.getConnectionStream()).foreach(new Procedure() { + @Override + public void apply(IncomingConnection conn) throws Exception { + System.out.println("New incoming connection from " + conn.remoteAddress()); + + Flow.create(conn.getRequestProducer()) + .map(new Function() { + @Override + public HttpResponse apply(HttpRequest request) throws Exception { + System.out.println("Handling request to " + request.getUri()); + return JavaApiTestCases.handleRequest(request); + } + }) + .produceTo(materializer, conn.getResponseConsumer()); + } + }).consume(materializer); + } + }, system.dispatcher()); + + System.out.println("Press ENTER to stop."); + new BufferedReader(new InputStreamReader(System.in)).readLine(); + + system.shutdown(); + } +} diff --git a/akka-http-core/src/test/scala/akka/http/model/japi/JavaApiSpec.scala b/akka-http-core/src/test/scala/akka/http/model/japi/JavaApiSpec.scala new file mode 100644 index 0000000000..5a6f769a36 --- /dev/null +++ b/akka-http-core/src/test/scala/akka/http/model/japi/JavaApiSpec.scala @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi + +import org.scalatest.{ MustMatchers, FreeSpec } +import scala.collection.JavaConverters._ + +class JavaApiSpec extends FreeSpec with MustMatchers { + "The Java API should work for" - { + "work with Uris" - { + "addParameter" in { + Accessors.Uri("/abc") + .addParameter("name", "paul") must be(Accessors.Uri("/abc?name=paul")) + } + "addSegment" in { + Accessors.Uri("/abc") + .addPathSegment("def") must be(Accessors.Uri("/abc/def")) + + Accessors.Uri("/abc/") + .addPathSegment("def") must be(Accessors.Uri("/abc/def")) + } + "scheme/host/port" in { + Accessors.Uri("/abc") + .scheme("http") + .host("example.com") + .port(8258) must be(Accessors.Uri("http://example.com:8258/abc")) + } + "toRelative" in { + Accessors.Uri("http://example.com/abc") + .toRelative must be(Accessors.Uri("/abc")) + } + "pathSegments" in { + Accessors.Uri("/abc/def/ghi/jkl") + .pathSegments().asScala.toSeq must contain inOrderOnly ("abc", "def", "ghi", "jkl") + } + "access parameterMap" in { + Accessors.Uri("/abc?name=blub&age=28") + .parameterMap().asScala must contain allOf ("name" -> "blub", "age" -> "28") + } + "access parameters" in { + val Seq(param1, param2, param3) = + Accessors.Uri("/abc?name=blub&age=28&name=blub2") + .parameters.asScala.toSeq + + param1.key() must be("name") + param1.value() must be("blub") + + param2.key() must be("age") + param2.value() must be("28") + + param3.key() must be("name") + param3.value() must be("blub2") + } + "containsParameter" in { + val uri = Accessors.Uri("/abc?name=blub") + uri.containsParameter("name") must be(true) + uri.containsParameter("age") must be(false) + } + "access single parameter" in { + val uri = Accessors.Uri("/abc?name=blub") + uri.parameter("name") must be(akka.japi.Option.some("blub")) + uri.parameter("age") must be(akka.japi.Option.none) + + Accessors.Uri("/abc?name=blub&name=blib").parameter("name") must be(akka.japi.Option.some("blub")) + } + } + } +} diff --git a/akka-http-core/src/test/scala/akka/http/model/japi/JavaApiTestCaseSpecs.scala b/akka-http-core/src/test/scala/akka/http/model/japi/JavaApiTestCaseSpecs.scala new file mode 100644 index 0000000000..10afd57575 --- /dev/null +++ b/akka-http-core/src/test/scala/akka/http/model/japi/JavaApiTestCaseSpecs.scala @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.model.japi + +import scala.collection.immutable + +import akka.http.model +import org.scalatest.{ MustMatchers, FreeSpec } +import akka.http.model.headers.BasicHttpCredentials + +class JavaApiTestCaseSpecs extends FreeSpec with MustMatchers { + "JavaApiTestCases should work as intended" - { + "buildRequest" in { + JavaApiTestCases.buildRequest() must be( + model.HttpRequest( + model.HttpMethods.POST, + uri = "/send")) + } + "handleRequest" - { + "wrong method" in { + JavaApiTestCases.handleRequest(model.HttpRequest(model.HttpMethods.HEAD)) must be( + model.HttpResponse(model.StatusCodes.MethodNotAllowed, entity = "Unsupported method")) + } + "missing path" in { + JavaApiTestCases.handleRequest(model.HttpRequest(uri = "/blubber")) must be( + model.HttpResponse(model.StatusCodes.NotFound, entity = "Not found")) + } + "happy path" - { + "with name parameter" in { + JavaApiTestCases.handleRequest(model.HttpRequest(uri = "/hello?name=Peter")) must be( + model.HttpResponse(entity = "Hello Peter!")) + } + "without name parameter" in { + JavaApiTestCases.handleRequest(model.HttpRequest(uri = "/hello")) must be( + model.HttpResponse(entity = "Hello Mister X!")) + } + } + } + "addAuthentication" in { + JavaApiTestCases.addAuthentication(model.HttpRequest()) must be( + model.HttpRequest(headers = immutable.Seq(model.headers.Authorization(BasicHttpCredentials("username", "password"))))) + } + "removeCookies" in { + val testRequest = model.HttpRequest(headers = immutable.Seq(model.headers.Cookie(model.headers.HttpCookie("test", "blub")))) + JavaApiTestCases.removeCookies(testRequest) must be( + model.HttpRequest()) + } + "createUriForOrder" in { + JavaApiTestCases.createUriForOrder("123", "149", "42") must be( + Accessors.Uri(model.Uri("/order?orderId=123&price=149&amount=42"))) + } + "addSessionId" in { + val origin = Accessors.Uri("/order?orderId=123") + JavaApiTestCases.addSessionId(origin) must be(Accessors.Uri("/order?orderId=123&session=abcdefghijkl")) + } + } +} \ No newline at end of file