== Server

Jooby comes with three server implementations:

- javadoc:Jetty[]
- javadoc:Netty[]
- javadoc:Undertow[]

Server are automatically registered based on their presence on the project classpath.

To use Jetty, add the dependency:

[dependency, artifactId="jooby-jetty"]
.

To use Netty, add the dependency:

[dependency, artifactId="jooby-netty"]
.

To use Undertow, add the dependency:

[dependency, artifactId="jooby-utow"]
.

[IMPORTANT]
====
Only one server dependency must be available on classpath.
====

=== Options

Server options are available via javadoc:ServerOptions[] class:

.Server Options
[source,java,role="primary"]
----
{
  setServerOptions(new ServerOptions()
      .setBufferSize(16384)
      .setPort(8080)
      .setIoThreads(16)
      .setWorkerThreads(64)
      .setGzip(false)
      .setSingleLoop(false)
      .setDefaultHeaders(true)
      .setMaxRequestSize(10485760)
      .setSecurePort(8433)
      .setSsl(SslOptions.selfSigned())
  ); 
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  serverOptions {
    bufferSize = 16384
    port = 8080
    ioThreads = 16
    workerThreads = 64
    gzip = false
    singleLoop = false
    defaultHeaders = true
    maxRequestSize = 10485760
    securePort = 8443
    ssl = SslOptions.selfSigned()
  }
}
----

- bufferSize: Buffer size used by server for reading/writing data. Default is: `16k`.
- port: Server HTTP port or `0` for random port. Default is: `8080`.
- ioThreads: Number of IO threads used by the server. Used by Netty and Undertow. Default is: `Runtime.getRuntime().availableProcessors() * 2`
- workerThreads: Number of worker (a.k.a application) threads. Default is: `ioThreads * 8`.
- gzip: Gzip support. Default is: `false`.
- singleLoop: Indicates if the web server should use a single loop/group for doing IO or not. **Netty only**.
- defaultHeaders: Configure server to set the following headers: `Date`, `Content-Type` and `Server` headers.
- maxRequestSize: Maximum request size in bytes. Request exceeding this value results in 413(REQUEST_ENTITY_TOO_LARGE) response. Default is `10mb`.
- securePort: Configure Jooby to do HTTPs. This option is fully convered in next section.
- ssl: SSL options with certificate details.  This option is fully convered in next section.

Server options are available as application configuration properties too:

.application.conf
[source, properties]
----
server.bufferSize = 16384
server.port = 8080
server.ioThreads = 16
server.workerThreads = 64
server.gzip = false
server.singleLoop = false
server.defaultHeaders = true
server.maxRequestSize = 10485760
server.securePort = 8443
server.ssl.type = self-signed
----

=== SSL

Jooby supports HTTPS out of the box. By default HTTPS is disabled and all requests are served using 
HTTP. Jooby supports two certificate formats:

- PKCS12 (this is the default format)
- X.509

The javadoc:SslOptions[] class provides options to configure SSL:

- cert: A PKCS12 or X.509 certificate chain file in PEM format. It can be an absolute path or a classpath resource. Required.
- key:  A PKCS#8 private key file in PEM format. It can be an absolute path or a classpath resource. Required when using X.509 certificates.
- password: Password to use (if any). Optional. Default is: null/empty.


.Hello HTTPS
[source,java,role="primary"]
----
{
  setServerOptions(new ServerOptions()
      .setSecurePort(8443)             <1>
  ); 
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  serverOptions {
    securePort = 8443                  <1>
  }
}
----

<1> Set secure port and use a self-signed certificate

Once SSL is enabled application logs print something like:

----
listening on:
  http://localhost:8080/
  https://localhost:8443/
----

[IMPORTANT]
====
The `self-signed` certificate is useful for development but keep in mind it will generate a warning on the browser.
====

image::self-signed-not-secure.png[Not Secure]

A better option for development is the https://mkcert.dev[mkcert] tool:

.Generates a PKCS12 certificate
[source,bash,role="primary]
----
mkcrt -pkcs12 localhost
----

.Generates a X.509 certificate
[source,bash,role="secondary"]
----
mkcrt localhost
----

==== Using X.509

To use a valid X.509 certificate, for example one created with https://letsencrypt.org/[Let’s Encrypt]. You will need the `*.crt` and `*.key` files:

.X509
[source,java,role="primary"]
----
{
  SslOptions ssl = SslOptions.x509("path/to/server.crt", "path/to/server.key");
  setServerOptions(new ServerOptions()
      .setSsl(ssl)                                                    <1>
  ); 
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  serverOptions {
    ssl = SslOptions.x509("path/to/server.crt", "path/to/server.key")  <1>
  }
}
----

<1> Creates a SslOptions using X509 certificates path

Certificate (.crt) and private key (.key) location can be file system or class path locations.

Optionally you can define the SSL options in your application configuration file:

.Ssl options:
[source,json]
----
server {
  ssl {
    type: X509,
    cert: "path/to/server.crt",
    key: "path/to/server.key"
  }
}
----

.X509 from configuration
[source,java,role="primary"]
----
{
  setServerOptions(new ServerOptions()
      .setSsl(SslOptions.from(getConfig()))
  ); 
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  serverOptions {
    ssl = SslOptions.from(config)
  }
}
----

==== Using PKCS12

To use a valid PKCS12 certificate:

.PKCS12
[source,java,role="primary"]
----
{
  SslOptions ssl = SslOptions.pkcs12("path/to/server.p12", "password");
  setServerOptions(new ServerOptions()
      .setSsl(ssl)                                                      <1>
  ); 
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  serverOptions {
    ssl = SslOptions.x509("path/to/server.p12", "password")             <1>
  }
}
----

<1> Creates SslOptions using PKCS12 certificates path

Certificate (.crt) location can be file system or class path locations.

Optionally you can define the SSL options in your application configuration file:

.Ssl options:
[source,json]
----
server {
  ssl {
    type: PKCS12,
    cert: "path/to/server.p12",
    password: "password"
  }
}
----

.PKCS12 from configuration
[source,java,role="primary"]
----
{
  setServerOptions(new ServerOptions()
      .setSsl(SslOptions.from(getConfig()))
  ); 
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  serverOptions {
    ssl = SslOptions.from(config)
  }
}
----
