From 379a3a85b4c702080146c4f26412ae3f206d84a7 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Fri, 22 Jan 2016 16:56:49 +0100 Subject: [PATCH] !htc #19514 add withXYZ methods to all configs --- .../BasicDirectivesExamplesSpec.scala | 6 +- .../akka/http/javadsl/model/HttpMethod.java | 7 + .../java/akka/http/javadsl/model/Uri.java | 258 +++++++++--------- .../akka/http/ClientConnectionSettings.scala | 118 -------- .../akka/http/ConnectionPoolSettings.scala | 121 -------- .../main/scala/akka/http/ParserSettings.scala | 231 ---------------- .../main/scala/akka/http/ServerSettings.scala | 211 -------------- .../client/OutgoingConnectionBlueprint.scala | 3 +- .../http/impl/engine/client/PoolFlow.scala | 2 +- .../http/impl/engine/client/PoolGateway.scala | 2 +- .../engine/client/PoolInterfaceActor.scala | 2 +- .../http/impl/engine/client/PoolSlot.scala | 3 +- .../engine/parsing/HttpMessageParser.scala | 2 +- .../engine/parsing/HttpRequestParser.scala | 2 +- .../engine/parsing/HttpResponseParser.scala | 2 +- .../http/impl/engine/parsing/package.scala | 2 +- .../HttpRequestRendererFactory.scala | 2 +- .../engine/server/HttpServerBluePrint.scala | 2 +- .../engine/ws/WebSocketClientBlueprint.scala | 2 +- .../http/impl/model/parser/HeaderParser.scala | 4 +- .../ClientConnectionSettingsImpl.scala | 47 ++++ .../settings/ConnectionPoolSettingsImpl.scala | 41 +++ .../impl/settings/ConnectionPoolSetup.scala | 15 + .../settings/HostConnectionPoolSetup.scala | 9 + .../impl/settings/ParserSettingsImpl.scala | 77 ++++++ .../impl/settings/ServerSettingsImpl.scala | 91 ++++++ .../akka/http/impl/util/JavaMapping.scala | 13 +- .../http/impl/util/SettingsCompanion.scala | 5 +- .../http/impl/util/SocketOptionSettings.scala | 2 +- .../http/javadsl/HostConnectionPool.scala | 2 +- .../main/scala/akka/http/javadsl/Http.scala | 58 ++-- .../settings/ClientConnectionSettings.scala | 44 +++ .../settings/ConnectionPoolSettings.scala | 36 +++ .../javadsl/settings/ParserSettings.scala | 78 ++++++ .../javadsl/settings/ServerSettings.scala | 69 +++++ .../javadsl/settings/SettingsCompanion.scala | 30 ++ .../main/scala/akka/http/scaladsl/Http.scala | 8 +- .../akka/http/scaladsl/model/HttpMethod.scala | 2 - .../scala/akka/http/scaladsl/model/Uri.scala | 3 +- .../settings/ClientConnectionSettings.scala | 61 +++++ .../settings/ConnectionPoolSettings.scala | 46 ++++ .../scaladsl/settings/ParserSettings.scala | 124 +++++++++ .../scaladsl/settings/ServerSettings.scala | 95 +++++++ .../scaladsl/settings/SettingsCompanion.scala | 27 ++ .../engine/client/ConnectionPoolSpec.scala | 12 +- .../engine/client/HttpConfigurationSpec.scala | 2 +- .../LowLevelOutgoingConnectionSpec.scala | 6 +- .../engine/parsing/HttpHeaderParserSpec.scala | 2 +- .../parsing/HttpHeaderParserTestBed.scala | 2 +- .../engine/parsing/RequestParserSpec.scala | 2 +- .../engine/parsing/ResponseParserSpec.scala | 2 +- .../impl/engine/server/HttpServerSpec.scala | 14 +- .../server/HttpServerTestSetupBase.scala | 4 +- .../impl/engine/ws/WebSocketClientSpec.scala | 7 +- .../impl/model/parser/HttpHeaderSpec.scala | 2 +- .../akka/http/scaladsl/ClientServerSpec.scala | 13 +- .../akka/http/javadsl/testkit/RouteTest.scala | 4 +- .../http/scaladsl/testkit/RouteTest.scala | 2 +- .../http/javadsl/client/HttpAPIsTest.java | 2 +- .../FileAndResourceDirectivesSpec.scala | 2 +- .../http/javadsl/server/HttpService.scala | 3 +- .../scaladsl/server/ExceptionHandler.scala | 8 +- .../http/scaladsl/server/RequestContext.scala | 8 +- .../scaladsl/server/RequestContextImpl.scala | 14 +- .../akka/http/scaladsl/server/Route.scala | 8 +- .../http/scaladsl/server/RouteResult.scala | 4 +- .../scaladsl/server/RoutingSettings.scala | 80 ------ .../scaladsl/server/RoutingSettingsImpl.scala | 31 +++ .../server/directives/BasicDirectives.scala | 20 +- .../directives/MarshallingDirectives.scala | 2 +- .../MultipartUnmarshallers.scala | 34 ++- 71 files changed, 1225 insertions(+), 1030 deletions(-) delete mode 100644 akka-http-core/src/main/scala/akka/http/ClientConnectionSettings.scala delete mode 100644 akka-http-core/src/main/scala/akka/http/ConnectionPoolSettings.scala delete mode 100644 akka-http-core/src/main/scala/akka/http/ParserSettings.scala delete mode 100644 akka-http-core/src/main/scala/akka/http/ServerSettings.scala create mode 100644 akka-http-core/src/main/scala/akka/http/impl/settings/ClientConnectionSettingsImpl.scala create mode 100644 akka-http-core/src/main/scala/akka/http/impl/settings/ConnectionPoolSettingsImpl.scala create mode 100644 akka-http-core/src/main/scala/akka/http/impl/settings/ConnectionPoolSetup.scala create mode 100644 akka-http-core/src/main/scala/akka/http/impl/settings/HostConnectionPoolSetup.scala create mode 100644 akka-http-core/src/main/scala/akka/http/impl/settings/ParserSettingsImpl.scala create mode 100644 akka-http-core/src/main/scala/akka/http/impl/settings/ServerSettingsImpl.scala create mode 100644 akka-http-core/src/main/scala/akka/http/javadsl/settings/ClientConnectionSettings.scala create mode 100644 akka-http-core/src/main/scala/akka/http/javadsl/settings/ConnectionPoolSettings.scala create mode 100644 akka-http-core/src/main/scala/akka/http/javadsl/settings/ParserSettings.scala create mode 100644 akka-http-core/src/main/scala/akka/http/javadsl/settings/ServerSettings.scala create mode 100644 akka-http-core/src/main/scala/akka/http/javadsl/settings/SettingsCompanion.scala create mode 100644 akka-http-core/src/main/scala/akka/http/scaladsl/settings/ClientConnectionSettings.scala create mode 100644 akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala create mode 100644 akka-http-core/src/main/scala/akka/http/scaladsl/settings/ParserSettings.scala create mode 100644 akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala create mode 100644 akka-http-core/src/main/scala/akka/http/scaladsl/settings/SettingsCompanion.scala delete mode 100644 akka-http/src/main/scala/akka/http/scaladsl/server/RoutingSettings.scala create mode 100644 akka-http/src/main/scala/akka/http/scaladsl/server/RoutingSettingsImpl.scala diff --git a/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala index 007160adb0..ece31eaa4d 100644 --- a/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala @@ -183,7 +183,7 @@ class BasicDirectivesExamplesSpec extends RoutingSpec { } "withSettings-0" in compileOnlySpec { //#withSettings-0 - val special = RoutingSettings(system).copy(fileIODispatcher = "special-io-dispatcher") + val special = RoutingSettingsImpl(system).copy(fileIODispatcher = "special-io-dispatcher") def sample() = path("sample") { @@ -687,7 +687,7 @@ class BasicDirectivesExamplesSpec extends RoutingSpec { "extractSettings-examples" in { //#extractSettings-examples val route = - extractSettings { settings: RoutingSettings => + extractSettings { settings: RoutingSettingsImpl => complete(s"RoutingSettings.renderVanityFooter = ${settings.renderVanityFooter}") } @@ -705,7 +705,7 @@ class BasicDirectivesExamplesSpec extends RoutingSpec { val route = tunedSettings { - extractSettings { settings: RoutingSettings => + extractSettings { settings: RoutingSettingsImpl => complete(s"RoutingSettings.fileGetConditional = ${settings.fileGetConditional}") } } diff --git a/akka-http-core/src/main/java/akka/http/javadsl/model/HttpMethod.java b/akka-http-core/src/main/java/akka/http/javadsl/model/HttpMethod.java index 5f24bc5237..fb86379270 100644 --- a/akka-http-core/src/main/java/akka/http/javadsl/model/HttpMethod.java +++ b/akka-http-core/src/main/java/akka/http/javadsl/model/HttpMethod.java @@ -9,6 +9,13 @@ package akka.http.javadsl.model; * and static constructors to create custom ones. */ public abstract class HttpMethod { + + /** + * Returns the name of the method, always equal to [[value]]. + */ + public final String name() { + return value(); + } /** * Returns the name of the method. */ diff --git a/akka-http-core/src/main/java/akka/http/javadsl/model/Uri.java b/akka-http-core/src/main/java/akka/http/javadsl/model/Uri.java index cd8f54f6e6..9d4cec58e8 100644 --- a/akka-http-core/src/main/java/akka/http/javadsl/model/Uri.java +++ b/akka-http-core/src/main/java/akka/http/javadsl/model/Uri.java @@ -16,163 +16,165 @@ import java.util.Optional; * Represents an 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 an absolute Uri. + */ + public abstract boolean isAbsolute(); - /** - * Returns if this is a relative Uri. - */ - public abstract boolean isRelative(); + /** + * Returns if this is a relative Uri. + */ + public abstract boolean isRelative(); - /** - * Returns if this is an empty Uri. - */ - public abstract boolean isEmpty(); + /** + * Returns if this is an empty Uri. + */ + public abstract boolean isEmpty(); - /** - * Returns the scheme of this Uri. - */ - public abstract String scheme(); + /** + * Returns the scheme of this Uri. + */ + public abstract String scheme(); - /** - * Returns the Host of this Uri. - */ - public abstract Host host(); + /** + * Returns the Host of this Uri. + */ + public abstract Host host(); - /** - * Returns the port of this Uri. - */ - public abstract int port(); + /** + * Returns the port of this Uri. + */ + public abstract int port(); - /** - * Returns the user-info of this Uri. - */ - public abstract String userInfo(); + /** + * 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 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 the the path segments of this Uri as an Iterable. + */ + public abstract Iterable pathSegments(); - /** - * Returns a decoded String representation of the query of this Uri. - */ - public abstract Optional queryString(Charset charset); + /** + * Returns a decoded String representation of the query of this Uri. + */ + public abstract Optional queryString(Charset charset); - /** - * Returns an undecoded String representation of the query of this Uri. - */ - public abstract Optional rawQueryString(); + /** + * Returns an undecoded String representation of the query of this Uri. + */ + public abstract Optional rawQueryString(); - /** - * Returns the parsed Query instance of this Uri. - */ - public abstract Query query(); + /** + * Returns the parsed Query instance of this Uri. + */ + public abstract Query query(); - /** - * Returns the parsed Query instance of this Uri using the given charset and parsing mode. - */ - public abstract Query query(Charset charset, akka.http.scaladsl.model.Uri.ParsingMode mode); + /** + * Returns the parsed Query instance of this Uri using the given charset and parsing mode. + */ + public abstract Query query(Charset charset, akka.http.scaladsl.model.Uri.ParsingMode mode); - /** - * Returns the fragment part of this Uri. - */ - public abstract Optional fragment(); + /** + * Returns the fragment part of this Uri. + */ + public abstract Optional 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 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(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 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 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 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 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 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 rawQueryString(String rawQuery); + /** + * Returns a copy of this instance with a new query. + */ + public abstract Uri rawQueryString(String rawQuery); - /** - * Returns a copy of this instance with a new query. - */ - public abstract Uri query(Query query); + /** + * Returns a copy of this instance with a new query. + */ + public abstract Uri query(Query query); - /** - * Returns a copy of this instance that is relative. - */ - public abstract Uri toRelative(); + /** + * Returns a copy of this instance that is relative. + */ + public abstract Uri toRelative(); - /** - * 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 fragment. + */ + public abstract Uri fragment(String fragment); - /** - * Returns a copy of this instance with a new optional fragment. - */ - public abstract Uri fragment(Optional fragment); + /** + * Returns a copy of this instance with a new optional fragment. + */ + public abstract Uri fragment(Optional fragment); - public static final akka.http.scaladsl.model.Uri.ParsingMode STRICT = UriJavaAccessor.pmStrict(); - public static final akka.http.scaladsl.model.Uri.ParsingMode RELAXED = UriJavaAccessor.pmRelaxed(); + public static final akka.http.scaladsl.model.Uri.ParsingMode STRICT = UriJavaAccessor.pmStrict(); + public static final akka.http.scaladsl.model.Uri.ParsingMode RELAXED = UriJavaAccessor.pmRelaxed(); - /** - * Creates a default Uri to be modified using the modification methods. - */ - public static final Uri EMPTY = new JavaUri(akka.http.scaladsl.model.Uri.Empty$.MODULE$); + /** + * Creates a default Uri to be modified using the modification methods. + */ + public static final Uri EMPTY = new JavaUri(akka.http.scaladsl.model.Uri.Empty$.MODULE$); - /** - * Returns a Uri created by parsing the given string representation. - */ - public static Uri create(String uri) { - return new JavaUri(akka.http.scaladsl.model.Uri.apply(uri)); - } + /** + * Returns a Uri created by parsing the given string representation. + */ + public static Uri create(String uri) { + return new JavaUri(akka.http.scaladsl.model.Uri.apply(uri)); + } - /** - * Returns a Uri created by parsing the given string representation with the provided parsing mode. - */ - public static Uri create(String uri, akka.http.scaladsl.model.Uri.ParsingMode parsingMode) { - return new JavaUri(akka.http.scaladsl.model.Uri.apply(ParserInput$.MODULE$.apply(uri), parsingMode)); - } + /** + * Returns a Uri created by parsing the given string representation with the provided parsing mode. + */ + public static Uri create(String uri, akka.http.scaladsl.model.Uri.ParsingMode parsingMode) { + return new JavaUri(akka.http.scaladsl.model.Uri.apply(ParserInput$.MODULE$.apply(uri), parsingMode)); + } - /** - * Returns a Uri created by parsing the given string representation with the provided charset and parsing mode. - */ - public static Uri create(String uri, Charset charset, akka.http.scaladsl.model.Uri.ParsingMode parsingMode) { - return new JavaUri(akka.http.scaladsl.model.Uri.apply(ParserInput$.MODULE$.apply(uri), charset, parsingMode)); - } + /** + * Returns a Uri created by parsing the given string representation with the provided charset and parsing mode. + */ + public static Uri create(String uri, Charset charset, akka.http.scaladsl.model.Uri.ParsingMode parsingMode) { + return new JavaUri(akka.http.scaladsl.model.Uri.apply(ParserInput$.MODULE$.apply(uri), charset, parsingMode)); + } + + public static interface ParsingMode {} } diff --git a/akka-http-core/src/main/scala/akka/http/ClientConnectionSettings.scala b/akka-http-core/src/main/scala/akka/http/ClientConnectionSettings.scala deleted file mode 100644 index cfbcd4aedc..0000000000 --- a/akka-http-core/src/main/scala/akka/http/ClientConnectionSettings.scala +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright (C) 2009-2016 Typesafe Inc. - */ - -package akka.http - -import java.util.Random - -import akka.http.impl.engine.ws.Randoms -import akka.io.Inet.SocketOption - -import scala.concurrent.duration.{ Duration, FiniteDuration } -import scala.collection.immutable - -import com.typesafe.config.Config -import akka.actor.ActorSystem - -import akka.http.impl.util._ - -import akka.http.scaladsl.model.headers.`User-Agent` - -final class ClientConnectionSettings( - val userAgentHeader: Option[`User-Agent`], - val connectingTimeout: FiniteDuration, - val idleTimeout: Duration, - val requestHeaderSizeHint: Int, - val websocketRandomFactory: () ⇒ Random, - val socketOptions: immutable.Traversable[SocketOption], - val parserSettings: ParserSettings) { - - require(connectingTimeout >= Duration.Zero, "connectingTimeout must be >= 0") - require(requestHeaderSizeHint > 0, "request-size-hint must be > 0") - - def copy( - userAgentHeader: Option[`User-Agent`] = userAgentHeader, - connectingTimeout: FiniteDuration = connectingTimeout, - idleTimeout: Duration = idleTimeout, - requestHeaderSizeHint: Int = requestHeaderSizeHint, - websocketRandomFactory: () ⇒ Random = websocketRandomFactory, - socketOptions: immutable.Traversable[SocketOption] = socketOptions, - parserSettings: ParserSettings = parserSettings) = - new ClientConnectionSettings( - userAgentHeader = userAgentHeader, - connectingTimeout = connectingTimeout, - idleTimeout = idleTimeout, - requestHeaderSizeHint = requestHeaderSizeHint, - websocketRandomFactory = websocketRandomFactory, - socketOptions = socketOptions, - parserSettings = parserSettings) - - override def toString = { - getClass.getSimpleName + "(" + - userAgentHeader + "," + - connectingTimeout + "," + - idleTimeout + "," + - requestHeaderSizeHint + "," + - websocketRandomFactory + "," + - socketOptions + "," + - parserSettings + "," + - ")" - } -} - -object ClientConnectionSettings extends SettingsCompanion[ClientConnectionSettings]("akka.http.client") { - def fromSubConfig(root: Config, inner: Config) = { - val c = inner.withFallback(root.getConfig(prefix)) - new ClientConnectionSettings( - userAgentHeader = c.getString("user-agent-header").toOption.map(`User-Agent`(_)), - connectingTimeout = c getFiniteDuration "connecting-timeout", - idleTimeout = c getPotentiallyInfiniteDuration "idle-timeout", - requestHeaderSizeHint = c getIntBytes "request-header-size-hint", - websocketRandomFactory = Randoms.SecureRandomInstances, // can currently only be overridden from code - socketOptions = SocketOptionSettings.fromSubConfig(root, c.getConfig("socket-options")), - parserSettings = ParserSettings.fromSubConfig(root, c.getConfig("parsing"))) - } - - /** - * Creates an instance of ClientConnectionSettings using the configuration provided by the given - * ActorSystem. - * - * Java API - */ - def create(system: ActorSystem): ClientConnectionSettings = ClientConnectionSettings(system) - - /** - * Creates an instance of ClientConnectionSettings using the given Config. - * - * Java API - */ - def create(config: Config): ClientConnectionSettings = ClientConnectionSettings(config) - - /** - * Create an instance of ClientConnectionSettings using the given String of config overrides to override - * settings set in the class loader of this class (i.e. by application.conf or reference.conf files in - * the class loader of this class). - * - * Java API - */ - def create(configOverrides: String): ClientConnectionSettings = ClientConnectionSettings(configOverrides) - - def apply( - userAgentHeader: Option[`User-Agent`], - connectingTimeout: FiniteDuration, - idleTimeout: Duration, - requestHeaderSizeHint: Int, - websocketRandomFactory: () ⇒ Random, - socketOptions: immutable.Traversable[SocketOption], - parserSettings: ParserSettings) = - new ClientConnectionSettings( - userAgentHeader = userAgentHeader, - connectingTimeout = connectingTimeout, - idleTimeout = idleTimeout, - requestHeaderSizeHint = requestHeaderSizeHint, - websocketRandomFactory = websocketRandomFactory, - socketOptions = socketOptions, - parserSettings = parserSettings) - -} \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/ConnectionPoolSettings.scala b/akka-http-core/src/main/scala/akka/http/ConnectionPoolSettings.scala deleted file mode 100644 index 6d7f861c59..0000000000 --- a/akka-http-core/src/main/scala/akka/http/ConnectionPoolSettings.scala +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (C) 2009-2016 Typesafe Inc. - */ - -package akka.http - -import akka.actor.ActorSystem -import akka.event.LoggingAdapter -import akka.http.impl.util._ -import akka.http.javadsl.ConnectionContext -import com.typesafe.config.Config - -import scala.concurrent.duration.Duration - -final case class HostConnectionPoolSetup(host: String, port: Int, setup: ConnectionPoolSetup) - -final case class ConnectionPoolSetup( - settings: ConnectionPoolSettings, - connectionContext: ConnectionContext = ConnectionContext.noEncryption(), - log: LoggingAdapter) - -object ConnectionPoolSetup { - /** Java API */ - def create(settings: ConnectionPoolSettings, - connectionContext: ConnectionContext, - log: LoggingAdapter): ConnectionPoolSetup = - ConnectionPoolSetup(settings, connectionContext, log) -} - -final class ConnectionPoolSettings( - val maxConnections: Int, - val maxRetries: Int, - val maxOpenRequests: Int, - val pipeliningLimit: Int, - val idleTimeout: Duration, - val connectionSettings: ClientConnectionSettings) { - - require(maxConnections > 0, "max-connections must be > 0") - require(maxRetries >= 0, "max-retries must be >= 0") - require(maxOpenRequests > 0 && (maxOpenRequests & (maxOpenRequests - 1)) == 0, "max-open-requests must be a power of 2 > 0") - require(pipeliningLimit > 0, "pipelining-limit must be > 0") - require(idleTimeout >= Duration.Zero, "idle-timeout must be >= 0") - - def copy( - maxConnections: Int = maxConnections, - maxRetries: Int = maxRetries, - maxOpenRequests: Int = maxOpenRequests, - pipeliningLimit: Int = pipeliningLimit, - idleTimeout: Duration = idleTimeout, - connectionSettings: ClientConnectionSettings = connectionSettings) = - new ConnectionPoolSettings( - maxConnections = maxConnections, - maxRetries = maxRetries, - maxOpenRequests = maxOpenRequests, - pipeliningLimit = pipeliningLimit, - idleTimeout = idleTimeout, - connectionSettings = connectionSettings) - - // TODO we should automate generating those - override def toString = { - getClass.getSimpleName + "(" + - maxConnections + "," + - maxRetries + "," + - maxOpenRequests + "," + - pipeliningLimit + "," + - idleTimeout + "," + - connectionSettings + - ")" - } -} - -object ConnectionPoolSettings extends SettingsCompanion[ConnectionPoolSettings]("akka.http.host-connection-pool") { - def fromSubConfig(root: Config, c: Config) = { - new ConnectionPoolSettings( - c getInt "max-connections", - c getInt "max-retries", - c getInt "max-open-requests", - c getInt "pipelining-limit", - c getPotentiallyInfiniteDuration "idle-timeout", - ClientConnectionSettings.fromSubConfig(root, c.getConfig("client"))) - } - - /** - * Creates an instance of ConnectionPoolSettings using the configuration provided by the given - * ActorSystem. - * - * Java API - */ - def create(system: ActorSystem): ConnectionPoolSettings = ConnectionPoolSettings(system) - - /** - * Creates an instance of ConnectionPoolSettings using the given Config. - * - * Java API - */ - def create(config: Config): ConnectionPoolSettings = ConnectionPoolSettings(config) - - /** - * Create an instance of ConnectionPoolSettings using the given String of config overrides to override - * settings set in the class loader of this class (i.e. by application.conf or reference.conf files in - * the class loader of this class). - * - * Java API - */ - def create(configOverrides: String): ConnectionPoolSettings = ConnectionPoolSettings(configOverrides) - - def apply( - maxConnections: Int, - maxRetries: Int, - maxOpenRequests: Int, - pipeliningLimit: Int, - idleTimeout: Duration, - connectionSettings: ClientConnectionSettings) = - new ConnectionPoolSettings( - maxConnections: Int, - maxRetries: Int, - maxOpenRequests: Int, - pipeliningLimit: Int, - idleTimeout: Duration, - connectionSettings: ClientConnectionSettings) -} \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/ParserSettings.scala b/akka-http-core/src/main/scala/akka/http/ParserSettings.scala deleted file mode 100644 index ea369d8a41..0000000000 --- a/akka-http-core/src/main/scala/akka/http/ParserSettings.scala +++ /dev/null @@ -1,231 +0,0 @@ -/** - * Copyright (C) 2009-2016 Typesafe Inc. - */ - -package akka.http - -import akka.actor.{ ActorRefFactory, ActorSystem } -import akka.stream.{ ActorMaterializer, Materializer } -import com.typesafe.config.Config -import scala.collection.JavaConverters._ -import akka.http.scaladsl.model.{ StatusCode, HttpMethod, Uri } -import akka.http.impl.util._ -import akka.http.impl.engine.parsing.{ BodyPartParser, HttpHeaderParser } - -final class ParserSettings( - val maxUriLength: Int, - val maxMethodLength: Int, - val maxResponseReasonLength: Int, - val maxHeaderNameLength: Int, - val maxHeaderValueLength: Int, - val maxHeaderCount: Int, - val maxContentLength: Long, - val maxChunkExtLength: Int, - val maxChunkSize: Int, - val uriParsingMode: Uri.ParsingMode, - val cookieParsingMode: ParserSettings.CookieParsingMode, - val illegalHeaderWarnings: Boolean, - val errorLoggingVerbosity: ParserSettings.ErrorLoggingVerbosity, - val headerValueCacheLimits: Map[String, Int], - val includeTlsSessionInfoHeader: Boolean, - val customMethods: String ⇒ Option[HttpMethod], - val customStatusCodes: Int ⇒ Option[StatusCode]) - extends BodyPartParser.Settings { - - require(maxUriLength > 0, "max-uri-length must be > 0") - require(maxMethodLength > 0, "max-method-length must be > 0") - require(maxResponseReasonLength > 0, "max-response-reason-length must be > 0") - require(maxHeaderNameLength > 0, "max-header-name-length must be > 0") - require(maxHeaderValueLength > 0, "max-header-value-length must be > 0") - require(maxHeaderCount > 0, "max-header-count must be > 0") - require(maxContentLength > 0, "max-content-length must be > 0") - require(maxChunkExtLength > 0, "max-chunk-ext-length must be > 0") - require(maxChunkSize > 0, "max-chunk-size must be > 0") - - override val defaultHeaderValueCacheLimit: Int = headerValueCacheLimits("default") - - override def headerValueCacheLimit(headerName: String): Int = - headerValueCacheLimits.getOrElse(headerName, defaultHeaderValueCacheLimit) - - def withCustomMethods(methods: HttpMethod*): ParserSettings = { - val map = methods.map(m ⇒ m.name -> m).toMap - copy(customMethods = map.get) - } - def withCustomStatusCodes(codes: StatusCode*): ParserSettings = { - val map = codes.map(c ⇒ c.intValue -> c).toMap - copy(customStatusCodes = map.get) - } - - def copy(maxUriLength: Int = maxUriLength, - maxMethodLength: Int = maxMethodLength, - maxResponseReasonLength: Int = maxResponseReasonLength, - maxHeaderNameLength: Int = maxHeaderNameLength, - maxHeaderValueLength: Int = maxHeaderValueLength, - maxHeaderCount: Int = maxHeaderCount, - maxContentLength: Long = maxContentLength, - maxChunkExtLength: Int = maxChunkExtLength, - maxChunkSize: Int = maxChunkSize, - uriParsingMode: Uri.ParsingMode = uriParsingMode, - cookieParsingMode: ParserSettings.CookieParsingMode = cookieParsingMode, - illegalHeaderWarnings: Boolean = illegalHeaderWarnings, - errorLoggingVerbosity: ParserSettings.ErrorLoggingVerbosity = errorLoggingVerbosity, - headerValueCacheLimits: Map[String, Int] = headerValueCacheLimits, - includeTlsSessionInfoHeader: Boolean = includeTlsSessionInfoHeader, - customMethods: String ⇒ Option[HttpMethod] = customMethods, - customStatusCodes: Int ⇒ Option[StatusCode] = customStatusCodes): ParserSettings = - new ParserSettings(maxUriLength, - maxMethodLength, - maxResponseReasonLength, - maxHeaderNameLength, - maxHeaderValueLength, - maxHeaderCount, - maxContentLength, - maxChunkExtLength, - maxChunkSize, - uriParsingMode, - cookieParsingMode, - illegalHeaderWarnings, - errorLoggingVerbosity, - headerValueCacheLimits, - includeTlsSessionInfoHeader, - customMethods, - customStatusCodes) - - // TODO we should automate generating those - override def toString = { - getClass.getSimpleName + "(" + - maxUriLength + "," + - maxMethodLength + "," + - maxResponseReasonLength + "," + - maxHeaderNameLength + "," + - maxHeaderValueLength + "," + - maxHeaderCount + "," + - maxContentLength + "," + - maxChunkExtLength + "," + - maxChunkSize + "," + - uriParsingMode + "," + - cookieParsingMode + "," + - illegalHeaderWarnings + "," + - errorLoggingVerbosity + "," + - headerValueCacheLimits + "," + - includeTlsSessionInfoHeader + "," + - customMethods + "," + - customStatusCodes + - ")" - } -} - -object ParserSettings extends SettingsCompanion[ParserSettings]("akka.http.parsing") { - def fromSubConfig(root: Config, inner: Config) = { - val c = inner.withFallback(root.getConfig(prefix)) - val cacheConfig = c getConfig "header-cache" - - ParserSettings( - c getIntBytes "max-uri-length", - c getIntBytes "max-method-length", - c getIntBytes "max-response-reason-length", - c getIntBytes "max-header-name-length", - c getIntBytes "max-header-value-length", - c getIntBytes "max-header-count", - c getPossiblyInfiniteBytes "max-content-length", - c getIntBytes "max-chunk-ext-length", - c getIntBytes "max-chunk-size", - Uri.ParsingMode(c getString "uri-parsing-mode"), - CookieParsingMode(c getString "cookie-parsing-mode"), - c getBoolean "illegal-header-warnings", - ErrorLoggingVerbosity(c getString "error-logging-verbosity"), - cacheConfig.entrySet.asScala.map(kvp ⇒ kvp.getKey -> cacheConfig.getInt(kvp.getKey))(collection.breakOut), - c getBoolean "tls-session-info-header", - _ ⇒ None, - _ ⇒ None) - } - - sealed trait ErrorLoggingVerbosity - object ErrorLoggingVerbosity { - case object Off extends ErrorLoggingVerbosity - case object Simple extends ErrorLoggingVerbosity - case object Full extends ErrorLoggingVerbosity - - def apply(string: String): ErrorLoggingVerbosity = - string.toRootLowerCase match { - case "off" ⇒ Off - case "simple" ⇒ Simple - case "full" ⇒ Full - case x ⇒ throw new IllegalArgumentException(s"[$x] is not a legal `error-logging-verbosity` setting") - } - } - - sealed trait CookieParsingMode - object CookieParsingMode { - case object RFC6265 extends CookieParsingMode - case object Raw extends CookieParsingMode - - def apply(mode: String): CookieParsingMode = mode.toRootLowerCase match { - case "rfc6265" ⇒ RFC6265 - case "raw" ⇒ Raw - } - } - - /** - * Creates an instance of ParserSettings using the configuration provided by the given - * ActorSystem. - * - * Java API - */ - def create(system: ActorSystem): ParserSettings = ParserSettings(system) - - /** - * Creates an instance of ParserSettings using the given Config. - * - * Java API - */ - def create(config: Config): ParserSettings = ParserSettings(config) - - /** - * Create an instance of ParserSettings using the given String of config overrides to override - * settings set in the class loader of this class (i.e. by application.conf or reference.conf files in - * the class loader of this class). - * - * Java API - */ - def create(configOverrides: String): ParserSettings = ParserSettings(configOverrides) - - implicit def default(implicit refFactory: ActorRefFactory): ParserSettings = - apply(actorSystem) - - def apply(maxUriLength: Int, - maxMethodLength: Int, - maxResponseReasonLength: Int, - maxHeaderNameLength: Int, - maxHeaderValueLength: Int, - maxHeaderCount: Int, - maxContentLength: Long, - maxChunkExtLength: Int, - maxChunkSize: Int, - uriParsingMode: Uri.ParsingMode, - cookieParsingMode: ParserSettings.CookieParsingMode, - illegalHeaderWarnings: Boolean, - errorLoggingVerbosity: ParserSettings.ErrorLoggingVerbosity, - headerValueCacheLimits: Map[String, Int], - includeTlsSessionInfoHeader: Boolean, - customMethods: String ⇒ Option[HttpMethod], - customStatusCodes: Int ⇒ Option[StatusCode]): ParserSettings = - new ParserSettings(maxUriLength, - maxMethodLength, - maxResponseReasonLength, - maxHeaderNameLength, - maxHeaderValueLength, - maxHeaderCount, - maxContentLength, - maxChunkExtLength, - maxChunkSize, - uriParsingMode, - cookieParsingMode, - illegalHeaderWarnings, - errorLoggingVerbosity, - headerValueCacheLimits, - includeTlsSessionInfoHeader, - customMethods, - customStatusCodes) -} - diff --git a/akka-http-core/src/main/scala/akka/http/ServerSettings.scala b/akka-http-core/src/main/scala/akka/http/ServerSettings.scala deleted file mode 100644 index fee85addaf..0000000000 --- a/akka-http-core/src/main/scala/akka/http/ServerSettings.scala +++ /dev/null @@ -1,211 +0,0 @@ -/** - * Copyright (C) 2009-2016 Typesafe Inc. - */ - -package akka.http - -import java.util.Random - -import akka.http.impl.engine.ws.Randoms -import com.typesafe.config.Config - -import scala.language.implicitConversions -import scala.collection.immutable -import scala.concurrent.duration._ - -import akka.ConfigurationException -import akka.actor.{ ActorSystem, ActorRefFactory } -import akka.io.Inet.SocketOption - -import akka.http.impl.util._ - -import akka.http.scaladsl.model.HttpHeader -import akka.http.scaladsl.model.headers.{ Host, Server } - -final class ServerSettings( - val serverHeader: Option[Server], - val timeouts: ServerSettings.Timeouts, - val maxConnections: Int, - val pipeliningLimit: Int, - val remoteAddressHeader: Boolean, - val rawRequestUriHeader: Boolean, - val transparentHeadRequests: Boolean, - val verboseErrorMessages: Boolean, - val responseHeaderSizeHint: Int, - val backlog: Int, - val socketOptions: immutable.Traversable[SocketOption], - val defaultHostHeader: Host, - val websocketRandomFactory: () ⇒ Random, - val parserSettings: ParserSettings) { - - require(0 < maxConnections, "max-connections must be > 0") - require(0 < pipeliningLimit && pipeliningLimit <= 1024, "pipelining-limit must be > 0 and <= 1024") - require(0 < responseHeaderSizeHint, "response-size-hint must be > 0") - require(0 < backlog, "backlog must be > 0") - - def copy( - serverHeader: Option[Server] = serverHeader, - timeouts: ServerSettings.Timeouts = timeouts, - maxConnections: Int = maxConnections, - pipeliningLimit: Int = pipeliningLimit, - remoteAddressHeader: Boolean = remoteAddressHeader, - rawRequestUriHeader: Boolean = rawRequestUriHeader, - transparentHeadRequests: Boolean = transparentHeadRequests, - verboseErrorMessages: Boolean = verboseErrorMessages, - responseHeaderSizeHint: Int = responseHeaderSizeHint, - backlog: Int = backlog, - socketOptions: immutable.Traversable[SocketOption] = socketOptions, - defaultHostHeader: Host = defaultHostHeader, - websocketRandomFactory: () ⇒ Random = websocketRandomFactory, - parserSettings: ParserSettings = parserSettings) = - new ServerSettings( - serverHeader = serverHeader, - timeouts = timeouts, - maxConnections = maxConnections, - pipeliningLimit = pipeliningLimit, - remoteAddressHeader = remoteAddressHeader, - rawRequestUriHeader = rawRequestUriHeader, - transparentHeadRequests = transparentHeadRequests, - verboseErrorMessages = verboseErrorMessages, - responseHeaderSizeHint = responseHeaderSizeHint, - backlog = backlog, - socketOptions = socketOptions, - defaultHostHeader = defaultHostHeader, - websocketRandomFactory = websocketRandomFactory, - parserSettings = parserSettings) - - // TODO we should automate generating those - override def toString: String = { - getClass.getSimpleName + "(" + - serverHeader + "," + - timeouts + "," + - maxConnections + "," + - pipeliningLimit + "," + - remoteAddressHeader + "," + - rawRequestUriHeader + "," + - transparentHeadRequests + "," + - verboseErrorMessages + "," + - responseHeaderSizeHint + "," + - backlog + "," + - socketOptions + "," + - defaultHostHeader + "," + - websocketRandomFactory + "," + - parserSettings + "," + - ")" - } - -} - -object ServerSettings extends SettingsCompanion[ServerSettings]("akka.http.server") { - final class Timeouts( - val idleTimeout: Duration, - val requestTimeout: Duration, - val bindTimeout: FiniteDuration) { - require(idleTimeout > Duration.Zero, "idleTimeout must be infinite or > 0") - require(requestTimeout > Duration.Zero, "requestTimeout must be infinite or > 0") - require(bindTimeout > Duration.Zero, "bindTimeout must be > 0") - - def copy( - idleTimeout: Duration = idleTimeout, - requestTimeout: Duration = requestTimeout, - bindTimeout: FiniteDuration = bindTimeout) = - new Timeouts( - idleTimeout, - requestTimeout, - bindTimeout) - - override def toString = { - "Timeouts(" + - idleTimeout + "," + - requestTimeout + "," + - bindTimeout + "," + - ")" - } - } - implicit def timeoutsShortcut(s: ServerSettings): Timeouts = s.timeouts - - def fromSubConfig(root: Config, c: Config) = new ServerSettings( - c.getString("server-header").toOption.map(Server(_)), - new Timeouts( - c getPotentiallyInfiniteDuration "idle-timeout", - c getPotentiallyInfiniteDuration "request-timeout", - c getFiniteDuration "bind-timeout"), - c getInt "max-connections", - c getInt "pipelining-limit", - c getBoolean "remote-address-header", - c getBoolean "raw-request-uri-header", - c getBoolean "transparent-head-requests", - c getBoolean "verbose-error-messages", - c getIntBytes "response-header-size-hint", - c getInt "backlog", - SocketOptionSettings.fromSubConfig(root, c.getConfig("socket-options")), - defaultHostHeader = - HttpHeader.parse("Host", c getString "default-host-header") match { - case HttpHeader.ParsingResult.Ok(x: Host, Nil) ⇒ x - case result ⇒ - val info = result.errors.head.withSummary("Configured `default-host-header` is illegal") - throw new ConfigurationException(info.formatPretty) - }, - Randoms.SecureRandomInstances, // can currently only be overridden from code - ParserSettings.fromSubConfig(root, c.getConfig("parsing"))) - - def apply(optionalSettings: Option[ServerSettings])(implicit actorRefFactory: ActorRefFactory): ServerSettings = - optionalSettings getOrElse apply(actorSystem) - - /** - * Creates an instance of ServerSettings using the configuration provided by the given - * ActorSystem. - * - * Java API - */ - def create(system: ActorSystem): ServerSettings = ServerSettings(system) - - /** - * Creates an instance of ServerSettings using the given Config. - * - * Java API - */ - def create(config: Config): ServerSettings = ServerSettings(config) - - /** - * Create an instance of ServerSettings using the given String of config overrides to override - * settings set in the class loader of this class (i.e. by application.conf or reference.conf files in - * the class loader of this class). - * - * Java API - */ - def create(configOverrides: String): ServerSettings = ServerSettings(configOverrides) - - def apply( - serverHeader: Option[Server], - timeouts: ServerSettings.Timeouts, - maxConnections: Int, - pipeliningLimit: Int, - remoteAddressHeader: Boolean, - rawRequestUriHeader: Boolean, - transparentHeadRequests: Boolean, - verboseErrorMessages: Boolean, - responseHeaderSizeHint: Int, - backlog: Int, - socketOptions: immutable.Traversable[SocketOption], - defaultHostHeader: Host, - websocketRandomFactory: () ⇒ Random, - parserSettings: ParserSettings) = - new ServerSettings( - serverHeader = serverHeader, - timeouts = timeouts, - maxConnections = maxConnections, - pipeliningLimit = pipeliningLimit, - remoteAddressHeader = remoteAddressHeader, - rawRequestUriHeader = rawRequestUriHeader, - transparentHeadRequests = transparentHeadRequests, - verboseErrorMessages = verboseErrorMessages, - responseHeaderSizeHint = responseHeaderSizeHint, - backlog = backlog, - socketOptions = socketOptions, - defaultHostHeader = defaultHostHeader, - websocketRandomFactory = websocketRandomFactory, - parserSettings = parserSettings) - -} - diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/client/OutgoingConnectionBlueprint.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/client/OutgoingConnectionBlueprint.scala index 4bc6aedddc..b68264ab67 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/client/OutgoingConnectionBlueprint.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/client/OutgoingConnectionBlueprint.scala @@ -5,7 +5,7 @@ package akka.http.impl.engine.client import akka.NotUsed -import akka.stream.impl.fusing.GraphInterpreter +import akka.http.scaladsl.settings.ClientConnectionSettings import language.existentials import scala.annotation.tailrec import scala.collection.mutable.ListBuffer @@ -14,7 +14,6 @@ import akka.util.ByteString import akka.event.LoggingAdapter import akka.stream._ import akka.stream.scaladsl._ -import akka.http.ClientConnectionSettings import akka.http.scaladsl.Http import akka.http.scaladsl.model.headers.Host import akka.http.scaladsl.model.{ IllegalResponseException, HttpMethod, HttpRequest, HttpResponse } diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolFlow.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolFlow.scala index 4e492586cd..88d8139f80 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolFlow.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolFlow.scala @@ -6,7 +6,7 @@ package akka.http.impl.engine.client import java.net.InetSocketAddress import akka.NotUsed -import akka.http.ConnectionPoolSettings +import akka.http.scaladsl.settings.ConnectionPoolSettings import scala.concurrent.{ Promise, Future } import scala.util.Try diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolGateway.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolGateway.scala index 470a685d1e..6129e3029e 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolGateway.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolGateway.scala @@ -3,7 +3,7 @@ package akka.http.impl.engine.client import java.util.concurrent.atomic.AtomicReference import scala.annotation.tailrec import scala.concurrent.{ Future, Promise } -import akka.http.HostConnectionPoolSetup +import akka.http.impl.settings.HostConnectionPoolSetup import akka.actor.{ Deploy, Props, ActorSystem, ActorRef } import akka.http.scaladsl.Http import akka.http.scaladsl.model.{ HttpResponse, HttpRequest } diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolInterfaceActor.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolInterfaceActor.scala index 51eb0774eb..4c4ee9dc6c 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolInterfaceActor.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolInterfaceActor.scala @@ -18,7 +18,7 @@ import akka.stream.actor.ActorPublisherMessage._ import akka.stream.actor.ActorSubscriberMessage._ import akka.stream.impl.{ SeqActorName, FixedSizeBuffer } import akka.stream.scaladsl.{ Keep, Flow, Sink, Source } -import akka.http.HostConnectionPoolSetup +import akka.http.impl.settings.HostConnectionPoolSetup import akka.http.scaladsl.model._ import akka.http.scaladsl.{ ConnectionContext, HttpsConnectionContext, Http } import PoolFlow._ diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolSlot.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolSlot.scala index e7a5dee012..ad537d16ab 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolSlot.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/client/PoolSlot.scala @@ -7,10 +7,9 @@ package akka.http.impl.engine.client import java.net.InetSocketAddress import akka.actor._ -import akka.http.ConnectionPoolSettings +import akka.http.scaladsl.settings.ConnectionPoolSettings import akka.http.impl.util._ import akka.http.scaladsl.model.{ HttpEntity, HttpRequest, HttpResponse } -import akka.http.scaladsl.util.FastFuture import akka.stream._ import akka.stream.actor._ import akka.stream.impl.{ ActorProcessor, ExposedPublisher, SeqActorName, SubscribePending } diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpMessageParser.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpMessageParser.scala index 9f798e61e4..a612cc7d8d 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpMessageParser.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpMessageParser.scala @@ -14,7 +14,7 @@ import akka.parboiled2.CharUtils import akka.util.ByteString import akka.stream.stage._ import akka.http.impl.model.parser.CharacterClasses -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import akka.http.scaladsl.model._ import headers._ import HttpProtocols._ diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpRequestParser.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpRequestParser.scala index 46dcb7ed19..a7ed0cd9a6 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpRequestParser.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpRequestParser.scala @@ -6,7 +6,7 @@ package akka.http.impl.engine.parsing import java.lang.{ StringBuilder ⇒ JStringBuilder } import scala.annotation.tailrec -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import akka.util.ByteString import akka.http.impl.engine.ws.Handshake import akka.http.impl.model.parser.CharacterClasses diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpResponseParser.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpResponseParser.scala index 02598005e6..c338307819 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpResponseParser.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpResponseParser.scala @@ -5,7 +5,7 @@ package akka.http.impl.engine.parsing import scala.annotation.tailrec -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import akka.http.impl.model.parser.CharacterClasses import akka.util.ByteString import akka.http.scaladsl.model._ diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/package.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/package.scala index fc3c4d35d9..11b1c08737 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/package.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/package.scala @@ -5,7 +5,7 @@ package akka.http.impl.engine import java.lang.{ StringBuilder ⇒ JStringBuilder } -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import scala.annotation.tailrec import akka.event.LoggingAdapter diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/HttpRequestRendererFactory.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/HttpRequestRendererFactory.scala index bd8cb499a8..63cf2c7fbb 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/HttpRequestRendererFactory.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/HttpRequestRendererFactory.scala @@ -4,7 +4,7 @@ package akka.http.impl.engine.rendering -import akka.http.ClientConnectionSettings +import akka.http.scaladsl.settings.ClientConnectionSettings import akka.http.scaladsl.model.RequestEntityAcceptance._ import scala.annotation.tailrec diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala index 82c832edf1..4b47319a79 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala @@ -19,7 +19,7 @@ import akka.stream._ import akka.stream.io._ import akka.stream.scaladsl._ import akka.stream.stage._ -import akka.http.ServerSettings +import akka.http.scaladsl.settings.ServerSettings import akka.http.impl.engine.HttpConnectionTimeoutException import akka.http.impl.engine.parsing.ParserOutput._ import akka.http.impl.engine.parsing._ diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/ws/WebSocketClientBlueprint.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/ws/WebSocketClientBlueprint.scala index a4e53034bc..cae2f15287 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/ws/WebSocketClientBlueprint.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/ws/WebSocketClientBlueprint.scala @@ -17,7 +17,7 @@ import akka.stream.BidiShape import akka.stream.io.{ SessionBytes, SendBytes, SslTlsInbound } import akka.stream.scaladsl._ -import akka.http.ClientConnectionSettings +import akka.http.scaladsl.settings.ClientConnectionSettings import akka.http.scaladsl.Http import akka.http.scaladsl.model.{ HttpResponse, HttpMethods } import akka.http.scaladsl.model.headers.Host diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala index 73358285ec..d765e91aaa 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala @@ -4,8 +4,8 @@ package akka.http.impl.model.parser -import akka.http.ParserSettings -import akka.http.ParserSettings.CookieParsingMode +import akka.http.scaladsl.settings.ParserSettings +import akka.http.scaladsl.settings.ParserSettings.CookieParsingMode import akka.http.scaladsl.model.headers.HttpCookiePair import scala.util.control.NonFatal import akka.http.impl.util.SingletonException diff --git a/akka-http-core/src/main/scala/akka/http/impl/settings/ClientConnectionSettingsImpl.scala b/akka-http-core/src/main/scala/akka/http/impl/settings/ClientConnectionSettingsImpl.scala new file mode 100644 index 0000000000..ce4ba64ddd --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/impl/settings/ClientConnectionSettingsImpl.scala @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.impl.settings + +import java.util.Random + +import akka.http.impl.engine.ws.Randoms +import akka.http.impl.util._ +import akka.http.scaladsl.model.headers.`User-Agent` +import akka.http.scaladsl.settings.ParserSettings +import akka.io.Inet.SocketOption +import com.typesafe.config.Config + +import scala.collection.immutable +import scala.concurrent.duration.{ Duration, FiniteDuration } + +/** INTERNAL API */ +private[akka] final case class ClientConnectionSettingsImpl( + userAgentHeader: Option[`User-Agent`], + connectingTimeout: FiniteDuration, + idleTimeout: Duration, + requestHeaderSizeHint: Int, + websocketRandomFactory: () ⇒ Random, + socketOptions: immutable.Seq[SocketOption], + parserSettings: ParserSettings) + extends akka.http.scaladsl.settings.ClientConnectionSettings { + + require(connectingTimeout >= Duration.Zero, "connectingTimeout must be >= 0") + require(requestHeaderSizeHint > 0, "request-size-hint must be > 0") +} + +object ClientConnectionSettingsImpl extends SettingsCompanion[ClientConnectionSettingsImpl]("akka.http.client") { + def fromSubConfig(root: Config, inner: Config) = { + val c = inner.withFallback(root.getConfig(prefix)) + new ClientConnectionSettingsImpl( + userAgentHeader = c.getString("user-agent-header").toOption.map(`User-Agent`(_)), + connectingTimeout = c getFiniteDuration "connecting-timeout", + idleTimeout = c getPotentiallyInfiniteDuration "idle-timeout", + requestHeaderSizeHint = c getIntBytes "request-header-size-hint", + websocketRandomFactory = Randoms.SecureRandomInstances, // can currently only be overridden from code + socketOptions = SocketOptionSettings.fromSubConfig(root, c.getConfig("socket-options")), + parserSettings = ParserSettingsImpl.fromSubConfig(root, c.getConfig("parsing"))) + } + +} \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/impl/settings/ConnectionPoolSettingsImpl.scala b/akka-http-core/src/main/scala/akka/http/impl/settings/ConnectionPoolSettingsImpl.scala new file mode 100644 index 0000000000..eb7544e47d --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/impl/settings/ConnectionPoolSettingsImpl.scala @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ + +package akka.http.impl.settings + +import akka.http.impl.util.SettingsCompanion +import akka.http.impl.util._ +import akka.http.scaladsl.settings.{ ConnectionPoolSettings, ClientConnectionSettings } +import com.typesafe.config.Config +import scala.concurrent.duration.Duration + +/** INTERNAL API */ +private[akka] final case class ConnectionPoolSettingsImpl( + val maxConnections: Int, + val maxRetries: Int, + val maxOpenRequests: Int, + val pipeliningLimit: Int, + val idleTimeout: Duration, + val connectionSettings: ClientConnectionSettings) + extends ConnectionPoolSettings { + + require(maxConnections > 0, "max-connections must be > 0") + require(maxRetries >= 0, "max-retries must be >= 0") + require(maxOpenRequests > 0 && (maxOpenRequests & (maxOpenRequests - 1)) == 0, "max-open-requests must be a power of 2 > 0") + require(pipeliningLimit > 0, "pipelining-limit must be > 0") + require(idleTimeout >= Duration.Zero, "idle-timeout must be >= 0") + +} + +object ConnectionPoolSettingsImpl extends SettingsCompanion[ConnectionPoolSettingsImpl]("akka.http.host-connection-pool") { + def fromSubConfig(root: Config, c: Config) = { + ConnectionPoolSettingsImpl( + c getInt "max-connections", + c getInt "max-retries", + c getInt "max-open-requests", + c getInt "pipelining-limit", + c getPotentiallyInfiniteDuration "idle-timeout", + ClientConnectionSettingsImpl.fromSubConfig(root, c.getConfig("client"))) + } +} diff --git a/akka-http-core/src/main/scala/akka/http/impl/settings/ConnectionPoolSetup.scala b/akka-http-core/src/main/scala/akka/http/impl/settings/ConnectionPoolSetup.scala new file mode 100644 index 0000000000..81a94e4685 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/impl/settings/ConnectionPoolSetup.scala @@ -0,0 +1,15 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ + +package akka.http.impl.settings + +import akka.event.LoggingAdapter +import akka.http.scaladsl.ConnectionContext +import akka.http.scaladsl.settings.ConnectionPoolSettings + +/** INTERNAL API */ +private[akka] final case class ConnectionPoolSetup( + settings: ConnectionPoolSettings, + connectionContext: ConnectionContext = ConnectionContext.noEncryption(), + log: LoggingAdapter) \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/impl/settings/HostConnectionPoolSetup.scala b/akka-http-core/src/main/scala/akka/http/impl/settings/HostConnectionPoolSetup.scala new file mode 100644 index 0000000000..7e74055eb9 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/impl/settings/HostConnectionPoolSetup.scala @@ -0,0 +1,9 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ + +package akka.http.impl.settings + +/** INTERNAL API */ +final case class HostConnectionPoolSetup(host: String, port: Int, setup: ConnectionPoolSetup) + diff --git a/akka-http-core/src/main/scala/akka/http/impl/settings/ParserSettingsImpl.scala b/akka-http-core/src/main/scala/akka/http/impl/settings/ParserSettingsImpl.scala new file mode 100644 index 0000000000..4ba0734caf --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/impl/settings/ParserSettingsImpl.scala @@ -0,0 +1,77 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.impl.settings + +import akka.http.scaladsl.settings.ParserSettings +import akka.http.scaladsl.settings.ParserSettings.{ ErrorLoggingVerbosity, CookieParsingMode } +import com.typesafe.config.Config +import scala.collection.JavaConverters._ +import akka.http.scaladsl.model.{ StatusCode, HttpMethod, Uri } +import akka.http.impl.util._ + +/** INTERNAL API */ +private[akka] final case class ParserSettingsImpl( + maxUriLength: Int, + maxMethodLength: Int, + maxResponseReasonLength: Int, + maxHeaderNameLength: Int, + maxHeaderValueLength: Int, + maxHeaderCount: Int, + maxContentLength: Long, + maxChunkExtLength: Int, + maxChunkSize: Int, + uriParsingMode: Uri.ParsingMode, + cookieParsingMode: CookieParsingMode, + illegalHeaderWarnings: Boolean, + errorLoggingVerbosity: ParserSettings.ErrorLoggingVerbosity, + headerValueCacheLimits: Map[String, Int], + includeTlsSessionInfoHeader: Boolean, + customMethods: String ⇒ Option[HttpMethod], + customStatusCodes: Int ⇒ Option[StatusCode]) + extends akka.http.scaladsl.settings.ParserSettings { + + require(maxUriLength > 0, "max-uri-length must be > 0") + require(maxMethodLength > 0, "max-method-length must be > 0") + require(maxResponseReasonLength > 0, "max-response-reason-length must be > 0") + require(maxHeaderNameLength > 0, "max-header-name-length must be > 0") + require(maxHeaderValueLength > 0, "max-header-value-length must be > 0") + require(maxHeaderCount > 0, "max-header-count must be > 0") + require(maxContentLength > 0, "max-content-length must be > 0") + require(maxChunkExtLength > 0, "max-chunk-ext-length must be > 0") + require(maxChunkSize > 0, "max-chunk-size must be > 0") + + override val defaultHeaderValueCacheLimit: Int = headerValueCacheLimits("default") + + override def headerValueCacheLimit(headerName: String): Int = + headerValueCacheLimits.getOrElse(headerName, defaultHeaderValueCacheLimit) +} + +object ParserSettingsImpl extends SettingsCompanion[ParserSettingsImpl]("akka.http.parsing") { + def fromSubConfig(root: Config, inner: Config) = { + val c = inner.withFallback(root.getConfig(prefix)) + val cacheConfig = c getConfig "header-cache" + + new ParserSettingsImpl( + c getIntBytes "max-uri-length", + c getIntBytes "max-method-length", + c getIntBytes "max-response-reason-length", + c getIntBytes "max-header-name-length", + c getIntBytes "max-header-value-length", + c getIntBytes "max-header-count", + c getPossiblyInfiniteBytes "max-content-length", + c getIntBytes "max-chunk-ext-length", + c getIntBytes "max-chunk-size", + Uri.ParsingMode(c getString "uri-parsing-mode"), + CookieParsingMode(c getString "cookie-parsing-mode"), + c getBoolean "illegal-header-warnings", + ErrorLoggingVerbosity(c getString "error-logging-verbosity"), + cacheConfig.entrySet.asScala.map(kvp ⇒ kvp.getKey -> cacheConfig.getInt(kvp.getKey))(collection.breakOut), + c getBoolean "tls-session-info-header", + _ ⇒ None, + _ ⇒ None) + } + +} + diff --git a/akka-http-core/src/main/scala/akka/http/impl/settings/ServerSettingsImpl.scala b/akka-http-core/src/main/scala/akka/http/impl/settings/ServerSettingsImpl.scala new file mode 100644 index 0000000000..ce818b341d --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/impl/settings/ServerSettingsImpl.scala @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ + +package akka.http.impl.settings + +import java.util.Random + +import akka.http.impl.engine.ws.Randoms +import akka.http.scaladsl.settings.{ ServerSettings, ParserSettings } +import com.typesafe.config.Config + +import scala.language.implicitConversions +import scala.collection.immutable +import scala.concurrent.duration._ + +import akka.http.javadsl.{ settings ⇒ js } +import akka.ConfigurationException +import akka.io.Inet.SocketOption + +import akka.http.impl.util._ + +import akka.http.scaladsl.model.HttpHeader +import akka.http.scaladsl.model.headers.{ Host, Server } + +/** INTERNAL API */ +private[akka] final case class ServerSettingsImpl( + serverHeader: Option[Server], + timeouts: ServerSettings.Timeouts, + maxConnections: Int, + pipeliningLimit: Int, + remoteAddressHeader: Boolean, + rawRequestUriHeader: Boolean, + transparentHeadRequests: Boolean, + verboseErrorMessages: Boolean, + responseHeaderSizeHint: Int, + backlog: Int, + socketOptions: immutable.Seq[SocketOption], + defaultHostHeader: Host, + websocketRandomFactory: () ⇒ Random, + parserSettings: ParserSettings) extends ServerSettings { + + require(0 < maxConnections, "max-connections must be > 0") + require(0 < pipeliningLimit && pipeliningLimit <= 1024, "pipelining-limit must be > 0 and <= 1024") + require(0 < responseHeaderSizeHint, "response-size-hint must be > 0") + require(0 < backlog, "backlog must be > 0") + +} + +object ServerSettingsImpl extends SettingsCompanion[ServerSettingsImpl]("akka.http.server") { + implicit def timeoutsShortcut(s: js.ServerSettings): js.ServerSettings.Timeouts = s.getTimeouts + + /** INTERNAL API */ + final case class Timeouts( + idleTimeout: Duration, + requestTimeout: Duration, + bindTimeout: FiniteDuration) extends ServerSettings.Timeouts { + require(idleTimeout > Duration.Zero, "idleTimeout must be infinite or > 0") + require(requestTimeout > Duration.Zero, "requestTimeout must be infinite or > 0") + require(bindTimeout > Duration.Zero, "bindTimeout must be > 0") + } + + def fromSubConfig(root: Config, c: Config) = new ServerSettingsImpl( + c.getString("server-header").toOption.map(Server(_)), + new Timeouts( + c getPotentiallyInfiniteDuration "idle-timeout", + c getPotentiallyInfiniteDuration "request-timeout", + c getFiniteDuration "bind-timeout"), + c getInt "max-connections", + c getInt "pipelining-limit", + c getBoolean "remote-address-header", + c getBoolean "raw-request-uri-header", + c getBoolean "transparent-head-requests", + c getBoolean "verbose-error-messages", + c getIntBytes "response-header-size-hint", + c getInt "backlog", + SocketOptionSettings.fromSubConfig(root, c.getConfig("socket-options")), + defaultHostHeader = + HttpHeader.parse("Host", c getString "default-host-header") match { + case HttpHeader.ParsingResult.Ok(x: Host, Nil) ⇒ x + case result ⇒ + val info = result.errors.head.withSummary("Configured `default-host-header` is illegal") + throw new ConfigurationException(info.formatPretty) + }, + Randoms.SecureRandomInstances, // can currently only be overridden from code + ParserSettingsImpl.fromSubConfig(root, c.getConfig("parsing"))) + + // def apply(optionalSettings: Option[ServerSettings])(implicit actorRefFactory: ActorRefFactory): ServerSettings = + // optionalSettings getOrElse apply(actorSystem) + +} \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/JavaMapping.scala b/akka-http-core/src/main/scala/akka/http/impl/util/JavaMapping.scala index e147a094af..d38cf6cb9e 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/JavaMapping.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/JavaMapping.scala @@ -16,6 +16,7 @@ import akka.{ NotUsed, japi } import akka.http.impl.model.{ JavaQuery, JavaUri } import akka.http.javadsl.{ model ⇒ jm, HttpConnectionContext, ConnectionContext, HttpsConnectionContext } import akka.http.scaladsl.{ model ⇒ sm } +import akka.http.javadsl.{ settings ⇒ js } import scala.compat.java8.OptionConverters._ @@ -168,6 +169,14 @@ private[http] object JavaMapping { implicit object HttpConnectionContext extends Inherited[HttpConnectionContext, akka.http.scaladsl.HttpConnectionContext] implicit object HttpsConnectionContext extends Inherited[HttpsConnectionContext, akka.http.scaladsl.HttpsConnectionContext] + implicit object ClientConnectionSettings extends Inherited[js.ClientConnectionSettings, akka.http.scaladsl.settings.ClientConnectionSettings] + implicit object ConnectionPoolSettings extends Inherited[js.ConnectionPoolSettings, akka.http.scaladsl.settings.ConnectionPoolSettings] + implicit object ParserSettings extends Inherited[js.ParserSettings, akka.http.scaladsl.settings.ParserSettings] + implicit object CookieParsingMode extends Inherited[js.ParserSettings.CookieParsingMode, akka.http.scaladsl.settings.ParserSettings.CookieParsingMode] + implicit object ErrorLoggingVerbosity extends Inherited[js.ParserSettings.ErrorLoggingVerbosity, akka.http.scaladsl.settings.ParserSettings.ErrorLoggingVerbosity] + implicit object ServerSettings extends Inherited[js.ServerSettings, akka.http.scaladsl.settings.ServerSettings] + implicit object ServerSettingsT extends Inherited[js.ServerSettings.Timeouts, akka.http.scaladsl.settings.ServerSettings.Timeouts] + implicit object DateTime extends Inherited[jm.DateTime, akka.http.scaladsl.model.DateTime] implicit object ContentType extends Inherited[jm.ContentType, sm.ContentType] @@ -198,9 +207,10 @@ private[http] object JavaMapping { implicit object TransferEncoding extends Inherited[jm.TransferEncoding, sm.TransferEncoding] implicit object HostHeader extends Inherited[jm.headers.Host, sm.headers.Host] - + implicit object Server extends Inherited[jm.headers.Server, sm.headers.Server] implicit object ByteRange extends Inherited[jm.headers.ByteRange, sm.headers.ByteRange] implicit object CacheDirective extends Inherited[jm.headers.CacheDirective, sm.headers.CacheDirective] + implicit object UserAgent extends Inherited[jm.headers.UserAgent, sm.headers.`User-Agent`] implicit object ContentDispositionType extends Inherited[jm.headers.ContentDispositionType, sm.headers.ContentDispositionType] implicit object EntityTag extends Inherited[jm.headers.EntityTag, sm.headers.EntityTag] implicit object EntityTagRange extends Inherited[jm.headers.EntityTagRange, sm.headers.EntityTagRange] @@ -228,6 +238,7 @@ private[http] object JavaMapping { def toScala(javaObject: J): Uri.S = cast[JavaUri](javaObject).uri def toJava(scalaObject: S): Uri.J = JavaUri(scalaObject) } + implicit object UriParsingMode extends Inherited[jm.Uri.ParsingMode, akka.http.scaladsl.model.Uri.ParsingMode] implicit object Query extends JavaMapping[jm.Query, sm.Uri.Query] { def toScala(javaObject: J): Query.S = cast[JavaQuery](javaObject).query diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/SettingsCompanion.scala b/akka-http-core/src/main/scala/akka/http/impl/util/SettingsCompanion.scala index 75b8c93b84..80a132abd5 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/SettingsCompanion.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/SettingsCompanion.scala @@ -10,7 +10,7 @@ import com.typesafe.config.ConfigFactory._ import scala.util.control.NonFatal import scala.collection.immutable.ListMap import scala.collection.JavaConverters._ -import akka.actor.ActorSystem +import akka.actor.{ ActorRefFactory, ActorSystem } /** * INTERNAL API @@ -19,6 +19,9 @@ private[http] abstract class SettingsCompanion[T](protected val prefix: String) private final val MaxCached = 8 private[this] var cache = ListMap.empty[ActorSystem, T] + implicit def default(implicit refFactory: ActorRefFactory): T = + apply(actorSystem) + def apply(system: ActorSystem): T = // we use and update the cache without any synchronization, // there are two possible "problems" resulting from this: diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/SocketOptionSettings.scala b/akka-http-core/src/main/scala/akka/http/impl/util/SocketOptionSettings.scala index 6bf558689a..ff8f238dce 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/SocketOptionSettings.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/SocketOptionSettings.scala @@ -12,7 +12,7 @@ import akka.io.Inet.SocketOption import com.typesafe.config.Config private[http] object SocketOptionSettings { - def fromSubConfig(root: Config, c: Config): immutable.Traversable[SocketOption] = { + def fromSubConfig(root: Config, c: Config): immutable.Seq[SocketOption] = { def so[T](setting: String)(f: (Config, String) ⇒ T)(cons: T ⇒ SocketOption): List[SocketOption] = c.getString(setting) match { case "undefined" ⇒ Nil diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/HostConnectionPool.scala b/akka-http-core/src/main/scala/akka/http/javadsl/HostConnectionPool.scala index 0470b4e95a..7fdd8ec939 100644 --- a/akka-http-core/src/main/scala/akka/http/javadsl/HostConnectionPool.scala +++ b/akka-http-core/src/main/scala/akka/http/javadsl/HostConnectionPool.scala @@ -4,7 +4,7 @@ package akka.http.javadsl -import akka.http.HostConnectionPoolSetup +import akka.http.impl.settings.HostConnectionPoolSetup trait HostConnectionPool { def setup: HostConnectionPoolSetup diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala b/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala index 1dcdd0e0da..7a7d0a1b8e 100644 --- a/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala +++ b/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala @@ -6,10 +6,12 @@ package akka.http.javadsl import java.net.InetSocketAddress import java.util.Optional +import akka.http.impl.settings.HostConnectionPoolSetup import akka.http.impl.util.JavaMapping import akka.http.impl.util.JavaMapping.HttpsConnectionContext import akka.http.javadsl.model.ws._ -import akka.{ stream, NotUsed } +import akka.http.javadsl.settings.{ ConnectionPoolSettings, ClientConnectionSettings, ServerSettings } +import akka.{ NotUsed, stream } import akka.stream.io.{ SslTlsInbound, SslTlsOutbound } import scala.language.implicitConversions import scala.concurrent.Future @@ -44,29 +46,29 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { private lazy val delegate = akka.http.scaladsl.Http(system) /** - * Constructs a server layer stage using the configured default [[ServerSettings]]. The returned [[BidiFlow]] isn't + * Constructs a server layer stage using the configured default [[akka.http.javadsl.settings.ServerSettings]]. The returned [[BidiFlow]] isn't * reusable and can only be materialized once. */ def serverLayer(materializer: Materializer): BidiFlow[HttpResponse, SslTlsOutbound, SslTlsInbound, HttpRequest, NotUsed] = adaptServerLayer(delegate.serverLayer()(materializer)) /** - * Constructs a server layer stage using the given [[ServerSettings]]. The returned [[BidiFlow]] isn't reusable and + * Constructs a server layer stage using the given [[akka.http.javadsl.settings.ServerSettings]]. The returned [[BidiFlow]] isn't reusable and * can only be materialized once. */ def serverLayer(settings: ServerSettings, materializer: Materializer): BidiFlow[HttpResponse, SslTlsOutbound, SslTlsInbound, HttpRequest, NotUsed] = - adaptServerLayer(delegate.serverLayer(settings)(materializer)) + adaptServerLayer(delegate.serverLayer(settings.asScala)(materializer)) /** - * Constructs a server layer stage using the given [[ServerSettings]]. The returned [[BidiFlow]] isn't reusable and + * Constructs a server layer stage using the given [[akka.http.javadsl.settings.ServerSettings]]. The returned [[BidiFlow]] isn't reusable and * can only be materialized once. The `remoteAddress`, if provided, will be added as a header to each [[HttpRequest]] * this layer produces if the `akka.http.server.remote-address-header` configuration option is enabled. */ def serverLayer(settings: ServerSettings, remoteAddress: Optional[InetSocketAddress], materializer: Materializer): BidiFlow[HttpResponse, SslTlsOutbound, SslTlsInbound, HttpRequest, NotUsed] = - adaptServerLayer(delegate.serverLayer(settings, remoteAddress.asScala)(materializer)) + adaptServerLayer(delegate.serverLayer(settings.asScala, remoteAddress.asScala)(materializer)) /** * Constructs a server layer stage using the given [[ServerSettings]]. The returned [[BidiFlow]] isn't reusable and @@ -77,7 +79,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { remoteAddress: Optional[InetSocketAddress], log: LoggingAdapter, materializer: Materializer): BidiFlow[HttpResponse, SslTlsOutbound, SslTlsInbound, HttpRequest, NotUsed] = - adaptServerLayer(delegate.serverLayer(settings, remoteAddress.asScala, log)(materializer)) + adaptServerLayer(delegate.serverLayer(settings.asScala, remoteAddress.asScala, log)(materializer)) /** * Creates a [[Source]] of [[IncomingConnection]] instances which represents a prospective HTTP server binding @@ -110,7 +112,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { connectionContext: ConnectionContext, settings: ServerSettings, materializer: Materializer): Source[IncomingConnection, CompletionStage[ServerBinding]] = - new Source(delegate.bind(interface, port, settings = settings, connectionContext = ConnectionContext.noEncryption().asScala)(materializer) + new Source(delegate.bind(interface, port, settings = settings.asScala, connectionContext = ConnectionContext.noEncryption().asScala)(materializer) .map(new IncomingConnection(_)) .mapMaterializedValue(_.map(new ServerBinding(_))(ec).toJava)) @@ -150,7 +152,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { settings: ServerSettings, log: LoggingAdapter, materializer: Materializer): Source[IncomingConnection, CompletionStage[ServerBinding]] = - new Source(delegate.bind(interface, port, ConnectionContext.noEncryption().asScala, settings, log)(materializer) + new Source(delegate.bind(interface, port, ConnectionContext.noEncryption().asScala, settings.asScala, log)(materializer) .map(new IncomingConnection(_)) .mapMaterializedValue(_.map(new ServerBinding(_))(ec).toJava)) @@ -197,7 +199,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { log: LoggingAdapter, materializer: Materializer): CompletionStage[ServerBinding] = delegate.bindAndHandle(handler.asInstanceOf[Flow[sm.HttpRequest, sm.HttpResponse, _]].asScala, - interface, port, connectionContext.asScala, settings, log)(materializer) + interface, port, connectionContext.asScala, settings.asScala, log)(materializer) .map(new ServerBinding(_))(ec).toJava /** @@ -241,7 +243,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { log: LoggingAdapter, materializer: Materializer): CompletionStage[ServerBinding] = delegate.bindAndHandleSync(handler.apply(_).asScala, - interface, port, connectionContext.asScala, settings, log)(materializer) + interface, port, connectionContext.asScala, settings.asScala, log)(materializer) .map(new ServerBinding(_))(ec).toJava /** @@ -284,21 +286,21 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { parallelism: Int, log: LoggingAdapter, materializer: Materializer): CompletionStage[ServerBinding] = delegate.bindAndHandleAsync(handler.apply(_).toScala, - interface, port, connectionContext.asScala, settings, parallelism, log)(materializer) + interface, port, connectionContext.asScala, settings.asScala, parallelism, log)(materializer) .map(new ServerBinding(_))(ec).toJava /** - * Constructs a client layer stage using the configured default [[ClientConnectionSettings]]. + * Constructs a client layer stage using the configured default [[akka.http.javadsl.settings.ClientConnectionSettings]]. */ def clientLayer(hostHeader: headers.Host): BidiFlow[HttpRequest, SslTlsOutbound, SslTlsInbound, HttpResponse, NotUsed] = adaptClientLayer(delegate.clientLayer(JavaMapping.toScala(hostHeader))) /** - * Constructs a client layer stage using the given [[ClientConnectionSettings]]. + * Constructs a client layer stage using the given [[akka.http.javadsl.settings.ClientConnectionSettings]]. */ def clientLayer(hostHeader: headers.Host, settings: ClientConnectionSettings): BidiFlow[HttpRequest, SslTlsOutbound, SslTlsInbound, HttpResponse, NotUsed] = - adaptClientLayer(delegate.clientLayer(JavaMapping.toScala(hostHeader), settings)) + adaptClientLayer(delegate.clientLayer(JavaMapping.toScala(hostHeader), settings.asScala)) /** * Constructs a client layer stage using the given [[ClientConnectionSettings]]. @@ -306,7 +308,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { def clientLayer(hostHeader: headers.Host, settings: ClientConnectionSettings, log: LoggingAdapter): BidiFlow[HttpRequest, SslTlsOutbound, SslTlsInbound, HttpResponse, NotUsed] = - adaptClientLayer(delegate.clientLayer(JavaMapping.toScala(hostHeader), settings, log)) + adaptClientLayer(delegate.clientLayer(JavaMapping.toScala(hostHeader), settings.asScala, log)) /** * Creates a [[Flow]] representing a prospective HTTP client connection to the given endpoint. @@ -340,8 +342,8 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { log: LoggingAdapter): Flow[HttpRequest, HttpResponse, CompletionStage[OutgoingConnection]] = adaptOutgoingFlow { connectionContext match { - case https: HttpsConnectionContext ⇒ delegate.outgoingConnectionHttps(host, port, https.asScala, localAddress.asScala, settings, log) - case _ ⇒ delegate.outgoingConnection(host, port, localAddress.asScala, settings, log) + case https: HttpsConnectionContext ⇒ delegate.outgoingConnectionHttps(host, port, https.asScala, localAddress.asScala, settings.asScala, log) + case _ ⇒ delegate.outgoingConnection(host, port, localAddress.asScala, settings.asScala, log) } } @@ -389,8 +391,8 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { log: LoggingAdapter, materializer: Materializer): Flow[Pair[HttpRequest, T], Pair[Try[HttpResponse], T], HostConnectionPool] = adaptTupleFlow { to.effectiveConnectionContext(defaultClientHttpsContext) match { - case https: HttpsConnectionContext ⇒ delegate.newHostConnectionPoolHttps[T](to.host, to.port, https.asScala, settings, log)(materializer) - case _ ⇒ delegate.newHostConnectionPool[T](to.host, to.port, settings, log)(materializer) + case https: HttpsConnectionContext ⇒ delegate.newHostConnectionPoolHttps[T](to.host, to.port, https.asScala, settings.asScala, log)(materializer) + case _ ⇒ delegate.newHostConnectionPool[T](to.host, to.port, settings.asScala, log)(materializer) } } @@ -442,7 +444,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { def cachedHostConnectionPool[T](to: ConnectHttp, settings: ConnectionPoolSettings, log: LoggingAdapter, materializer: Materializer): Flow[Pair[HttpRequest, T], Pair[Try[HttpResponse], T], HostConnectionPool] = - adaptTupleFlow(delegate.cachedHostConnectionPoolHttps[T](to.host, to.port, to.effectiveConnectionContext(defaultClientHttpsContext).asScala, settings, log)(materializer)) + adaptTupleFlow(delegate.cachedHostConnectionPoolHttps[T](to.host, to.port, to.effectiveConnectionContext(defaultClientHttpsContext).asScala, settings.asScala, log)(materializer)) /** * Creates a new "super connection pool flow", which routes incoming requests to a (cached) host connection pool @@ -477,7 +479,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { def superPool[T](settings: ConnectionPoolSettings, connectionContext: HttpsConnectionContext, log: LoggingAdapter, materializer: Materializer): Flow[Pair[HttpRequest, T], Pair[Try[HttpResponse], T], NotUsed] = - adaptTupleFlow(delegate.superPool[T](connectionContext.asScala, settings, log)(materializer)) + adaptTupleFlow(delegate.superPool[T](connectionContext.asScala, settings.asScala, log)(materializer)) /** * Creates a new "super connection pool flow", which routes incoming requests to a (cached) host connection pool @@ -496,7 +498,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { */ def superPool[T](settings: ConnectionPoolSettings, log: LoggingAdapter, materializer: Materializer): Flow[Pair[HttpRequest, T], Pair[Try[HttpResponse], T], NotUsed] = - adaptTupleFlow(delegate.superPool[T](defaultClientHttpsContext.asScala, settings, log)(materializer)) + adaptTupleFlow(delegate.superPool[T](defaultClientHttpsContext.asScala, settings.asScala, log)(materializer)) /** * Fires a single [[HttpRequest]] across the (cached) host connection pool for the request's @@ -535,7 +537,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { connectionContext: HttpsConnectionContext, settings: ConnectionPoolSettings, log: LoggingAdapter, materializer: Materializer): CompletionStage[HttpResponse] = - delegate.singleRequest(request.asScala, connectionContext.asScala, settings, log)(materializer).toJava + delegate.singleRequest(request.asScala, connectionContext.asScala, settings.asScala, log)(materializer).toJava /** * Constructs a WebSocket [[BidiFlow]]. @@ -553,7 +555,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { */ def webSocketClientLayer(request: WebSocketRequest, settings: ClientConnectionSettings): BidiFlow[Message, SslTlsOutbound, SslTlsInbound, Message, CompletionStage[WebSocketUpgradeResponse]] = - adaptWsBidiFlow(delegate.webSocketClientLayer(request.asScala, settings)) + adaptWsBidiFlow(delegate.webSocketClientLayer(request.asScala, settings.asScala)) /** * Constructs a WebSocket [[BidiFlow]] using the configured default [[ClientConnectionSettings]], @@ -564,7 +566,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { def webSocketClientLayer(request: WebSocketRequest, settings: ClientConnectionSettings, log: LoggingAdapter): BidiFlow[Message, SslTlsOutbound, SslTlsInbound, Message, CompletionStage[WebSocketUpgradeResponse]] = - adaptWsBidiFlow(delegate.webSocketClientLayer(request.asScala, settings, log)) + adaptWsBidiFlow(delegate.webSocketClientLayer(request.asScala, settings.asScala, log)) /** * Constructs a flow that once materialized establishes a WebSocket connection to the given Uri. @@ -587,7 +589,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { settings: ClientConnectionSettings, log: LoggingAdapter): Flow[Message, Message, CompletionStage[WebSocketUpgradeResponse]] = adaptWsFlow { - delegate.webSocketClientFlow(request.asScala, connectionContext.asScala, localAddress.asScala, settings, log) + delegate.webSocketClientFlow(request.asScala, connectionContext.asScala, localAddress.asScala, settings.asScala, log) } /** @@ -639,7 +641,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { adaptWsFlow[T](clientFlow), connectionContext.asScala, localAddress.asScala, - settings, + settings.asScala, log)(materializer) } diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/settings/ClientConnectionSettings.scala b/akka-http-core/src/main/scala/akka/http/javadsl/settings/ClientConnectionSettings.scala new file mode 100644 index 0000000000..7005cd2db7 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/javadsl/settings/ClientConnectionSettings.scala @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ +package akka.http.javadsl.settings + +import java.util.{ Optional, Random } + +import akka.http.impl.settings.ClientConnectionSettingsImpl +import akka.http.javadsl.model.headers.UserAgent +import akka.io.Inet.SocketOption +import com.typesafe.config.Config + +import akka.http.impl.util.JavaMapping.Implicits._ +import scala.collection.JavaConverters._ +import scala.compat.java8.OptionConverters._ +import scala.concurrent.duration.{ Duration, FiniteDuration } + +abstract class ClientConnectionSettings { + def getUserAgentHeader: Optional[UserAgent] + def getConnectingTimeout: FiniteDuration + def getIdleTimeout: Duration + def getRequestHeaderSizeHint: Int + def getWebsocketRandomFactory: java.util.function.Supplier[Random] + def getSocketOptions: java.lang.Iterable[SocketOption] + def getParserSettings: ParserSettings + + // --- + + def withUserAgentHeader(newValue: Optional[UserAgent]): ClientConnectionSettings = self.copy(userAgentHeader = newValue.asScala.map(_.asScala)) + def withConnectingTimeout(newValue: FiniteDuration): ClientConnectionSettings = self.copy(connectingTimeout = newValue) + def withIdleTimeout(newValue: Duration): ClientConnectionSettings = self.copy(idleTimeout = newValue) + def withRequestHeaderSizeHint(newValue: Int): ClientConnectionSettings = self.copy(requestHeaderSizeHint = newValue) + def withWebsocketRandomFactory(newValue: java.util.function.Supplier[Random]): ClientConnectionSettings = self.copy(websocketRandomFactory = () ⇒ newValue.get()) + def withSocketOptions(newValue: java.lang.Iterable[SocketOption]): ClientConnectionSettings = self.copy(socketOptions = newValue.asScala.toList) + def withParserSettings(newValue: ParserSettings): ClientConnectionSettings = self.copy(parserSettings = newValue.asScala) + + /** INTERNAL API: safe by construction */ + protected val self = this.asInstanceOf[ClientConnectionSettingsImpl] +} + +object ClientConnectionSettings extends SettingsCompanion[ClientConnectionSettings] { + def create(config: Config): ClientConnectionSettings = ClientConnectionSettingsImpl(config) + def create(configOverrides: String): ClientConnectionSettings = ClientConnectionSettingsImpl(configOverrides) +} diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/settings/ConnectionPoolSettings.scala b/akka-http-core/src/main/scala/akka/http/javadsl/settings/ConnectionPoolSettings.scala new file mode 100644 index 0000000000..c380f4396e --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/javadsl/settings/ConnectionPoolSettings.scala @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ +package akka.http.javadsl.settings + +import akka.http.impl.settings.ConnectionPoolSettingsImpl +import com.typesafe.config.Config + +import scala.concurrent.duration.Duration +import akka.http.impl.util.JavaMapping.Implicits._ + +abstract class ConnectionPoolSettings { + def getMaxConnections: Int + def getMaxRetries: Int + def getMaxOpenRequests: Int + def getPipeliningLimit: Int + def getIdleTimeout: Duration + def getConnectionSettings: ClientConnectionSettings + + // --- + + def withMaxConnections(n: Int): ConnectionPoolSettings = self.copy(maxConnections = n) + def withMaxRetries(n: Int): ConnectionPoolSettings = self.copy(maxRetries = n) + def withMaxOpenRequests(newValue: Int): ConnectionPoolSettings = self.copy(maxOpenRequests = newValue) + def withPipeliningLimit(newValue: Int): ConnectionPoolSettings = self.copy(pipeliningLimit = newValue) + def withIdleTimeout(newValue: Duration): ConnectionPoolSettings = self.copy(idleTimeout = newValue) + def withConnectionSettings(newValue: ClientConnectionSettings): ConnectionPoolSettings = self.copy(connectionSettings = newValue.asScala) + + /** INTERNAL API */ + protected def self = this.asInstanceOf[ConnectionPoolSettingsImpl] +} + +object ConnectionPoolSettings extends SettingsCompanion[ConnectionPoolSettings] { + override def create(config: Config): ConnectionPoolSettings = ConnectionPoolSettingsImpl(config) + override def create(configOverrides: String): ConnectionPoolSettings = ConnectionPoolSettingsImpl(configOverrides) +} \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/settings/ParserSettings.scala b/akka-http-core/src/main/scala/akka/http/javadsl/settings/ParserSettings.scala new file mode 100644 index 0000000000..d21bcc94b4 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/javadsl/settings/ParserSettings.scala @@ -0,0 +1,78 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ +package akka.http.javadsl.settings + +import java.util.Optional + +import akka.http.impl.engine.parsing.BodyPartParser +import akka.http.impl.settings.ParserSettingsImpl +import java.{ util ⇒ ju } +import akka.http.impl.util.JavaMapping.Implicits._ +import scala.annotation.varargs +import scala.collection.JavaConverters._ +import scala.compat.java8.OptionConverters + +import akka.http.javadsl.model.{ HttpMethod, StatusCode, Uri } +import com.typesafe.config.Config + +abstract class ParserSettings extends BodyPartParser.Settings { + def getMaxUriLength: Int + def getMaxMethodLength: Int + def getMaxResponseReasonLength: Int + def getMaxHeaderNameLength: Int + def getMaxHeaderValueLength: Int + def getMaxHeaderCount: Int + def getMaxContentLength: Long + def getMaxChunkExtLength: Int + def getMaxChunkSize: Int + def getUriParsingMode: Uri.ParsingMode + def getCookieParsingMode: ParserSettings.CookieParsingMode + def getIllegalHeaderWarnings: Boolean + def getErrorLoggingVerbosity: ParserSettings.ErrorLoggingVerbosity + def getHeaderValueCacheLimits: ju.Map[String, Int] + def getIncludeTlsSessionInfoHeader: Boolean + def headerValueCacheLimits: Map[String, Int] + def getCustomMethods: java.util.function.Function[String, Optional[HttpMethod]] + def getCustomStatusCodes: java.util.function.Function[Int, Optional[StatusCode]] + + // --- + + def withMaxUriLength(newValue: Int): ParserSettings = self.copy(maxUriLength = newValue) + def withMaxMethodLength(newValue: Int): ParserSettings = self.copy(maxMethodLength = newValue) + def withMaxResponseReasonLength(newValue: Int): ParserSettings = self.copy(maxResponseReasonLength = newValue) + def withMaxHeaderNameLength(newValue: Int): ParserSettings = self.copy(maxHeaderNameLength = newValue) + def withMaxHeaderValueLength(newValue: Int): ParserSettings = self.copy(maxHeaderValueLength = newValue) + def withMaxHeaderCount(newValue: Int): ParserSettings = self.copy(maxHeaderCount = newValue) + def withMaxContentLength(newValue: Long): ParserSettings = self.copy(maxContentLength = newValue) + def withMaxChunkExtLength(newValue: Int): ParserSettings = self.copy(maxChunkExtLength = newValue) + def withMaxChunkSize(newValue: Int): ParserSettings = self.copy(maxChunkSize = newValue) + def withUriParsingMode(newValue: Uri.ParsingMode): ParserSettings = self.copy(uriParsingMode = newValue.asScala) + def withCookieParsingMode(newValue: ParserSettings.CookieParsingMode): ParserSettings = self.copy(cookieParsingMode = newValue.asScala) + def withIllegalHeaderWarnings(newValue: Boolean): ParserSettings = self.copy(illegalHeaderWarnings = newValue) + def withErrorLoggingVerbosity(newValue: ParserSettings.ErrorLoggingVerbosity): ParserSettings = self.copy(errorLoggingVerbosity = newValue.asScala) + def withHeaderValueCacheLimits(newValue: ju.Map[String, Int]): ParserSettings = self.copy(headerValueCacheLimits = newValue.asScala.toMap) + def withIncludeTlsSessionInfoHeader(newValue: Boolean): ParserSettings = self.copy(includeTlsSessionInfoHeader = newValue) + + // special --- + + def withCustomMethods(methods: HttpMethod*): ParserSettings = { + val map = methods.map(m ⇒ m.name -> m.asScala).toMap + self.copy(customMethods = map.get) + } + def withCustomStatusCodes(codes: StatusCode*): ParserSettings = { + val map = codes.map(c ⇒ c.intValue -> c.asScala).toMap + self.copy(customStatusCodes = map.get) + } + + /** INTERNAL API */ + protected def self = this.asInstanceOf[ParserSettingsImpl] +} + +object ParserSettings extends SettingsCompanion[ParserSettings] { + trait CookieParsingMode + trait ErrorLoggingVerbosity + + override def create(config: Config): ParserSettings = ParserSettingsImpl(config) + override def create(configOverrides: String): ParserSettings = ParserSettingsImpl(configOverrides) +} diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/settings/ServerSettings.scala b/akka-http-core/src/main/scala/akka/http/javadsl/settings/ServerSettings.scala new file mode 100644 index 0000000000..9b0b7fe078 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/javadsl/settings/ServerSettings.scala @@ -0,0 +1,69 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ +package akka.http.javadsl.settings + +import java.util.{ Optional, Random } + +import akka.http.impl.settings.ServerSettingsImpl +import akka.http.javadsl.model.headers.Host +import akka.http.javadsl.model.headers.Server +import akka.io.Inet.SocketOption +import akka.http.impl.util.JavaMapping.Implicits._ +import scala.collection.JavaConverters._ +import scala.compat.java8.OptionConverters._ + +import scala.concurrent.duration.{ Duration, FiniteDuration } + +abstract class ServerSettings { + def getServerHeader: Optional[Server] + def getTimeouts: ServerSettings.Timeouts + def getMaxConnections: Int + def getPipeliningLimit: Int + def getRemoteAddressHeader: Boolean + def getRawRequestUriHeader: Boolean + def getTransparentHeadRequests: Boolean + def getVerboseErrorMessages: Boolean + def getResponseHeaderSizeHint: Int + def getBacklog: Int + def getSocketOptions: java.lang.Iterable[SocketOption] + def getDefaultHostHeader: Host + def getWebsocketRandomFactory: java.util.function.Supplier[Random] + def getParserSettings: ParserSettings + + // --- + + def withServerHeader(newValue: Optional[Server]): ServerSettings = self.copy(serverHeader = newValue.asScala.map(_.asScala)) + def withTimeouts(newValue: ServerSettings.Timeouts): ServerSettings = self.copy(timeouts = newValue.asScala) + def withMaxConnections(newValue: Int): ServerSettings = self.copy(maxConnections = newValue) + def withPipeliningLimit(newValue: Int): ServerSettings = self.copy(pipeliningLimit = newValue) + def withRemoteAddressHeader(newValue: Boolean): ServerSettings = self.copy(remoteAddressHeader = newValue) + def withRawRequestUriHeader(newValue: Boolean): ServerSettings = self.copy(rawRequestUriHeader = newValue) + def withTransparentHeadRequests(newValue: Boolean): ServerSettings = self.copy(transparentHeadRequests = newValue) + def withVerboseErrorMessages(newValue: Boolean): ServerSettings = self.copy(verboseErrorMessages = newValue) + def withResponseHeaderSizeHint(newValue: Int): ServerSettings = self.copy(responseHeaderSizeHint = newValue) + def withBacklog(newValue: Int): ServerSettings = self.copy(backlog = newValue) + def withSocketOptions(newValue: java.lang.Iterable[SocketOption]): ServerSettings = self.copy(socketOptions = newValue.asScala.toList) + def withDefaultHostHeader(newValue: Host): ServerSettings = self.copy(defaultHostHeader = newValue.asScala) + def withParserSettings(newValue: ParserSettings): ServerSettings = self.copy(parserSettings = newValue.asScala) + def withWebsocketRandomFactory(newValue: java.util.function.Supplier[Random]): ServerSettings = self.copy(websocketRandomFactory = () ⇒ newValue.get()) + + /** INTERNAL API */ + protected def self = this.asInstanceOf[ServerSettingsImpl] +} + +object ServerSettings { + trait Timeouts { + def idleTimeout: Duration + def requestTimeout: Duration + def bindTimeout: FiniteDuration + + // --- + def withIdleTimeout(newValue: Duration): ServerSettings.Timeouts = self.copy(idleTimeout = newValue) + def withRequestTimeout(newValue: Duration): ServerSettings.Timeouts = self.copy(requestTimeout = newValue) + def withBindTimeout(newValue: FiniteDuration): ServerSettings.Timeouts = self.copy(bindTimeout = newValue) + + /** INTERNAL API */ + protected def self = this.asInstanceOf[ServerSettingsImpl.Timeouts] + } +} \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/settings/SettingsCompanion.scala b/akka-http-core/src/main/scala/akka/http/javadsl/settings/SettingsCompanion.scala new file mode 100644 index 0000000000..c9f7414d43 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/javadsl/settings/SettingsCompanion.scala @@ -0,0 +1,30 @@ +package akka.http.javadsl.settings + +import akka.actor.ActorSystem +import com.typesafe.config.Config + +trait SettingsCompanion[T] { + + /** + * Creates an instance of settings using the configuration provided by the given ActorSystem. + * + * Java API + */ + final def create(system: ActorSystem): T = create(system.settings.config) + + /** + * Creates an instance of settings using the given Config. + * + * Java API + */ + def create(config: Config): T + + /** + * Create an instance of settings using the given String of config overrides to override + * settings set in the class loader of this class (i.e. by application.conf or reference.conf files in + * the class loader of this class). + * + * Java API + */ + def create(configOverrides: String): T +} diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala index 539e8cdd3c..265560b18a 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala @@ -15,10 +15,12 @@ import akka.http.impl.engine.HttpConnectionTimeoutException import akka.http.impl.engine.client._ import akka.http.impl.engine.server._ import akka.http.impl.engine.ws.WebSocketClientBlueprint +import akka.http.impl.settings.{ ConnectionPoolSetup, HostConnectionPoolSetup } import akka.http.impl.util.StreamUtils import akka.http.scaladsl.model._ import akka.http.scaladsl.model.headers.Host import akka.http.scaladsl.model.ws.{ Message, WebSocketRequest, WebSocketUpgradeResponse } +import akka.http.scaladsl.settings.{ ServerSettings, ClientConnectionSettings, ConnectionPoolSettings } import akka.http.scaladsl.util.FastFuture import akka.NotUsed import akka.stream.Materializer @@ -68,7 +70,7 @@ class HttpExt(private val config: Config)(implicit val system: ActorSystem) exte * which is 80 for HTTP and 443 for HTTPS. * * To configure additional settings for a server started using this method, - * use the `akka.http.server` config section or pass in a [[ServerSettings]] explicitly. + * use the `akka.http.server` config section or pass in a [[akka.http.scaladsl.settings.ServerSettings]] explicitly. */ def bind(interface: String, port: Int = DefaultPortForProtocol, connectionContext: ConnectionContext = defaultServerHttpContext, @@ -297,6 +299,8 @@ class HttpExt(private val config: Config)(implicit val system: ActorSystem) exte } /** + * INTERNAL API + * * Starts a new connection pool to the given host and configuration and returns a [[Flow]] which dispatches * the requests from all its materializations across this pool. * While the started host connection pool internally shuts itself down automatically after the configured idle @@ -310,7 +314,7 @@ class HttpExt(private val config: Config)(implicit val system: ActorSystem) exte * In order to allow for easy response-to-request association the flow takes in a custom, opaque context * object of type `T` from the application which is emitted together with the corresponding response. */ - private def newHostConnectionPool[T](setup: HostConnectionPoolSetup)( + private[akka] def newHostConnectionPool[T](setup: HostConnectionPoolSetup)( implicit fm: Materializer): Flow[(HttpRequest, T), (Try[HttpResponse], T), HostConnectionPool] = { val gatewayFuture = FastFuture.successful(new PoolGateway(setup, Promise())) gatewayClientFlow(setup, gatewayFuture) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMethod.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMethod.scala index 8240613aba..d1e00b2968 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMethod.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMethod.scala @@ -33,8 +33,6 @@ final case class HttpMethod private[http] (override val value: String, isSafe: Boolean, isIdempotent: Boolean, requestEntityAcceptance: RequestEntityAcceptance) extends jm.HttpMethod with SingletonValueRenderable { - def name = value - override def isEntityAccepted: Boolean = requestEntityAcceptance.isEntityAccepted override def toString: String = s"HttpMethod($value)" } diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/Uri.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/Uri.scala index 53b5f48b9c..a1cfdd67da 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/Uri.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/Uri.scala @@ -599,8 +599,7 @@ object Uri { "pop3" -> 110, "nntp" -> 119, "imap" -> 143, "snmp" -> 161, "ldap" -> 389, "https" -> 443, "wss" -> 443, "imaps" -> 993, "nfs" -> 2049).withDefaultValue(-1) - sealed trait ParsingMode - + sealed trait ParsingMode extends akka.http.javadsl.model.Uri.ParsingMode object ParsingMode { case object Strict extends ParsingMode case object Relaxed extends ParsingMode diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ClientConnectionSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ClientConnectionSettings.scala new file mode 100644 index 0000000000..4c9a61118f --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ClientConnectionSettings.scala @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ +package akka.http.scaladsl.settings + +import java.lang.Iterable +import java.util.{ Optional, Random } +import java.util.function.Supplier + +import akka.actor.ActorSystem +import akka.http.impl.settings.ClientConnectionSettingsImpl +import akka.http.javadsl.model.headers.UserAgent +import akka.http.javadsl.{ settings ⇒ js } +import akka.http.scaladsl.model.headers.`User-Agent` +import akka.io.Inet.SocketOption +import com.typesafe.config.Config + +import scala.collection.immutable +import scala.compat.java8.OptionConverters +import scala.concurrent.duration.{ FiniteDuration, Duration } +import scala.collection.JavaConverters._ + +abstract class ClientConnectionSettings extends akka.http.javadsl.settings.ClientConnectionSettings { + def userAgentHeader: Option[`User-Agent`] + def connectingTimeout: FiniteDuration + def idleTimeout: Duration + def requestHeaderSizeHint: Int + def websocketRandomFactory: () ⇒ Random + def socketOptions: immutable.Seq[SocketOption] + def parserSettings: ParserSettings + + /* JAVA APIs */ + + final override def getConnectingTimeout: FiniteDuration = connectingTimeout + final override def getParserSettings: js.ParserSettings = parserSettings + final override def getIdleTimeout: Duration = idleTimeout + final override def getSocketOptions: Iterable[SocketOption] = socketOptions.asJava + final override def getUserAgentHeader: Optional[UserAgent] = OptionConverters.toJava(userAgentHeader) + final override def getRequestHeaderSizeHint: Int = requestHeaderSizeHint + final override def getWebsocketRandomFactory: Supplier[Random] = new Supplier[Random] { + override def get(): Random = websocketRandomFactory() + } + + // --- + + // overrides for more specific return type + override def withConnectingTimeout(newValue: FiniteDuration): ClientConnectionSettings = self.copy(connectingTimeout = newValue) + override def withIdleTimeout(newValue: Duration): ClientConnectionSettings = self.copy(idleTimeout = newValue) + override def withRequestHeaderSizeHint(newValue: Int): ClientConnectionSettings = self.copy(requestHeaderSizeHint = newValue) + + // overloads for idiomatic Scala use + def withWebsocketRandomFactory(newValue: () ⇒ Random): ClientConnectionSettings = self.copy(websocketRandomFactory = newValue) + def withUserAgentHeader(newValue: Option[`User-Agent`]): ClientConnectionSettings = self.copy(userAgentHeader = newValue) + def withSocketOptions(newValue: immutable.Seq[SocketOption]): ClientConnectionSettings = self.copy(socketOptions = newValue) + def withParserSettings(newValue: ParserSettings): ClientConnectionSettings = self.copy(parserSettings = newValue) +} + +object ClientConnectionSettings extends SettingsCompanion[ClientConnectionSettings] { + override def apply(config: Config): ClientConnectionSettings = ClientConnectionSettingsImpl(config) + override def apply(configOverrides: String): ClientConnectionSettings = ClientConnectionSettingsImpl(configOverrides) +} \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala new file mode 100644 index 0000000000..71954c8a07 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ +package akka.http.scaladsl.settings + +import akka.actor.ActorSystem +import akka.http.impl.settings.ConnectionPoolSettingsImpl +import akka.http.javadsl.{ settings ⇒ js } +import com.typesafe.config.Config + +import scala.concurrent.duration.Duration + +abstract class ConnectionPoolSettings extends js.ConnectionPoolSettings { + def maxConnections: Int + def maxRetries: Int + def maxOpenRequests: Int + def pipeliningLimit: Int + def idleTimeout: Duration + def connectionSettings: ClientConnectionSettings + + /* JAVA APIs */ + + final override def getConnectionSettings: js.ClientConnectionSettings = connectionSettings + final override def getPipeliningLimit: Int = pipeliningLimit + final override def getIdleTimeout: Duration = idleTimeout + final override def getMaxConnections: Int = maxConnections + final override def getMaxOpenRequests: Int = maxOpenRequests + final override def getMaxRetries: Int = maxRetries + + // --- + + // overrides for more precise return type + override def withMaxConnections(n: Int): ConnectionPoolSettings = self.copy(maxConnections = n) + override def withMaxRetries(n: Int): ConnectionPoolSettings = self.copy(maxRetries = n) + override def withMaxOpenRequests(newValue: Int): ConnectionPoolSettings = self.copy(maxOpenRequests = newValue) + override def withPipeliningLimit(newValue: Int): ConnectionPoolSettings = self.copy(pipeliningLimit = newValue) + override def withIdleTimeout(newValue: Duration): ConnectionPoolSettings = self.copy(idleTimeout = newValue) + + // overloads for idiomatic Scala use + def withConnectionSettings(newValue: ClientConnectionSettings): ConnectionPoolSettings = self.copy(connectionSettings = newValue) +} + +object ConnectionPoolSettings extends SettingsCompanion[ConnectionPoolSettings] { + override def apply(config: Config) = ConnectionPoolSettingsImpl(config) + override def apply(configOverrides: String) = ConnectionPoolSettingsImpl(configOverrides) +} \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ParserSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ParserSettings.scala new file mode 100644 index 0000000000..fabbd228c8 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ParserSettings.scala @@ -0,0 +1,124 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ +package akka.http.scaladsl.settings + +import java.util +import java.util.Optional +import java.util.function.Function + +import akka.http.impl.settings.ParserSettingsImpl +import akka.http.impl.util._ +import akka.http.scaladsl.model.HttpMethod +import akka.http.scaladsl.model.StatusCode +import akka.http.scaladsl.model.{ HttpMethod, StatusCode, Uri } +import akka.http.scaladsl.{ settings ⇒ js } +import com.typesafe.config.Config + +import scala.annotation.varargs +import scala.collection.JavaConverters._ +import scala.compat.java8.OptionConverters + +abstract class ParserSettings extends akka.http.javadsl.settings.ParserSettings { + def maxUriLength: Int + def maxMethodLength: Int + def maxResponseReasonLength: Int + def maxHeaderNameLength: Int + def maxHeaderValueLength: Int + def maxHeaderCount: Int + def maxContentLength: Long + def maxChunkExtLength: Int + def maxChunkSize: Int + def uriParsingMode: Uri.ParsingMode + def cookieParsingMode: ParserSettings.CookieParsingMode + def illegalHeaderWarnings: Boolean + def errorLoggingVerbosity: ParserSettings.ErrorLoggingVerbosity + def headerValueCacheLimits: Map[String, Int] + def includeTlsSessionInfoHeader: Boolean + def customMethods: String ⇒ Option[HttpMethod] + def customStatusCodes: Int ⇒ Option[StatusCode] + + /* Java APIs */ + override def getCookieParsingMode: js.ParserSettings.CookieParsingMode = cookieParsingMode + override def getHeaderValueCacheLimits: util.Map[String, Int] = headerValueCacheLimits.asJava + override def getMaxChunkExtLength = maxChunkExtLength + override def getUriParsingMode: akka.http.javadsl.model.Uri.ParsingMode = uriParsingMode + override def getMaxHeaderCount = maxHeaderCount + override def getMaxContentLength = maxContentLength + override def getMaxHeaderValueLength = maxHeaderValueLength + override def getIncludeTlsSessionInfoHeader = includeTlsSessionInfoHeader + override def getIllegalHeaderWarnings = illegalHeaderWarnings + override def getMaxHeaderNameLength = maxHeaderNameLength + override def getMaxChunkSize = maxChunkSize + override def getMaxResponseReasonLength = maxResponseReasonLength + override def getMaxUriLength = maxUriLength + override def getMaxMethodLength = maxMethodLength + override def getErrorLoggingVerbosity: js.ParserSettings.ErrorLoggingVerbosity = errorLoggingVerbosity + + override def getCustomMethods = new Function[String, Optional[akka.http.javadsl.model.HttpMethod]] { + override def apply(t: String) = OptionConverters.toJava(customMethods(t)) + } + override def getCustomStatusCodes = new Function[Int, Optional[akka.http.javadsl.model.StatusCode]] { + override def apply(t: Int) = OptionConverters.toJava(customStatusCodes(t)) + } + + // --- + + // override for more specific return type + override def withMaxUriLength(newValue: Int): ParserSettings = self.copy(maxUriLength = newValue) + override def withMaxMethodLength(newValue: Int): ParserSettings = self.copy(maxMethodLength = newValue) + override def withMaxResponseReasonLength(newValue: Int): ParserSettings = self.copy(maxResponseReasonLength = newValue) + override def withMaxHeaderNameLength(newValue: Int): ParserSettings = self.copy(maxHeaderNameLength = newValue) + override def withMaxHeaderValueLength(newValue: Int): ParserSettings = self.copy(maxHeaderValueLength = newValue) + override def withMaxHeaderCount(newValue: Int): ParserSettings = self.copy(maxHeaderCount = newValue) + override def withMaxContentLength(newValue: Long): ParserSettings = self.copy(maxContentLength = newValue) + override def withMaxChunkExtLength(newValue: Int): ParserSettings = self.copy(maxChunkExtLength = newValue) + override def withMaxChunkSize(newValue: Int): ParserSettings = self.copy(maxChunkSize = newValue) + override def withIllegalHeaderWarnings(newValue: Boolean): ParserSettings = self.copy(illegalHeaderWarnings = newValue) + override def withIncludeTlsSessionInfoHeader(newValue: Boolean): ParserSettings = self.copy(includeTlsSessionInfoHeader = newValue) + + // overloads for idiomatic Scala use + def withUriParsingMode(newValue: Uri.ParsingMode): ParserSettings = self.copy(uriParsingMode = newValue) + def withCookieParsingMode(newValue: ParserSettings.CookieParsingMode): ParserSettings = self.copy(cookieParsingMode = newValue) + def withErrorLoggingVerbosity(newValue: ParserSettings.ErrorLoggingVerbosity): ParserSettings = self.copy(errorLoggingVerbosity = newValue) + def withHeaderValueCacheLimits(newValue: Map[String, Int]): ParserSettings = self.copy(headerValueCacheLimits = newValue) + def withCustomMethods(methods: HttpMethod*): ParserSettings = { + val map = methods.map(m ⇒ m.name -> m).toMap + self.copy(customMethods = map.get) + } + def withCustomStatusCodes(codes: StatusCode*): ParserSettings = { + val map = codes.map(c ⇒ c.intValue -> c).toMap + self.copy(customStatusCodes = map.get) + } +} + +object ParserSettings extends SettingsCompanion[ParserSettings] { + trait CookieParsingMode extends akka.http.javadsl.settings.ParserSettings.CookieParsingMode + object CookieParsingMode { + case object RFC6265 extends CookieParsingMode + case object Raw extends CookieParsingMode + + def apply(mode: String): CookieParsingMode = mode.toRootLowerCase match { + case "rfc6265" ⇒ RFC6265 + case "raw" ⇒ Raw + } + } + + trait ErrorLoggingVerbosity extends akka.http.javadsl.settings.ParserSettings.ErrorLoggingVerbosity + object ErrorLoggingVerbosity { + case object Off extends ErrorLoggingVerbosity + case object Simple extends ErrorLoggingVerbosity + case object Full extends ErrorLoggingVerbosity + + def apply(string: String): ErrorLoggingVerbosity = + string.toRootLowerCase match { + case "off" ⇒ Off + case "simple" ⇒ Simple + case "full" ⇒ Full + case x ⇒ throw new IllegalArgumentException(s"[$x] is not a legal `error-logging-verbosity` setting") + } + } + + override def apply(config: Config): ParserSettings = ParserSettingsImpl(config) + override def apply(configOverrides: String): ParserSettings = ParserSettingsImpl(configOverrides) +} diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala new file mode 100644 index 0000000000..ae15b8e126 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2016 Typesafe Inc. + */ +package akka.http.scaladsl.settings + +import java.util.Random +import java.util.function.Supplier + +import akka.http.impl.settings.ServerSettingsImpl +import akka.http.impl.util.JavaMapping.Implicits._ +import akka.http.javadsl.{ model ⇒ jm, settings ⇒ js } +import akka.http.scaladsl.model.headers.Host +import akka.http.scaladsl.model.headers.Server +import akka.io.Inet.SocketOption +import com.typesafe.config.Config + +import scala.collection.JavaConverters._ +import scala.collection.immutable +import scala.compat.java8.OptionConverters +import scala.concurrent.duration.{ FiniteDuration, Duration } +import scala.language.implicitConversions + +abstract class ServerSettings extends akka.http.javadsl.settings.ServerSettings { + def serverHeader: Option[Server] + def timeouts: ServerSettings.Timeouts + def maxConnections: Int + def pipeliningLimit: Int + def remoteAddressHeader: Boolean + def rawRequestUriHeader: Boolean + def transparentHeadRequests: Boolean + def verboseErrorMessages: Boolean + def responseHeaderSizeHint: Int + def backlog: Int + def socketOptions: immutable.Seq[SocketOption] + def defaultHostHeader: Host + def websocketRandomFactory: () ⇒ Random + def parserSettings: ParserSettings + + /* Java APIs */ + + override def getBacklog = backlog + override def getDefaultHostHeader = defaultHostHeader.asJava + override def getPipeliningLimit = pipeliningLimit + override def getParserSettings: js.ParserSettings = parserSettings + override def getMaxConnections = maxConnections + override def getTransparentHeadRequests = transparentHeadRequests + override def getResponseHeaderSizeHint = responseHeaderSizeHint + override def getVerboseErrorMessages = verboseErrorMessages + override def getSocketOptions = socketOptions.asJava + override def getServerHeader = OptionConverters.toJava(serverHeader.map(_.asJava)) + override def getTimeouts = timeouts + override def getRawRequestUriHeader = rawRequestUriHeader + override def getRemoteAddressHeader = remoteAddressHeader + override def getWebsocketRandomFactory = new Supplier[Random] { + override def get(): Random = websocketRandomFactory() + } + + // --- + + // override for more specific return type + override def withMaxConnections(newValue: Int): ServerSettings = self.copy(maxConnections = newValue) + override def withPipeliningLimit(newValue: Int): ServerSettings = self.copy(pipeliningLimit = newValue) + override def withRemoteAddressHeader(newValue: Boolean): ServerSettings = self.copy(remoteAddressHeader = newValue) + override def withRawRequestUriHeader(newValue: Boolean): ServerSettings = self.copy(rawRequestUriHeader = newValue) + override def withTransparentHeadRequests(newValue: Boolean): ServerSettings = self.copy(transparentHeadRequests = newValue) + override def withVerboseErrorMessages(newValue: Boolean): ServerSettings = self.copy(verboseErrorMessages = newValue) + override def withResponseHeaderSizeHint(newValue: Int): ServerSettings = self.copy(responseHeaderSizeHint = newValue) + override def withBacklog(newValue: Int): ServerSettings = self.copy(backlog = newValue) + override def withSocketOptions(newValue: java.lang.Iterable[SocketOption]): ServerSettings = self.copy(socketOptions = newValue.asScala.toList) + override def withWebsocketRandomFactory(newValue: java.util.function.Supplier[Random]): ServerSettings = self.copy(websocketRandomFactory = () ⇒ newValue.get()) + + // overloads for Scala idiomatic use + def withTimeouts(newValue: ServerSettings.Timeouts): ServerSettings = self.copy(timeouts = newValue) + def withServerHeader(newValue: Option[Server]): ServerSettings = self.copy(serverHeader = newValue) + def withDefaultHostHeader(newValue: Host): ServerSettings = self.copy(defaultHostHeader = newValue) + def withParserSettings(newValue: ParserSettings): ServerSettings = self.copy(parserSettings = newValue) + def withWebsocketRandomFactory(newValue: () ⇒ Random): ServerSettings = self.copy(websocketRandomFactory = newValue) + def withSocketOptions(newValue: immutable.Seq[SocketOption]): ServerSettings = self.copy(socketOptions = newValue) + +} + +object ServerSettings extends SettingsCompanion[ServerSettings] { + trait Timeouts extends akka.http.javadsl.settings.ServerSettings.Timeouts { + // --- + // override for more specific return types + override def withIdleTimeout(newValue: Duration): ServerSettings.Timeouts = self.copy(idleTimeout = newValue) + override def withRequestTimeout(newValue: Duration): ServerSettings.Timeouts = self.copy(requestTimeout = newValue) + override def withBindTimeout(newValue: FiniteDuration): ServerSettings.Timeouts = self.copy(bindTimeout = newValue) + } + + implicit def timeoutsShortcut(s: ServerSettings): Timeouts = s.timeouts + + override def apply(config: Config): ServerSettings = ServerSettingsImpl(config) + override def apply(configOverrides: String): ServerSettings = ServerSettingsImpl(configOverrides) +} \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/SettingsCompanion.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/SettingsCompanion.scala new file mode 100644 index 0000000000..e1b0ee6b38 --- /dev/null +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/SettingsCompanion.scala @@ -0,0 +1,27 @@ +package akka.http.scaladsl.settings + +import akka.actor.{ ActorRefFactory, ActorSystem } +import com.typesafe.config.Config +import akka.http.impl.util._ + +/** INTERNAL API */ +private[akka] trait SettingsCompanion[T] { + + /** + * Creates an instance of settings using the configuration provided by the given ActorSystem. + */ + final def apply(system: ActorSystem): T = apply(system.settings.config) + implicit def default(implicit system: ActorRefFactory): T = apply(actorSystem) + + /** + * Creates an instance of settings using the given Config. + */ + def apply(config: Config): T + + /** + * Create an instance of settings using the given String of config overrides to override + * settings set in the class loader of this class (i.e. by application.conf or reference.conf files in + * the class loader of this class). + */ + def apply(configOverrides: String): T +} diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala index e5922936d5..b41590b149 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala @@ -8,6 +8,8 @@ import java.net.InetSocketAddress import java.nio.ByteBuffer import java.nio.channels.{ SocketChannel, ServerSocketChannel } import java.util.concurrent.atomic.AtomicInteger +import akka.http.impl.settings.ConnectionPoolSettingsImpl + import scala.concurrent.Await import scala.concurrent.duration._ import scala.util.control.NonFatal @@ -15,7 +17,7 @@ import scala.util.{ Failure, Success, Try } import akka.util.ByteString import akka.http.scaladsl.{ TestUtils, Http } import akka.http.impl.util.{ SingletonException, StreamUtils } -import akka.http.{ ClientConnectionSettings, ConnectionPoolSettings, ServerSettings } +import akka.http.scaladsl.settings.{ ClientConnectionSettings, ConnectionPoolSettings, ServerSettings } import akka.stream.io.{ SessionBytes, SendBytes, SslTlsOutbound } import akka.stream.{ BidiShape, ActorMaterializer } import akka.stream.testkit.{ TestPublisher, TestSubscriber, AkkaSpec } @@ -128,7 +130,7 @@ class ConnectionPoolSpec extends AkkaSpec(""" } "be able to handle 500 pipelined requests against the test server" in new TestSetup { - val settings = ConnectionPoolSettings(system).copy(maxConnections = 4, pipeliningLimit = 2) + val settings = ConnectionPoolSettings(system).withMaxConnections(4).withPipeliningLimit(2) val poolFlow = Http().cachedHostConnectionPool[Int](serverHostName, serverPort, settings = settings) val N = 500 @@ -229,7 +231,7 @@ class ConnectionPoolSpec extends AkkaSpec(""" } "The single-request client infrastructure" should { - class LocalTestSetup extends TestSetup(ServerSettings(system).copy(rawRequestUriHeader = true), autoAccept = true) + class LocalTestSetup extends TestSetup(ServerSettings(system).withRawRequestUriHeader(true), autoAccept = true) "transform absolute request URIs into relative URIs plus host header" in new LocalTestSetup { val request = HttpRequest(uri = s"http://$serverHostName:$serverPort/abc?query#fragment") @@ -326,7 +328,7 @@ class ConnectionPoolSpec extends AkkaSpec(""" pipeliningLimit: Int = 1, idleTimeout: Duration = 5.seconds, ccSettings: ClientConnectionSettings = ClientConnectionSettings(system)) = { - val settings = new ConnectionPoolSettings(maxConnections, maxRetries, maxOpenRequests, pipeliningLimit, + val settings = new ConnectionPoolSettingsImpl(maxConnections, maxRetries, maxOpenRequests, pipeliningLimit, idleTimeout, ClientConnectionSettings(system)) flowTestBench(Http().cachedHostConnectionPool[T](serverHostName, serverPort, settings)) } @@ -337,7 +339,7 @@ class ConnectionPoolSpec extends AkkaSpec(""" pipeliningLimit: Int = 1, idleTimeout: Duration = 5.seconds, ccSettings: ClientConnectionSettings = ClientConnectionSettings(system)) = { - val settings = ConnectionPoolSettings(maxConnections, maxRetries, maxOpenRequests, pipeliningLimit, + val settings = new ConnectionPoolSettingsImpl(maxConnections, maxRetries, maxOpenRequests, pipeliningLimit, idleTimeout, ClientConnectionSettings(system)) flowTestBench(Http().superPool[T](settings = settings)) } diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpConfigurationSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpConfigurationSpec.scala index 7c729208ea..2a1564dc14 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpConfigurationSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpConfigurationSpec.scala @@ -5,7 +5,7 @@ package akka.http.impl.engine.client import akka.actor.ActorSystem -import akka.http.{ ClientConnectionSettings, ConnectionPoolSettings, ServerSettings } +import akka.http.scaladsl.settings.{ ClientConnectionSettings, ConnectionPoolSettings, ServerSettings } import akka.stream.testkit.AkkaSpec import com.typesafe.config.ConfigFactory diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala index 1313302ebd..237e57b45d 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala @@ -7,7 +7,7 @@ package akka.http.impl.engine.client import scala.concurrent.duration._ import scala.reflect.ClassTag import org.scalatest.Inside -import akka.http.ClientConnectionSettings +import akka.http.scaladsl.settings.ClientConnectionSettings import akka.stream.io.{ SessionBytes, SslTlsOutbound, SendBytes } import akka.util.ByteString import akka.event.NoLogging @@ -521,9 +521,9 @@ class LowLevelOutgoingConnectionSpec extends AkkaSpec("akka.loggers = []\n akka. def settings = { val s = ClientConnectionSettings(system) - .copy(userAgentHeader = Some(`User-Agent`(List(ProductVersion("akka-http", "test"))))) + .withUserAgentHeader(Some(`User-Agent`(List(ProductVersion("akka-http", "test"))))) if (maxResponseContentLength < 0) s - else s.copy(parserSettings = s.parserSettings.copy(maxContentLength = maxResponseContentLength)) + else s.withParserSettings(s.parserSettings.withMaxContentLength(maxResponseContentLength)) } val (netOut, netIn) = { diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala index 25ffa46fd0..5653afbc67 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala @@ -5,7 +5,7 @@ package akka.http.impl.engine.parsing import java.lang.{ StringBuilder ⇒ JStringBuilder } -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import com.typesafe.config.{ ConfigFactory, Config } import scala.annotation.tailrec import scala.util.Random diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala index c951412441..b8dcb95b9a 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala @@ -1,7 +1,7 @@ package akka.http.impl.engine.parsing import akka.actor.ActorSystem -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import com.typesafe.config.{ ConfigFactory, Config } object HttpHeaderParserTestBed extends App { diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala index d555179637..c1bb085683 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala @@ -23,7 +23,7 @@ import akka.stream.io.{ SslTlsPlacebo, SessionBytes } import org.scalatest.matchers.Matcher import org.scalatest.{ BeforeAndAfterAll, FreeSpec, Matchers } -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import akka.http.impl.engine.parsing.ParserOutput._ import akka.http.impl.util._ import akka.http.scaladsl.model.HttpEntity._ diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala index 105f32e0eb..ed0362fa71 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala @@ -5,7 +5,7 @@ package akka.http.impl.engine.parsing import akka.NotUsed -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import akka.http.scaladsl.util.FastFuture import akka.stream.io.{ SslTlsPlacebo, SessionBytes } import com.typesafe.config.{ ConfigFactory, Config } diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerSpec.scala index 9e5c6e4580..720bf6a1dd 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerSpec.scala @@ -5,7 +5,7 @@ package akka.http.impl.engine.server import java.net.{ InetAddress, InetSocketAddress } -import akka.http.ServerSettings +import akka.http.scaladsl.settings.ServerSettings import scala.reflect.ClassTag import scala.util.Random import scala.annotation.tailrec @@ -366,7 +366,7 @@ class HttpServerSpec extends AkkaSpec( } "translate HEAD request to GET request when transparent-head-requests are enabled" in new TestSetup { - override def settings = ServerSettings(system).copy(transparentHeadRequests = true) + override def settings = ServerSettings(system).withTransparentHeadRequests(true) send("""HEAD / HTTP/1.1 |Host: example.com | @@ -375,7 +375,7 @@ class HttpServerSpec extends AkkaSpec( } "keep HEAD request when transparent-head-requests are disabled" in new TestSetup { - override def settings = ServerSettings(system).copy(transparentHeadRequests = false) + override def settings = ServerSettings(system).withTransparentHeadRequests(false) send("""HEAD / HTTP/1.1 |Host: example.com | @@ -662,7 +662,7 @@ class HttpServerSpec extends AkkaSpec( expectRequest() shouldEqual HttpRequest(uri = "http://example.com/abc", protocol = HttpProtocols.`HTTP/1.0`) - override def settings: ServerSettings = super.settings.copy(defaultHostHeader = Host("example.com")) + override def settings: ServerSettings = super.settings.withDefaultHostHeader(Host("example.com")) } "fail an HTTP/1.0 request with 400 if no default-host-header is set" in new TestSetup { @@ -690,7 +690,7 @@ class HttpServerSpec extends AkkaSpec( Some(new InetSocketAddress(theAddress, 8080)) override def settings: ServerSettings = - super.settings.copy(remoteAddressHeader = true) + super.settings.withRemoteAddressHeader(true) send("""GET / HTTP/1.1 |Host: example.com @@ -987,13 +987,13 @@ class HttpServerSpec extends AkkaSpec( override def settings = { val s = super.settings if (maxContentLength < 0) s - else s.copy(parserSettings = s.parserSettings.copy(maxContentLength = maxContentLength)) + else s.withParserSettings(s.parserSettings.withMaxContentLength(maxContentLength)) } } class RequestTimeoutTestSetup(requestTimeout: Duration) extends TestSetup { override def settings = { val s = super.settings - s.copy(timeouts = s.timeouts.copy(requestTimeout = requestTimeout)) + s.withTimeouts(s.timeouts.withRequestTimeout(requestTimeout)) } } } diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerTestSetupBase.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerTestSetupBase.scala index b6d93364cf..af4b76b46e 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerTestSetupBase.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerTestSetupBase.scala @@ -6,6 +6,7 @@ package akka.http.impl.engine.server import java.net.InetSocketAddress import akka.http.impl.engine.ws.ByteStringSinkProbe +import akka.http.scaladsl.settings.ServerSettings import akka.stream.io.{ SendBytes, SslTlsOutbound, SessionBytes } import scala.concurrent.duration.FiniteDuration import akka.actor.ActorSystem @@ -15,7 +16,6 @@ import akka.stream.{ ClosedShape, Materializer } import akka.stream.scaladsl._ import akka.stream.testkit.{ TestPublisher, TestSubscriber } import akka.http.impl.util._ -import akka.http.ServerSettings import akka.http.scaladsl.model.headers.{ ProductVersion, Server } import akka.http.scaladsl.model.{ HttpResponse, HttpRequest } import akka.stream.OverflowStrategy @@ -28,7 +28,7 @@ abstract class HttpServerTestSetupBase { val responses = TestPublisher.probe[HttpResponse]() def settings = ServerSettings(system) - .copy(serverHeader = Some(Server(List(ProductVersion("akka-http", "test"))))) + .withServerHeader(Some(Server(List(ProductVersion("akka-http", "test"))))) def remoteAddress: Option[InetSocketAddress] = None val (netIn, netOut) = { diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketClientSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketClientSpec.scala index 4a447229e6..b75a323042 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketClientSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketClientSpec.scala @@ -12,7 +12,7 @@ import akka.stream.ClosedShape import scala.concurrent.duration._ -import akka.http.ClientConnectionSettings +import akka.http.scaladsl.settings.ClientConnectionSettings import akka.http.scaladsl.Http import akka.http.scaladsl.model.headers.{ ProductVersion, `User-Agent` } import akka.http.scaladsl.model.ws._ @@ -297,9 +297,8 @@ class WebSocketClientSpec extends FreeSpec with Matchers with WithMaterializerSp val random = new Random(0) def settings = ClientConnectionSettings(system) - .copy( - userAgentHeader = Some(`User-Agent`(List(ProductVersion("akka-http", "test")))), - websocketRandomFactory = () ⇒ random) + .withUserAgentHeader(Some(`User-Agent`(List(ProductVersion("akka-http", "test"))))) + .withWebsocketRandomFactory(() ⇒ random) def targetUri: Uri = "ws://example.org/ws" diff --git a/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala index eaff63684b..4b84322c4d 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala @@ -4,7 +4,7 @@ package akka.http.impl.model.parser -import akka.http.ParserSettings.CookieParsingMode +import akka.http.scaladsl.settings.ParserSettings.CookieParsingMode import akka.http.impl.model.parser.HeaderParser.Settings import org.scalatest.{ Matchers, FreeSpec } import org.scalatest.matchers.{ Matcher, MatchResult } diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala index 1556003910..d8be965b22 100644 --- a/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala @@ -7,6 +7,8 @@ package akka.http.scaladsl import java.io.{ BufferedReader, BufferedWriter, InputStreamReader, OutputStreamWriter } import java.net.{ BindException, Socket } import java.util.concurrent.TimeoutException +import akka.http.scaladsl.settings.{ ConnectionPoolSettings, ClientConnectionSettings, ServerSettings } + import scala.annotation.tailrec import scala.concurrent.duration._ import scala.concurrent.{ Await, Future, Promise } @@ -18,7 +20,6 @@ import akka.http.scaladsl.model.HttpEntity._ import akka.http.scaladsl.model.HttpMethods._ import akka.http.scaladsl.model._ import akka.http.scaladsl.model.headers._ -import akka.http.{ ConnectionPoolSettings, ClientConnectionSettings, ServerSettings } import akka.stream.scaladsl._ import akka.stream.testkit._ import akka.stream.{ ActorMaterializer, BindFailedException, StreamTcpException } @@ -114,7 +115,7 @@ class ClientServerSpec extends WordSpec with Matchers with BeforeAndAfterAll wit "prevent more than the configured number of max-connections with bindAndHandle" in { val (_, hostname, port) = TestUtils.temporaryServerHostnameAndPort() - val settings = ServerSettings(system).copy(maxConnections = 1) + val settings = ServerSettings(system).withMaxConnections(1) val receivedSlow = Promise[Long]() val receivedFast = Promise[Long]() @@ -155,7 +156,7 @@ class ClientServerSpec extends WordSpec with Matchers with BeforeAndAfterAll wit "timeouts" should { def bindServer(hostname: String, port: Int, serverTimeout: FiniteDuration): (Promise[Long], ServerBinding) = { val s = ServerSettings(system) - val settings = s.copy(timeouts = s.timeouts.copy(idleTimeout = serverTimeout)) + val settings = s.withTimeouts(s.timeouts.withIdleTimeout(serverTimeout)) val receivedRequest = Promise[Long]() @@ -204,7 +205,7 @@ class ClientServerSpec extends WordSpec with Matchers with BeforeAndAfterAll wit val cs = ClientConnectionSettings(system) val clientTimeout = 345.millis - val clientSettings = cs.copy(idleTimeout = clientTimeout) + val clientSettings = cs.withIdleTimeout(clientTimeout) val (_, hostname, port) = TestUtils.temporaryServerHostnameAndPort() val (receivedRequest: Promise[Long], b1: ServerBinding) = bindServer(hostname, port, serverTimeout) @@ -237,7 +238,7 @@ class ClientServerSpec extends WordSpec with Matchers with BeforeAndAfterAll wit val cs = ConnectionPoolSettings(system) val clientTimeout = 345.millis - val clientPoolSettings = cs.copy(idleTimeout = clientTimeout) + val clientPoolSettings = cs.withIdleTimeout(clientTimeout) val (_, hostname, port) = TestUtils.temporaryServerHostnameAndPort() val (receivedRequest: Promise[Long], b1: ServerBinding) = bindServer(hostname, port, serverTimeout) @@ -272,7 +273,7 @@ class ClientServerSpec extends WordSpec with Matchers with BeforeAndAfterAll wit val cs = ConnectionPoolSettings(system) val clientTimeout = 345.millis - val clientPoolSettings = cs.copy(idleTimeout = clientTimeout) + val clientPoolSettings = cs.withIdleTimeout(clientTimeout) val (_, hostname, port) = TestUtils.temporaryServerHostnameAndPort() val (receivedRequest: Promise[Long], b1: ServerBinding) = bindServer(hostname, port, serverTimeout) diff --git a/akka-http-testkit/src/main/scala/akka/http/javadsl/testkit/RouteTest.scala b/akka-http-testkit/src/main/scala/akka/http/javadsl/testkit/RouteTest.scala index 03bfedd635..941b2c3bd2 100644 --- a/akka-http-testkit/src/main/scala/akka/http/javadsl/testkit/RouteTest.scala +++ b/akka-http-testkit/src/main/scala/akka/http/javadsl/testkit/RouteTest.scala @@ -15,7 +15,7 @@ import akka.http.javadsl.server.{ HttpApp, AllDirectives, Route, Directives } import akka.http.impl.util.JavaMapping.Implicits._ import akka.http.impl.server.RouteImplementation import akka.http.scaladsl.model.HttpResponse -import akka.http.scaladsl.server.{ RouteResult, RoutingSettings, Route ⇒ ScalaRoute } +import akka.http.scaladsl.server.{ RouteResult, RoutingSettingsImpl, Route ⇒ ScalaRoute } import akka.actor.ActorSystem import akka.event.NoLogging import akka.http.impl.util._ @@ -55,7 +55,7 @@ abstract class RouteTest extends AllDirectives { securedConnection = defaultHostInfo.isSecuredConnection(), defaultHostHeader = defaultHostInfo.getHost().asScala) - val result = scalaRoute(new server.RequestContextImpl(effectiveRequest, NoLogging, RoutingSettings(system))) + val result = scalaRoute(new server.RequestContextImpl(effectiveRequest, NoLogging, RoutingSettingsImpl(system))) result.awaitResult(awaitDuration) match { case RouteResult.Complete(response) ⇒ createTestResponse(response) diff --git a/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTest.scala b/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTest.scala index 992fd451f9..4128289ebd 100644 --- a/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTest.scala +++ b/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTest.scala @@ -134,7 +134,7 @@ trait RouteTest extends RequestBuilding with WSTestRequestBuilding with RouteTes } implicit def injectIntoRoute(implicit timeout: RouteTestTimeout, defaultHostInfo: DefaultHostInfo, - routingSettings: RoutingSettings, + routingSettings: RoutingSettingsImpl, executionContext: ExecutionContext, materializer: Materializer, routingLog: RoutingLog, diff --git a/akka-http-tests/src/test/java/akka/http/javadsl/client/HttpAPIsTest.java b/akka-http-tests/src/test/java/akka/http/javadsl/client/HttpAPIsTest.java index fb02b1e26c..ad2ab3c543 100644 --- a/akka-http-tests/src/test/java/akka/http/javadsl/client/HttpAPIsTest.java +++ b/akka-http-tests/src/test/java/akka/http/javadsl/client/HttpAPIsTest.java @@ -5,11 +5,11 @@ package akka.http.javadsl.client; import akka.event.LoggingAdapter; -import akka.http.ConnectionPoolSettings; import akka.http.javadsl.*; import akka.http.javadsl.model.HttpRequest; import akka.http.javadsl.model.HttpResponse; import akka.http.javadsl.testkit.JUnitRouteTest; +import akka.http.scaladsl.settings.ConnectionPoolSettings; import akka.japi.Function; import akka.stream.javadsl.Flow; import scala.concurrent.Future; diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala index 0e07bd486f..685810dfe8 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala @@ -229,7 +229,7 @@ class FileAndResourceDirectivesSpec extends RoutingSpec with Inspectors with Ins val base = new File(getClass.getClassLoader.getResource("").toURI).getPath new File(base, "subDirectory/emptySub").mkdir() def eraseDateTime(s: String) = s.replaceAll("""\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d""", "xxxx-xx-xx xx:xx:xx") - implicit val settings = RoutingSettings.default.copy(renderVanityFooter = false) + implicit val settings = RoutingSettingsImpl.default.copy(renderVanityFooter = false) "properly render a simple directory" in { Get() ~> listDirectoryContents(base + "/someDir") ~> check { diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/HttpService.scala b/akka-http/src/main/scala/akka/http/javadsl/server/HttpService.scala index 88dddec333..e5f004b9af 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/HttpService.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/HttpService.scala @@ -7,6 +7,7 @@ package akka.http.javadsl.server import akka.actor.ActorSystem import akka.http.scaladsl.{ server, Http } import akka.http.scaladsl.Http.ServerBinding +import akka.http.scaladsl.server.RouteResult import akka.http.impl.server.RouteImplementation import akka.stream.{ ActorMaterializer, Materializer } import akka.stream.scaladsl.{ Keep, Sink } @@ -38,7 +39,7 @@ trait HttpServiceBase { import system.dispatcher val r: server.Route = RouteImplementation(route) - Http(system).bind(interface, port).toMat(Sink.foreach(_.handleWith(r)))(Keep.left).run()(materializer).toJava + Http(system).bind(interface, port).toMat(Sink.foreach(_.handleWith(RouteResult.route2HandlerFlow(r))))(Keep.left).run()(materializer).toJava } } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/ExceptionHandler.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/ExceptionHandler.scala index 1ea71e2a0d..422a1a608a 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/ExceptionHandler.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/ExceptionHandler.scala @@ -18,7 +18,7 @@ trait ExceptionHandler extends ExceptionHandler.PF { /** * "Seals" this handler by attaching a default handler as fallback if necessary. */ - def seal(settings: RoutingSettings): ExceptionHandler + def seal(settings: RoutingSettingsImpl): ExceptionHandler } object ExceptionHandler { @@ -32,11 +32,11 @@ object ExceptionHandler { def apply(error: Throwable) = pf(error) def withFallback(that: ExceptionHandler): ExceptionHandler = if (!knownToBeSealed) ExceptionHandler(knownToBeSealed = false)(this orElse that) else this - def seal(settings: RoutingSettings): ExceptionHandler = + def seal(settings: RoutingSettingsImpl): ExceptionHandler = if (!knownToBeSealed) ExceptionHandler(knownToBeSealed = true)(this orElse default(settings)) else this } - def default(settings: RoutingSettings): ExceptionHandler = + def default(settings: RoutingSettingsImpl): ExceptionHandler = apply(knownToBeSealed = true) { case IllegalRequestException(info, status) ⇒ ctx ⇒ { ctx.log.warning("Illegal request {}\n\t{}\n\tCompleting with '{}' response", @@ -53,6 +53,6 @@ object ExceptionHandler { * Creates a sealed ExceptionHandler from the given one. Returns the default handler if the given one * is `null`. */ - def seal(handler: ExceptionHandler)(implicit settings: RoutingSettings): ExceptionHandler = + def seal(handler: ExceptionHandler)(implicit settings: RoutingSettingsImpl): ExceptionHandler = if (handler ne null) handler.seal(settings) else ExceptionHandler.default(settings) } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/RequestContext.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/RequestContext.scala index 15632522f3..e447be55dd 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/RequestContext.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/RequestContext.scala @@ -5,11 +5,11 @@ package akka.http.scaladsl.server import scala.concurrent.{ Future, ExecutionContextExecutor } -import akka.http.ParserSettings import akka.stream.Materializer import akka.event.LoggingAdapter import akka.http.scaladsl.marshalling.ToResponseMarshallable import akka.http.scaladsl.model._ +import akka.http.scaladsl.settings.ParserSettings /** * Immutable object encapsulating the context of an [[akka.http.scaladsl.model.HttpRequest]] @@ -41,7 +41,7 @@ trait RequestContext { /** * The default RoutingSettings to be used for configuring directives. */ - def settings: RoutingSettings + def settings: RoutingSettingsImpl /** * The default ParserSettings to be used for configuring directives. @@ -55,7 +55,7 @@ trait RequestContext { executionContext: ExecutionContextExecutor = executionContext, materializer: Materializer = materializer, log: LoggingAdapter = log, - settings: RoutingSettings = settings): RequestContext + settings: RoutingSettingsImpl = settings): RequestContext /** * Completes the request with the given ToResponseMarshallable. @@ -97,7 +97,7 @@ trait RequestContext { /** * Returns a copy of this context with the new RoutingSettings. */ - def withRoutingSettings(settings: RoutingSettings): RequestContext + def withRoutingSettings(settings: RoutingSettingsImpl): RequestContext /** * Returns a copy of this context with the new [[ParserSettings]]. diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/RequestContextImpl.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/RequestContextImpl.scala index 1edc1529c6..868a4fdd92 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/RequestContextImpl.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/RequestContextImpl.scala @@ -7,7 +7,7 @@ package akka.http.scaladsl.server import scala.concurrent.{ Future, ExecutionContextExecutor } import akka.stream.{ ActorMaterializer, Materializer } import akka.event.LoggingAdapter -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import akka.http.scaladsl.marshalling.{ Marshal, ToResponseMarshallable } import akka.http.scaladsl.model._ import akka.http.scaladsl.util.FastFuture @@ -22,16 +22,16 @@ private[http] class RequestContextImpl( val executionContext: ExecutionContextExecutor, val materializer: Materializer, val log: LoggingAdapter, - val settings: RoutingSettings, + val settings: RoutingSettingsImpl, val parserSettings: ParserSettings) extends RequestContext { - def this(request: HttpRequest, log: LoggingAdapter, settings: RoutingSettings, parserSettings: ParserSettings)(implicit ec: ExecutionContext, materializer: Materializer) = + def this(request: HttpRequest, log: LoggingAdapter, settings: RoutingSettingsImpl, parserSettings: ParserSettings)(implicit ec: ExecutionContextExecutor, materializer: Materializer) = this(request, request.uri.path, ec, materializer, log, settings, parserSettings) - def this(request: HttpRequest, log: LoggingAdapter, settings: RoutingSettings)(implicit ec: ExecutionContextExecutor, materializer: Materializer) = + def this(request: HttpRequest, log: LoggingAdapter, settings: RoutingSettingsImpl)(implicit ec: ExecutionContextExecutor, materializer: Materializer) = this(request, request.uri.path, ec, materializer, log, settings, ParserSettings(ActorMaterializer.downcast(materializer).system)) - def reconfigure(executionContext: ExecutionContextExecutor, materializer: Materializer, log: LoggingAdapter, settings: RoutingSettings): RequestContext = + def reconfigure(executionContext: ExecutionContextExecutor, materializer: Materializer, log: LoggingAdapter, settings: RoutingSettingsImpl): RequestContext = copy(executionContext = executionContext, materializer = materializer, log = log, routingSettings = settings) override def complete(trm: ToResponseMarshallable): Future[RouteResult] = @@ -61,7 +61,7 @@ private[http] class RequestContextImpl( override def withLog(log: LoggingAdapter): RequestContext = if (log != this.log) copy(log = log) else this - override def withRoutingSettings(routingSettings: RoutingSettings): RequestContext = + override def withRoutingSettings(routingSettings: RoutingSettingsImpl): RequestContext = if (routingSettings != this.settings) copy(routingSettings = routingSettings) else this override def withParserSettings(parserSettings: ParserSettings): RequestContext = @@ -94,7 +94,7 @@ private[http] class RequestContextImpl( executionContext: ExecutionContextExecutor = executionContext, materializer: Materializer = materializer, log: LoggingAdapter = log, - routingSettings: RoutingSettings = settings, + routingSettings: RoutingSettingsImpl = settings, parserSettings: ParserSettings = parserSettings) = new RequestContextImpl(request, unmatchedPath, executionContext, materializer, log, routingSettings, parserSettings) } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/Route.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/Route.scala index c1e99f5f94..4f81f9193c 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/Route.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/Route.scala @@ -6,7 +6,7 @@ package akka.http.scaladsl.server import akka.NotUsed import akka.actor.ActorSystem -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import akka.stream.{ ActorMaterializer, Materializer } import scala.concurrent.{ ExecutionContextExecutor, Future } @@ -24,7 +24,7 @@ object Route { /** * "Seals" a route by wrapping it with exception handling and rejection conversion. */ - def seal(route: Route)(implicit routingSettings: RoutingSettings, + def seal(route: Route)(implicit routingSettings: RoutingSettingsImpl, parserSettings: ParserSettings = null, rejectionHandler: RejectionHandler = RejectionHandler.default, exceptionHandler: ExceptionHandler = null): Route = { @@ -41,7 +41,7 @@ object Route { * * This conversion is also implicitly available through [[RouteResult.route2HandlerFlow]]. */ - def handlerFlow(route: Route)(implicit routingSettings: RoutingSettings, + def handlerFlow(route: Route)(implicit routingSettings: RoutingSettingsImpl, parserSettings: ParserSettings, materializer: Materializer, routingLog: RoutingLog, @@ -53,7 +53,7 @@ object Route { /** * Turns a `Route` into an async handler function. */ - def asyncHandler(route: Route)(implicit routingSettings: RoutingSettings, + def asyncHandler(route: Route)(implicit routingSettings: RoutingSettingsImpl, parserSettings: ParserSettings, materializer: Materializer, routingLog: RoutingLog, diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/RouteResult.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/RouteResult.scala index d9562be72d..ae5c306a50 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/RouteResult.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/RouteResult.scala @@ -5,7 +5,7 @@ package akka.http.scaladsl.server import akka.NotUsed -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import scala.collection.immutable import scala.concurrent.ExecutionContext @@ -25,7 +25,7 @@ object RouteResult { final case class Complete(response: HttpResponse) extends RouteResult final case class Rejected(rejections: immutable.Seq[Rejection]) extends RouteResult - implicit def route2HandlerFlow(route: Route)(implicit routingSettings: RoutingSettings, + implicit def route2HandlerFlow(route: Route)(implicit routingSettings: RoutingSettingsImpl, parserSettings: ParserSettings, materializer: Materializer, routingLog: RoutingLog, diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/RoutingSettings.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/RoutingSettings.scala deleted file mode 100644 index a528e5276d..0000000000 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/RoutingSettings.scala +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2009-2016 Typesafe Inc. - */ - -package akka.http.scaladsl.server - -import com.typesafe.config.Config -import akka.actor.ActorRefFactory -import akka.http.impl.util._ - -final class RoutingSettings( - val verboseErrorMessages: Boolean, - val fileGetConditional: Boolean, - val renderVanityFooter: Boolean, - val rangeCountLimit: Int, - val rangeCoalescingThreshold: Long, - val decodeMaxBytesPerChunk: Int, - val fileIODispatcher: String) { - - def copy( - verboseErrorMessages: Boolean = verboseErrorMessages, - fileGetConditional: Boolean = fileGetConditional, - renderVanityFooter: Boolean = renderVanityFooter, - rangeCountLimit: Int = rangeCountLimit, - rangeCoalescingThreshold: Long = rangeCoalescingThreshold, - decodeMaxBytesPerChunk: Int = decodeMaxBytesPerChunk, - fileIODispatcher: String = fileIODispatcher): RoutingSettings = - new RoutingSettings( - verboseErrorMessages, - fileGetConditional, - renderVanityFooter, - rangeCountLimit, - rangeCoalescingThreshold, - decodeMaxBytesPerChunk, - fileIODispatcher) - - // TODO we should automate generating those - override def toString = { - getClass.getSimpleName + "(" + - verboseErrorMessages + "," + - fileGetConditional + "," + - renderVanityFooter + "," + - rangeCountLimit + "," + - rangeCoalescingThreshold + "," + - decodeMaxBytesPerChunk + "," + - fileIODispatcher + - ")" - } -} - -object RoutingSettings extends SettingsCompanion[RoutingSettings]("akka.http.routing") { - def fromSubConfig(root: Config, c: Config) = new RoutingSettings( - c getBoolean "verbose-error-messages", - c getBoolean "file-get-conditional", - c getBoolean "render-vanity-footer", - c getInt "range-count-limit", - c getBytes "range-coalescing-threshold", - c getIntBytes "decode-max-bytes-per-chunk", - c getString "file-io-dispatcher") - - implicit def default(implicit refFactory: ActorRefFactory): RoutingSettings = - apply(actorSystem) - - def apply( - verboseErrorMessages: Boolean, - fileGetConditional: Boolean, - renderVanityFooter: Boolean, - rangeCountLimit: Int, - rangeCoalescingThreshold: Long, - decodeMaxBytesPerChunk: Int, - fileIODispatcher: String): RoutingSettings = - new RoutingSettings( - verboseErrorMessages, - fileGetConditional, - renderVanityFooter, - rangeCountLimit, - rangeCoalescingThreshold, - decodeMaxBytesPerChunk, - fileIODispatcher) -} diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/RoutingSettingsImpl.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/RoutingSettingsImpl.scala new file mode 100644 index 0000000000..fb88469005 --- /dev/null +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/RoutingSettingsImpl.scala @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.scaladsl.server + +import com.typesafe.config.Config +import akka.actor.ActorRefFactory +import akka.http.impl.util._ + +/** INTERNAL API */ +final case class RoutingSettingsImpl( + verboseErrorMessages: Boolean, + fileGetConditional: Boolean, + renderVanityFooter: Boolean, + rangeCountLimit: Int, + rangeCoalescingThreshold: Long, + decodeMaxBytesPerChunk: Int, + fileIODispatcher: String) + +object RoutingSettingsImpl extends SettingsCompanion[RoutingSettingsImpl]("akka.http.routing") { + def fromSubConfig(root: Config, c: Config) = new RoutingSettingsImpl( + c getBoolean "verbose-error-messages", + c getBoolean "file-get-conditional", + c getBoolean "render-vanity-footer", + c getInt "range-count-limit", + c getBytes "range-coalescing-threshold", + c getIntBytes "decode-max-bytes-per-chunk", + c getString "file-io-dispatcher") + +} diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/BasicDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/BasicDirectives.scala index d55fc5ba9e..0536fa9865 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/BasicDirectives.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/BasicDirectives.scala @@ -9,7 +9,7 @@ import scala.concurrent.{ Future, ExecutionContextExecutor } import scala.collection.immutable import akka.event.LoggingAdapter import akka.stream.Materializer -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import akka.http.scaladsl.server.util.Tuple import akka.http.scaladsl.util.FastFuture import akka.http.scaladsl.model._ @@ -131,13 +131,13 @@ trait BasicDirectives { def extractUri: Directive1[Uri] = BasicDirectives._extractUri /** - * Runs its inner route with the given alternative [[ExecutionContext]]. + * Runs its inner route with the given alternative [[ExecutionContextExecutor]]. */ def withExecutionContext(ec: ExecutionContextExecutor): Directive0 = mapRequestContext(_ withExecutionContext ec) /** - * Extracts the [[ExecutionContext]] from the [[RequestContext]]. + * Extracts the [[ExecutionContextExecutor]] from the [[RequestContext]]. */ def extractExecutionContext: Directive1[ExecutionContextExecutor] = BasicDirectives._extractExecutionContext @@ -165,25 +165,25 @@ trait BasicDirectives { BasicDirectives._extractLog /** - * Runs its inner route with the given alternative [[RoutingSettings]]. + * Runs its inner route with the given alternative [[RoutingSettingsImpl]]. */ - def withSettings(settings: RoutingSettings): Directive0 = + def withSettings(settings: RoutingSettingsImpl): Directive0 = mapRequestContext(_ withRoutingSettings settings) /** * Runs the inner route with settings mapped by the given function. */ - def mapSettings(f: RoutingSettings ⇒ RoutingSettings): Directive0 = + def mapSettings(f: RoutingSettingsImpl ⇒ RoutingSettingsImpl): Directive0 = mapRequestContext(ctx ⇒ ctx.withRoutingSettings(f(ctx.settings))) /** - * Extracts the [[RoutingSettings]] from the [[RequestContext]]. + * Extracts the [[RoutingSettingsImpl]] from the [[RequestContext]]. */ - def extractSettings: Directive1[RoutingSettings] = + def extractSettings: Directive1[RoutingSettingsImpl] = BasicDirectives._extractSettings /** - * Extracts the [[akka.http.ParserSettings]] from the [[RequestContext]]. + * Extracts the [[akka.http.scaladsl.settings.ParserSettings]] from the [[RequestContext]]. */ def extractParserSettings: Directive1[ParserSettings] = BasicDirectives._extractParserSettings @@ -201,7 +201,7 @@ object BasicDirectives extends BasicDirectives { private val _extractExecutionContext: Directive1[ExecutionContextExecutor] = extract(_.executionContext) private val _extractMaterializer: Directive1[Materializer] = extract(_.materializer) private val _extractLog: Directive1[LoggingAdapter] = extract(_.log) - private val _extractSettings: Directive1[RoutingSettings] = extract(_.settings) + private val _extractSettings: Directive1[RoutingSettingsImpl] = extract(_.settings) private val _extractParserSettings: Directive1[ParserSettings] = extract(_.parserSettings) private val _extractRequestContext: Directive1[RequestContext] = extract(conforms) } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/MarshallingDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/MarshallingDirectives.scala index c861409555..fe44221e59 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/MarshallingDirectives.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/MarshallingDirectives.scala @@ -6,7 +6,7 @@ package akka.http.scaladsl.server package directives import akka.actor.ActorSystem -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import akka.http.scaladsl.model.Multipart import akka.http.scaladsl.model.Multipart.ByteRanges diff --git a/akka-http/src/main/scala/akka/http/scaladsl/unmarshalling/MultipartUnmarshallers.scala b/akka-http/src/main/scala/akka/http/scaladsl/unmarshalling/MultipartUnmarshallers.scala index 8ae9b7a749..7d522bcae7 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/unmarshalling/MultipartUnmarshallers.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/unmarshalling/MultipartUnmarshallers.scala @@ -5,7 +5,7 @@ package akka.http.scaladsl.unmarshalling import akka.actor.ActorSystem -import akka.http.ParserSettings +import akka.http.scaladsl.settings.ParserSettings import scala.collection.immutable import scala.collection.immutable.VectorBuilder @@ -23,11 +23,16 @@ import MediaTypes._ import HttpCharsets._ import akka.stream.impl.fusing.SubSource +/** + * Provides [[Multipart]] marshallers. + * It is possible to configure the default parsing mode by providing an implicit [[ParserSettings]] instance. + */ trait MultipartUnmarshallers { - implicit def defaultMultipartGeneralUnmarshaller(implicit log: LoggingAdapter = NoLogging): FromEntityUnmarshaller[Multipart.General] = + implicit def defaultMultipartGeneralUnmarshaller(implicit log: LoggingAdapter = NoLogging, parserSettings: ParserSettings = null): FromEntityUnmarshaller[Multipart.General] = multipartGeneralUnmarshaller(`UTF-8`) - def multipartGeneralUnmarshaller(defaultCharset: HttpCharset)(implicit log: LoggingAdapter = NoLogging): FromEntityUnmarshaller[Multipart.General] = + + def multipartGeneralUnmarshaller(defaultCharset: HttpCharset)(implicit log: LoggingAdapter = NoLogging, parserSettings: ParserSettings = null): FromEntityUnmarshaller[Multipart.General] = multipartUnmarshaller[Multipart.General, Multipart.General.BodyPart, Multipart.General.BodyPart.Strict]( mediaRange = `multipart/*`, defaultContentType = MediaTypes.`text/plain` withCharset defaultCharset, @@ -36,7 +41,7 @@ trait MultipartUnmarshallers { createStrictBodyPart = Multipart.General.BodyPart.Strict, createStrict = Multipart.General.Strict) - implicit def multipartFormDataUnmarshaller(implicit log: LoggingAdapter = NoLogging): FromEntityUnmarshaller[Multipart.FormData] = + implicit def multipartFormDataUnmarshaller(implicit log: LoggingAdapter = NoLogging, parserSettings: ParserSettings = null): FromEntityUnmarshaller[Multipart.FormData] = multipartUnmarshaller[Multipart.FormData, Multipart.FormData.BodyPart, Multipart.FormData.BodyPart.Strict]( mediaRange = `multipart/form-data`, defaultContentType = ContentTypes.`application/octet-stream`, @@ -45,9 +50,10 @@ trait MultipartUnmarshallers { createStrictBodyPart = (entity, headers) ⇒ Multipart.General.BodyPart.Strict(entity, headers).toFormDataBodyPart.get, createStrict = (_, parts) ⇒ Multipart.FormData.Strict(parts)) - implicit def defaultMultipartByteRangesUnmarshaller(implicit log: LoggingAdapter = NoLogging): FromEntityUnmarshaller[Multipart.ByteRanges] = + implicit def defaultMultipartByteRangesUnmarshaller(implicit log: LoggingAdapter = NoLogging, parserSettings: ParserSettings = null): FromEntityUnmarshaller[Multipart.ByteRanges] = multipartByteRangesUnmarshaller(`UTF-8`) - def multipartByteRangesUnmarshaller(defaultCharset: HttpCharset)(implicit log: LoggingAdapter = NoLogging): FromEntityUnmarshaller[Multipart.ByteRanges] = + + def multipartByteRangesUnmarshaller(defaultCharset: HttpCharset)(implicit log: LoggingAdapter = NoLogging, parserSettings: ParserSettings = null): FromEntityUnmarshaller[Multipart.ByteRanges] = multipartUnmarshaller[Multipart.ByteRanges, Multipart.ByteRanges.BodyPart, Multipart.ByteRanges.BodyPart.Strict]( mediaRange = `multipart/byteranges`, defaultContentType = MediaTypes.`text/plain` withCharset defaultCharset, @@ -56,12 +62,13 @@ trait MultipartUnmarshallers { createStrictBodyPart = (entity, headers) ⇒ Multipart.General.BodyPart.Strict(entity, headers).toByteRangesBodyPart.get, createStrict = (_, parts) ⇒ Multipart.ByteRanges.Strict(parts)) - def multipartUnmarshaller[T <: Multipart, BP <: Multipart.BodyPart, BPS <: Multipart.BodyPart.Strict](mediaRange: MediaRange, - defaultContentType: ContentType, - createBodyPart: (BodyPartEntity, List[HttpHeader]) ⇒ BP, - createStreamed: (MediaType.Multipart, Source[BP, Any]) ⇒ T, - createStrictBodyPart: (HttpEntity.Strict, List[HttpHeader]) ⇒ BPS, - createStrict: (MediaType.Multipart, immutable.Seq[BPS]) ⇒ T)(implicit log: LoggingAdapter = NoLogging): FromEntityUnmarshaller[T] = + def multipartUnmarshaller[T <: Multipart, BP <: Multipart.BodyPart, BPS <: Multipart.BodyPart.Strict]( + mediaRange: MediaRange, + defaultContentType: ContentType, + createBodyPart: (BodyPartEntity, List[HttpHeader]) ⇒ BP, + createStreamed: (MediaType.Multipart, Source[BP, Any]) ⇒ T, + createStrictBodyPart: (HttpEntity.Strict, List[HttpHeader]) ⇒ BPS, + createStrict: (MediaType.Multipart, immutable.Seq[BPS]) ⇒ T)(implicit log: LoggingAdapter = NoLogging, parserSettings: ParserSettings = null): FromEntityUnmarshaller[T] = Unmarshaller.withMaterializer { implicit ec ⇒ mat => entity ⇒ if (entity.contentType.mediaType.isMultipart && mediaRange.matches(entity.contentType.mediaType)) { @@ -70,7 +77,8 @@ trait MultipartUnmarshallers { FastFuture.failed(new RuntimeException("Content-Type with a multipart media type must have a 'boundary' parameter")) case Some(boundary) ⇒ import BodyPartParser._ - val parser = new BodyPartParser(defaultContentType, boundary, log, ParserSettings(ActorMaterializer.downcast(mat).system)) // TODO we could cache it + val effectiveParserSettings = Option(parserSettings).getOrElse(ParserSettings(ActorMaterializer.downcast(mat).system)) + val parser = new BodyPartParser(defaultContentType, boundary, log, effectiveParserSettings) FastFuture.successful { entity match { case HttpEntity.Strict(ContentType(mediaType: MediaType.Multipart, _), data) ⇒