Skip to content
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

Configuration of server socket(s) #2189

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions docs/mp/jaxrs/02_server-configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,16 @@ server.port=7011
# Helidon configuration (optional)

# Length of queue for incoming connections. Default is 1024
server.backlog: 512
server.backlog=512
# TCP receive window. Default is 0 to use implementation default
server.receive-buffer: 256
server.receive-buffer=256
# Socket timeout milliseconds - defaults to 0 (infinite)
server.timeout: 30000
server.timeout=30000
# Defaults to Runtime.availableProcessors()
server.workers=4
# Default is not to use SSL
ssl:
private-key:
keystore-resource-path: "certificate.p12"
keystore-passphrase: "abcd"
ssl.private-key.keystore-resource-path=certificate.p12
ssl.private-key.keystore-passphrase="abcd"
----

== Configuring additional ports
Expand Down
21 changes: 21 additions & 0 deletions docs/se/webserver/02_configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,24 @@ just use `Config.create()`

See all configuration options
link:{javadoc-base-url-api}/WebServer.html[here].

Available socket configuration options:

[cols="^2s,<2,<2,<6"]
|===
|Configuration key |Default value ^|Java type ^|Description

|`port` |{nbsp} |int |Port to open server socket on, defaults to an available ephemeral port
|`bind-address` |all local addresses |String |Address to listen on (may be an IPV6 address as well)
|`backlog` |`1024` |int |Maximum length of the queue of incoming connections on the server socket.
|`max-header-size` |`8192` |int |Maximal number of bytes of all header values combined. Returns `400` if headers are bigger
|`max-initial-line-length` |`4096` |int |Maximal number of characters in the initial HTTP line. Returns `400` if line is longer
|`timeout-millis` |no timeout| long |Server socket timeout.
|`receive-buffer-size` |implementation default |int |Proposed value of the TCP receive window that is advertised to the remote peer on the server socket.
|`name` |`@default` for default socket |String |Name used for named sockets, to support additional server sockets (and their named routing)
|`enabled` |`true` |boolean |A socket can be disabled through configuration, in which case it is never opened
|`max-chunk-size` | `8192` |int |Maximal size of a chunk to read from incoming requests
|`validate-headers` |`true` |boolean |Whether to validate header names, if they contain illegal characters.
|`initial-buffer-size` |`128` |int |Initial size of buffer used to parse HTTP line and headers
|`tls` |{nbsp} |Object |Configuration of SSL, please see our SSL example in repository
|===
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,18 @@ public Builder keepAlive(boolean keepAlive) {
return this;
}

/**
* Whether to validate header names.
* Defaults to {@code true}.
*
* @param validate whether to validate the header name contains only allowed characters
* @return updated builder instance
*/
public Builder validateHeaders(boolean validate) {
configuration.validateHeaders(validate);
return this;
}

WebClientConfiguration configuration() {
configuration.clientServices(services());
return configuration.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class WebClientConfiguration {
private final MessageBodyWriterContext writerContext;
private final WebClientTls webClientTls;
private final URI uri;
private final boolean validateHeaders;

/**
* Creates a new instance of client configuration.
Expand Down Expand Up @@ -107,6 +108,7 @@ class WebClientConfiguration {
this.clientServices = Collections.unmodifiableList(builder.clientServices);
this.uri = builder.uri;
this.keepAlive = builder.keepAlive;
this.validateHeaders = builder.validateHeaders;
}

/**
Expand Down Expand Up @@ -267,6 +269,10 @@ boolean keepAlive() {
return keepAlive;
}

boolean validateHeaders() {
return validateHeaders;
}

/**
* A fluent API builder for {@link WebClientConfiguration}.
*/
Expand Down Expand Up @@ -295,6 +301,7 @@ static class Builder<B extends Builder<B, T>, T extends WebClientConfiguration>
private MessageBodyReaderContext readerContext;
private MessageBodyWriterContext writerContext;
private List<WebClientService> clientServices;
private boolean validateHeaders = true;
@SuppressWarnings("unchecked")
private B me = (B) this;

Expand Down Expand Up @@ -486,6 +493,18 @@ public B uri(URI uri) {
return me;
}

/**
* Whether to validate header names.
* Defaults to {@code true}.
*
* @param validate whether to validate the header name contains only allowed characters
* @return updated builder instance
*/
B validateHeaders(boolean validate) {
this.validateHeaders = validate;
return me;
}

@Override
public B addReader(MessageBodyReader<?> reader) {
this.readerContext.registerReader(reader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ private HttpVersion toNettyHttpVersion(Http.Version version) {
}

private HttpHeaders toNettyHttpHeaders() {
HttpHeaders headers = new DefaultHttpHeaders();
HttpHeaders headers = new DefaultHttpHeaders(this.configuration.validateHeaders());
try {
Map<String, List<String>> cookieHeaders = this.configuration.cookieManager().get(uri, new HashMap<>());
List<String> cookies = new ArrayList<>(cookieHeaders.get(Http.Header.COOKIE));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -57,10 +57,15 @@ class HttpInitializer extends ChannelInitializer<SocketChannel> {

private final SslContext sslContext;
private final NettyWebServer webServer;
private final SocketConfiguration soConfig;
private final Routing routing;
private final Queue<ReferenceHoldingQueue<DataChunk>> queues = new ConcurrentLinkedQueue<>();

HttpInitializer(SslContext sslContext, Routing routing, NettyWebServer webServer) {
HttpInitializer(SocketConfiguration soConfig,
SslContext sslContext,
Routing routing,
NettyWebServer webServer) {
this.soConfig = soConfig;
this.routing = routing;
this.sslContext = sslContext;
this.webServer = webServer;
Expand Down Expand Up @@ -91,7 +96,11 @@ public void initChannel(SocketChannel ch) {

// Set up HTTP/2 pipeline if feature is enabled
ServerConfiguration serverConfig = webServer.configuration();
HttpRequestDecoder requestDecoder = new HttpRequestDecoder();
HttpRequestDecoder requestDecoder = new HttpRequestDecoder(soConfig.maxInitialLineLength(),
soConfig.maxHeaderSize(),
8192,
soConfig.validateHeaders(),
soConfig.initialBufferSize());
if (serverConfig.isHttp2Enabled()) {
ExperimentalConfiguration experimental = serverConfig.experimental();
Http2Configuration http2Config = experimental.http2();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,10 @@ class NettyWebServer implements WebServer {
bootstrap.option(ChannelOption.SO_RCVBUF, soConfig.receiveBufferSize());
}

HttpInitializer childHandler = new HttpInitializer(sslContext, namedRoutings.getOrDefault(name, routing), this);
HttpInitializer childHandler = new HttpInitializer(soConfig,
sslContext,
namedRoutings.getOrDefault(name, routing),
this);
initializers.add(childHandler);
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,31 @@ public int receiveBufferSize() {
return socketConfig.receiveBufferSize();
}

@Override
public int maxHeaderSize() {
return socketConfig.maxHeaderSize();
}

@Override
public int maxInitialLineLength() {
return socketConfig.maxInitialLineLength();
}

@Override
public int maxChunkSize() {
return socketConfig.maxChunkSize();
}

@Override
public boolean validateHeaders() {
return socketConfig.validateHeaders();
}

@Override
public int initialBufferSize() {
return socketConfig.initialBufferSize();
}

@Override
public Tracer tracer() {
return tracer;
Expand Down Expand Up @@ -141,6 +166,11 @@ static class SocketConfig implements SocketConfiguration {
private final String name;
private final boolean enabled;
private final ClientAuthentication clientAuth;
private final int maxHeaderSize;
private final int maxInitialLineLength;
private final int maxChunkSize;
private final boolean validateHeaders;
private final int initialBufferSize;

/**
* Creates new instance.
Expand All @@ -153,6 +183,12 @@ static class SocketConfig implements SocketConfiguration {
this.backlog = builder.backlog() < 0 ? DEFAULT_BACKLOG_SIZE : builder.backlog();
this.timeoutMillis = Math.max(builder.timeoutMillis(), 0);
this.receiveBufferSize = Math.max(builder.receiveBufferSize(), 0);
this.maxHeaderSize = builder.maxHeaderSize();
this.maxInitialLineLength = builder.maxInitialLineLength();
this.maxChunkSize = builder.maxChunkSize();
this.validateHeaders = builder.validateHeaders();
this.initialBufferSize = builder.initialBufferSize();

WebServerTls webServerTls = builder.tlsConfig();
if (webServerTls.enabled()) {
this.sslContext = webServerTls.sslContext();
Expand Down Expand Up @@ -214,5 +250,30 @@ public String name() {
public boolean enabled() {
return enabled;
}

@Override
public int maxHeaderSize() {
return maxHeaderSize;
}

@Override
public int maxInitialLineLength() {
return maxInitialLineLength;
}

@Override
public int maxChunkSize() {
return maxChunkSize;
}

@Override
public boolean validateHeaders() {
return validateHeaders;
}

@Override
public int initialBufferSize() {
return initialBufferSize;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,18 @@ public Builder receiveBufferSize(int bytes) {
return this;
}

@Override
public Builder maxHeaderSize(int size) {
defaultSocketBuilder.maxHeaderSize(size);
return this;
}

@Override
public Builder maxInitialLineLength(int length) {
defaultSocketBuilder.maxInitialLineLength(length);
return this;
}

/**
* Adds an additional named server socket configuration. As a result, the server will listen
* on multiple ports.
Expand Down
Loading