-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add HttpServer object #591
Changes from all commits
c517ec3
43bc913
d004970
af8a9cf
0773ddf
2c253ba
c8c4bac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
Copyright (C) 2013-2019 Expedia Inc. | ||
Copyright (C) 2013-2020 Expedia Inc. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
|
@@ -36,6 +36,7 @@ | |
import static com.hotels.styx.config.schema.SchemaDsl.union; | ||
import static com.hotels.styx.config.validator.DocumentFormat.newDocument; | ||
import static com.hotels.styx.routing.config.Builtins.BUILTIN_HANDLER_SCHEMAS; | ||
import static com.hotels.styx.routing.config.Builtins.BUILTIN_SERVER_SCHEMAS; | ||
import static com.hotels.styx.routing.config.Builtins.BUILTIN_SERVICE_PROVIDER_SCHEMAS; | ||
import static com.hotels.styx.routing.config.Builtins.INTERCEPTOR_SCHEMAS; | ||
|
||
|
@@ -58,8 +59,7 @@ final class ServerConfigSchema { | |
optional("sessionCacheSize", integer()), | ||
optional("cipherSuites", list(string())), | ||
optional("protocols", list(string())) | ||
)), | ||
atLeastOne("http", "https") | ||
)) | ||
); | ||
|
||
Schema.FieldType logFormatSchema = object( | ||
|
@@ -70,7 +70,7 @@ final class ServerConfigSchema { | |
|
||
STYX_SERVER_CONFIGURATION_SCHEMA_BUILDER = newDocument() | ||
.rootSchema(object( | ||
field("proxy", object( | ||
optional("proxy", object( | ||
optional("compressResponses", bool()), | ||
field("connectors", serverConnectorsSchema), | ||
optional("bossThreadsCount", integer()), | ||
|
@@ -115,6 +115,7 @@ final class ServerConfigSchema { | |
field("factories", map(object(opaque()))) | ||
)), | ||
optional("providers", map(routingObject())), | ||
optional("servers", map(routingObject())), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we happy with servers or do we want to go to something more common like listeners? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should think about the naming before freezing this. However WDYT? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We've already discussed this and it seems we can keep using our current names. |
||
optional("url", object( | ||
field("encoding", object( | ||
field("unwiseCharactersToEncode", string()) | ||
|
@@ -163,6 +164,7 @@ final class ServerConfigSchema { | |
|
||
BUILTIN_HANDLER_SCHEMAS.forEach(STYX_SERVER_CONFIGURATION_SCHEMA_BUILDER::typeExtension); | ||
BUILTIN_SERVICE_PROVIDER_SCHEMAS.forEach(STYX_SERVER_CONFIGURATION_SCHEMA_BUILDER::typeExtension); | ||
BUILTIN_SERVER_SCHEMAS.forEach(STYX_SERVER_CONFIGURATION_SCHEMA_BUILDER::typeExtension); | ||
INTERCEPTOR_SCHEMAS.forEach(STYX_SERVER_CONFIGURATION_SCHEMA_BUILDER::typeExtension); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/* | ||
Copyright (C) 2013-2020 Expedia Inc. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
package com.hotels.styx.servers | ||
|
||
import com.fasterxml.jackson.databind.JsonNode | ||
import com.hotels.styx.InetServer | ||
import com.hotels.styx.NettyExecutor | ||
import com.hotels.styx.ProxyConnectorFactory | ||
import com.hotels.styx.ResponseInfoFormat | ||
import com.hotels.styx.StyxObjectRecord | ||
import com.hotels.styx.config.schema.SchemaDsl.* | ||
import com.hotels.styx.infrastructure.configuration.yaml.JsonNodeConfig | ||
import com.hotels.styx.proxy.ProxyServerConfig | ||
import com.hotels.styx.proxy.encoders.ConfigurableUnwiseCharsEncoder.ENCODE_UNWISECHARS | ||
import com.hotels.styx.routing.config.RoutingObjectFactory | ||
import com.hotels.styx.routing.config.StyxObjectReference | ||
import com.hotels.styx.routing.db.StyxObjectStore | ||
import com.hotels.styx.server.HttpConnectorConfig | ||
import com.hotels.styx.server.HttpsConnectorConfig | ||
import com.hotels.styx.server.netty.NettyServerBuilder | ||
import com.hotels.styx.server.netty.connectors.ResponseEnhancer | ||
import com.hotels.styx.serviceproviders.StyxServerFactory | ||
import org.slf4j.LoggerFactory | ||
|
||
object StyxHttpServer { | ||
@JvmField | ||
val SCHEMA = `object`( | ||
field("port", integer()), | ||
field("handler", string()), | ||
optional("tlsSettings", `object`( | ||
optional("sslProvider", string()), | ||
optional("certificateFile", string()), | ||
optional("certificateKeyFile", string()), | ||
optional("sessionTimeoutMillis", integer()), | ||
optional("sessionCacheSize", integer()), | ||
optional("cipherSuites", list(string())), | ||
optional("protocols", list(string())) | ||
)), | ||
|
||
optional("maxInitialLength", integer()), | ||
optional("maxHeaderSize", integer()), | ||
optional("maxChunkSize", integer()), | ||
|
||
optional("requestTimeoutMillis", integer()), | ||
optional("keepAliveTimeoutMillis", integer()), | ||
optional("maxConnectionsCount", integer()), | ||
|
||
optional("bossThreadsCount", integer()), | ||
optional("workerThreadsCount", integer()) | ||
) | ||
|
||
internal val LOGGER = LoggerFactory.getLogger(StyxHttpServer::class.java) | ||
} | ||
|
||
private data class StyxHttpServerTlsSettings( | ||
val certificateFile: String, | ||
val certificateKeyFile: String, | ||
val sslProvider: String = "JDK", | ||
val sessionTimeoutMillis: Int = 300000, | ||
val sessionCacheSize: Int = 0, | ||
val cipherSuites: List<String> = listOf(), | ||
val protocols: List<String> = listOf() | ||
) | ||
|
||
|
||
private data class StyxHttpServerConfiguration( | ||
val port: Int, | ||
val handler: String, | ||
val tlsSettings: StyxHttpServerTlsSettings?, | ||
|
||
val maxInitialLength: Int = 4096, | ||
val maxHeaderSize: Int = 8192, | ||
val maxChunkSize: Int = 8192, | ||
|
||
val requestTimeoutMillis: Int = 60000, | ||
val keepAliveTimeoutMillis: Int = 120000, | ||
val maxConnectionsCount: Int = 512, | ||
|
||
val bossThreadsCount: Int = 0, | ||
val workerThreadsCount: Int = 0 | ||
) | ||
|
||
internal class StyxHttpServerFactory : StyxServerFactory { | ||
private fun serverConfig(configuration: JsonNode) = JsonNodeConfig(configuration).`as`(StyxHttpServerConfiguration::class.java) | ||
|
||
override fun create(name: String, context: RoutingObjectFactory.Context, configuration: JsonNode, serverDb: StyxObjectStore<StyxObjectRecord<InetServer>>): InetServer { | ||
val config = serverConfig(configuration) | ||
|
||
val environment = context.environment() | ||
val proxyServerConfig = ProxyServerConfig.Builder() | ||
.setMaxInitialLength(config.maxInitialLength) | ||
.setMaxHeaderSize(config.maxHeaderSize) | ||
.setMaxChunkSize(config.maxChunkSize) | ||
.setRequestTimeoutMillis(config.requestTimeoutMillis) | ||
.setKeepAliveTimeoutMillis(config.keepAliveTimeoutMillis) | ||
.setMaxConnectionsCount(config.maxConnectionsCount) | ||
.setBossThreadsCount(config.bossThreadsCount) | ||
.setWorkerThreadsCount(config.workerThreadsCount) | ||
.build() | ||
|
||
return NettyServerBuilder() | ||
.setMetricsRegistry(environment.metricRegistry()) | ||
.setProtocolConnector( | ||
ProxyConnectorFactory( | ||
proxyServerConfig, | ||
environment.metricRegistry(), | ||
environment.errorListener(), | ||
environment.configuration().get(ENCODE_UNWISECHARS).orElse(""), | ||
ResponseEnhancer { builder, request -> | ||
builder.header( | ||
environment.configuration().styxHeaderConfig().styxInfoHeaderName(), | ||
ResponseInfoFormat(environment).format(request)) | ||
}, | ||
false) | ||
.create( | ||
if (config.tlsSettings == null) { | ||
HttpConnectorConfig(config.port) | ||
} else { | ||
HttpsConnectorConfig.Builder() | ||
.port(config.port) | ||
.sslProvider(config.tlsSettings.sslProvider) | ||
.certificateFile(config.tlsSettings.certificateFile) | ||
.certificateKeyFile(config.tlsSettings.certificateKeyFile) | ||
.cipherSuites(config.tlsSettings.cipherSuites) | ||
.protocols(*config.tlsSettings.protocols.toTypedArray()) | ||
.build() | ||
})) | ||
.workerExecutor(NettyExecutor.create("Http-Server(localhost-${config.port})", config.workerThreadsCount)) | ||
.bossExecutor(NettyExecutor.create("Http-Server(localhost-${config.port})", config.bossThreadsCount)) | ||
.handler({ request, ctx -> | ||
context.refLookup() | ||
.apply(StyxObjectReference(config.handler)) | ||
.handle(request, ctx) | ||
}) | ||
.build(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to move at least the compressResponses attribute somewhere else if it is optional now.
Don't we need any other of the attributes? factories, bossThreadsCount ... It seems bossThreadsCount was always applied to each listener/ServerBooStrap individually (we aren't sharing the NioEventLoopGroup between different BootStraps).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
compressResponses
attribute, and the other missing attributes would still work with the oldproxy
attribute. I will add them as a separate increment to the server object. I can do it straight after the PR is merged.Regarding The executors & thread counts. This is a know limitation and I think mentioned in the PR description. We need to think about a specific mechanism of configuring and injecting event loops into various kinks of styx objects: servers, routing objects, and providers. I'm thinking to introduce a separate
executors
block where you declare named executors, which can be then called into action from the other styx objects. For example:(This is a separate enhancement BTW)
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Raised an issue for missing content compression: #593