From 511badb1eab2daeadb8a301b954be8cde08ad49e Mon Sep 17 00:00:00 2001 From: Sumant Awasthi Date: Sun, 23 Jan 2022 19:20:11 +0530 Subject: [PATCH 1/6] removed config.md and make configurations part of Server page --- docs/website/docs/v1.x/dsl/server/config.md | 3 - docs/website/docs/v1.x/dsl/server/index.md | 122 ++++++++++++++++++++ 2 files changed, 122 insertions(+), 3 deletions(-) delete mode 100644 docs/website/docs/v1.x/dsl/server/config.md create mode 100644 docs/website/docs/v1.x/dsl/server/index.md diff --git a/docs/website/docs/v1.x/dsl/server/config.md b/docs/website/docs/v1.x/dsl/server/config.md deleted file mode 100644 index 50b2454a71..0000000000 --- a/docs/website/docs/v1.x/dsl/server/config.md +++ /dev/null @@ -1,3 +0,0 @@ -# Config - -Work in progress \ No newline at end of file diff --git a/docs/website/docs/v1.x/dsl/server/index.md b/docs/website/docs/v1.x/dsl/server/index.md new file mode 100644 index 0000000000..cb2d432fd0 --- /dev/null +++ b/docs/website/docs/v1.x/dsl/server/index.md @@ -0,0 +1,122 @@ +# Running HTTP Server and serving requests + +This section describes, how to build an HttpApp, a collection of "routes", and then how it is bound to a "port" to serve HTTP requests. + +## Building and running a simple Server +- First, the usual imports +```scala +import zhttp.http._ +import zhttp.service.Server +import zio._ +``` +- Build an HttpApp with a set of routes +```scala + val app: HttpApp[Any, Nothing] = Http.collect[Request] { + case Method.GET -> !! / "text" => Response.text("Hello World!") + case Method.GET -> !! / "json" => Response.json("""{"greetings": "Hello World!"}""") + } +``` +- As a convenience, zio provides an `App` trait with the main function of the application which returns `URIO[ZEnv, ExitCode]`. Directly use `Server.start` specifying port and mount the app to start the server +```scala + override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = + Server.start(8090, app.silent).exitCode +``` +## Building and running a Server in "forever" mode, with custom configurations. +1. Imports required by the advanced server. + ```scala + import zhttp.http._ + import zhttp.service.server.ServerChannelFactory + import zhttp.service.{EventLoopGroup, Server} + import zio._ + import scala.util.Try + ``` +2. The Server can be built incrementally with a `++` each returning a new Server overriding any default configuration. + ```scala + private val server = + Server.port(PORT) ++ // Setup port + Server.maxRequestSize(8 * 1024) ++ // handle max request size of 8 KB (default 4 KB) + Server.app(fooBar ++ app) // Setup the Http app + ``` + More properties are given in the [Server Configurations](#server-configurations) section below. +3. And then use ```Server.make``` to get a "managed" instance use it to run a server forever + ```scala + override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = { + server.make + .use(start => + console.putStrLn(s"Server started on port ${start.port}") + *> ZIO.never, + ).provideCustomLayer(ServerChannelFactory.auto ++ EventLoopGroup.auto(2)) + .exitCode + ``` + **Note**`ServerChannelFactory.auto ++ EventLoopGroup.auto(num Threads)` is supplied as an external dependency to choose netty transport type. One can leave it as `auto` to let the application handle it for you. + Also in `EventLoopGroup.auto(numThreads)` you can choose number of threads based on number of available processors. + +### Binding Server to a socket address +One can bind server to Inet address in multiple ways, either by providing a port number or +- If no port is provided, the default port is 8080 +- If port is 0, it will use a dynamically selected port. + +
+A complete example + +- Example below shows how the server can be started in forever mode to serve HTTP requests: + +```scala +import zhttp.http._ +import zhttp.service._ +import zhttp.service.server.ServerChannelFactory +import zio._ + +import scala.util.Try + +object HelloWorldAdvanced extends App { + // Set a port + private val PORT = 8090 + + private val fooBar: HttpApp[Any, Nothing] = Http.collect[Request] { + case Method.GET -> !! / "foo" => Response.text("bar") + case Method.GET -> !! / "bar" => Response.text("foo") + } + + private val app = Http.collectM[Request] { + case Method.GET -> !! / "random" => random.nextString(10).map(Response.text) + case Method.GET -> !! / "utc" => clock.currentDateTime.map(s => Response.text(s.toString)) + } + + private val server = + Server.port(PORT) ++ // Setup port + Server.paranoidLeakDetection ++ // Paranoid leak detection (affects performance) + Server.app(fooBar +++ app) // Setup the Http app + + override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = { + // Configure thread count using CLI + val nThreads: Int = args.headOption.flatMap(x => Try(x.toInt).toOption).getOrElse(0) + + // Create a new server + server.make + .use(_ => + // Waiting for the server to start + console.putStrLn(s"Server started on port $PORT") + + // Ensures the server doesn't die after printing + *> ZIO.never, + ) + .provideCustomLayer(ServerChannelFactory.auto ++ EventLoopGroup.auto(nThreads)) + .exitCode + } +} + ``` +
+ +## Server Configurations + +| **Configuration** | **Purpose and usage** | +| ----------- | ----------- | +| `Server.ssl(sslOptions)` | | +| `Server.acceptContinue` | | +| `Server.disableFlowControl` | | +| `Server.disableLeakDetection` | | +| `Server.simpleLeakDetection` | | +| `Server.paranoidLeakDetection` | | +| `Server.disableFlowControl` | | +| `Server.consolidateFlush` | | From c2b5b238c49ffc0639ed702716c3aee6a9554ca1 Mon Sep 17 00:00:00 2001 From: Sumant Awasthi Date: Sun, 23 Jan 2022 20:16:07 +0530 Subject: [PATCH 2/6] added server configurations --- docs/website/docs/v1.x/dsl/server/index.md | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/website/docs/v1.x/dsl/server/index.md b/docs/website/docs/v1.x/dsl/server/index.md index cb2d432fd0..0e6e26bf76 100644 --- a/docs/website/docs/v1.x/dsl/server/index.md +++ b/docs/website/docs/v1.x/dsl/server/index.md @@ -16,7 +16,7 @@ import zio._ case Method.GET -> !! / "json" => Response.json("""{"greetings": "Hello World!"}""") } ``` -- As a convenience, zio provides an `App` trait with the main function of the application which returns `URIO[ZEnv, ExitCode]`. Directly use `Server.start` specifying port and mount the app to start the server +- As a convenience, Zio provides an `App` trait with the main function of the application which returns `URIO[ZEnv, ExitCode]`. Directly use `Server.start` specifying a port and mount the app to start the server ```scala override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = Server.start(8090, app.silent).exitCode @@ -54,7 +54,7 @@ import zio._ ### Binding Server to a socket address One can bind server to Inet address in multiple ways, either by providing a port number or - If no port is provided, the default port is 8080 -- If port is 0, it will use a dynamically selected port. +- If specified port is 0, it will use a dynamically selected port.
A complete example @@ -110,13 +110,14 @@ object HelloWorldAdvanced extends App { ## Server Configurations -| **Configuration** | **Purpose and usage** | -| ----------- | ----------- | -| `Server.ssl(sslOptions)` | | -| `Server.acceptContinue` | | -| `Server.disableFlowControl` | | -| `Server.disableLeakDetection` | | -| `Server.simpleLeakDetection` | | -| `Server.paranoidLeakDetection` | | -| `Server.disableFlowControl` | | -| `Server.consolidateFlush` | | +| **Configuration** | **Purpose and usage** | +| ----------- | ----------- | +| `Server.app(httpApp)` | Mount routes. Refer to complete example above | +| `Server.port(portNum)` or `Server.bind(portNum)` | Bind server to the port, refer to examples above | +| `Server.ssl(sslOptions)` | Creates a new server with ssl options. [HttpsHelloWorld](https://github.com/dream11/zio-http/blob/main/example/src/main/scala/example/HttpsHelloWorld.scala) | +| `Server.acceptContinue` | Sends a [100 CONTINUE](https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3) | +| `Server.disableFlowControl` | Refer [Netty FlowControlHandler](https://netty.io/4.1/api/io/netty/handler/flow/FlowControlHandler.html) | +| `Server.disableLeakDetection` | Disable any leak detection Refer netty's [ResourceLeakDetector](https://netty.io/4.0/api/io/netty/util/ResourceLeakDetector.Level.html) | +| `Server.simpleLeakDetection` | Simplistic leak detection comes with small over head. Refer netty's [ResourceLeakDetector](https://netty.io/4.0/api/io/netty/util/ResourceLeakDetector.Level.html) | +| `Server.paranoidLeakDetection` | Comes with highest possible overhead (for testing purposes only). Refer netty's [ResourceLeakDetector](https://netty.io/4.0/api/io/netty/util/ResourceLeakDetector.Level.html) | +| `Server.consolidateFlush` | Flushing content is done in batches. Can potentially improve performance. | From cbbd3c5dd5b83551d9ab257bf1e24b2e44909aac Mon Sep 17 00:00:00 2001 From: Sumant Awasthi Date: Mon, 24 Jan 2022 10:14:28 +0530 Subject: [PATCH 3/6] markdwon appearing fine in docusaurus generated page --- docs/website/docs/v1.x/dsl/server/index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/website/docs/v1.x/dsl/server/index.md b/docs/website/docs/v1.x/dsl/server/index.md index 0e6e26bf76..912f5ad8d1 100644 --- a/docs/website/docs/v1.x/dsl/server/index.md +++ b/docs/website/docs/v1.x/dsl/server/index.md @@ -30,14 +30,13 @@ import zio._ import zio._ import scala.util.Try ``` -2. The Server can be built incrementally with a `++` each returning a new Server overriding any default configuration. +2. The Server can be built incrementally with a `++` each returning a new Server overriding any default configuration. (More properties are given in the [Server Configurations](#server-configurations) section below.) ```scala private val server = Server.port(PORT) ++ // Setup port Server.maxRequestSize(8 * 1024) ++ // handle max request size of 8 KB (default 4 KB) Server.app(fooBar ++ app) // Setup the Http app ``` - More properties are given in the [Server Configurations](#server-configurations) section below. 3. And then use ```Server.make``` to get a "managed" instance use it to run a server forever ```scala override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = { From 231d4ec253390686dd0f169f5e9254b06d398182 Mon Sep 17 00:00:00 2001 From: Sumant Awasthi Date: Mon, 24 Jan 2022 10:17:43 +0530 Subject: [PATCH 4/6] added one missing configuration --- docs/website/docs/v1.x/dsl/server/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/website/docs/v1.x/dsl/server/index.md b/docs/website/docs/v1.x/dsl/server/index.md index 912f5ad8d1..6830874b4a 100644 --- a/docs/website/docs/v1.x/dsl/server/index.md +++ b/docs/website/docs/v1.x/dsl/server/index.md @@ -111,7 +111,8 @@ object HelloWorldAdvanced extends App { | **Configuration** | **Purpose and usage** | | ----------- | ----------- | -| `Server.app(httpApp)` | Mount routes. Refer to complete example above | +| `Server.app(httpApp)` | Mount routes. Refer to complete example above | +| `Server.maxRequestSize(8 * 1024)` | handle max request size of 8 KB (default 4 KB) | | `Server.port(portNum)` or `Server.bind(portNum)` | Bind server to the port, refer to examples above | | `Server.ssl(sslOptions)` | Creates a new server with ssl options. [HttpsHelloWorld](https://github.com/dream11/zio-http/blob/main/example/src/main/scala/example/HttpsHelloWorld.scala) | | `Server.acceptContinue` | Sends a [100 CONTINUE](https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3) | From 749189759afe75daceb69ea232f2c26965b9b999 Mon Sep 17 00:00:00 2001 From: Sumant Awasthi Date: Thu, 27 Jan 2022 09:51:03 +0530 Subject: [PATCH 5/6] Server documentation changed according to PR comments --- docs/website/docs/v1.x/dsl/server/index.md | 24 +++++----------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/docs/website/docs/v1.x/dsl/server/index.md b/docs/website/docs/v1.x/dsl/server/index.md index 6830874b4a..961343e0c3 100644 --- a/docs/website/docs/v1.x/dsl/server/index.md +++ b/docs/website/docs/v1.x/dsl/server/index.md @@ -1,28 +1,14 @@ -# Running HTTP Server and serving requests +# ZIO HTTP Server -This section describes, how to build an HttpApp, a collection of "routes", and then how it is bound to a "port" to serve HTTP requests. +This section describes, ZIO HTTP Server and different configurations you can provide while creating the Server -## Building and running a simple Server -- First, the usual imports -```scala -import zhttp.http._ -import zhttp.service.Server -import zio._ -``` -- Build an HttpApp with a set of routes -```scala - val app: HttpApp[Any, Nothing] = Http.collect[Request] { - case Method.GET -> !! / "text" => Response.text("Hello World!") - case Method.GET -> !! / "json" => Response.json("""{"greetings": "Hello World!"}""") - } -``` -- As a convenience, Zio provides an `App` trait with the main function of the application which returns `URIO[ZEnv, ExitCode]`. Directly use `Server.start` specifying a port and mount the app to start the server +## Start a ZIO HTTP Server with default configurations ```scala override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = Server.start(8090, app.silent).exitCode ``` -## Building and running a Server in "forever" mode, with custom configurations. -1. Imports required by the advanced server. +## Start a ZIO HTTP Server with custom configurations. +1. Imports required by the customised server. ```scala import zhttp.http._ import zhttp.service.server.ServerChannelFactory From 48fccf0eb9e307f8291b7ccba3b7e9a61b92a76b Mon Sep 17 00:00:00 2001 From: amitsingh Date: Thu, 27 Jan 2022 10:16:02 +0530 Subject: [PATCH 6/6] change note to tip --- docs/website/docs/v1.x/dsl/server/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/website/docs/v1.x/dsl/server/index.md b/docs/website/docs/v1.x/dsl/server/index.md index 961343e0c3..eff8c9feff 100644 --- a/docs/website/docs/v1.x/dsl/server/index.md +++ b/docs/website/docs/v1.x/dsl/server/index.md @@ -33,7 +33,7 @@ This section describes, ZIO HTTP Server and different configurations you can pro ).provideCustomLayer(ServerChannelFactory.auto ++ EventLoopGroup.auto(2)) .exitCode ``` - **Note**`ServerChannelFactory.auto ++ EventLoopGroup.auto(num Threads)` is supplied as an external dependency to choose netty transport type. One can leave it as `auto` to let the application handle it for you. + **Tip :** `ServerChannelFactory.auto ++ EventLoopGroup.auto(num Threads)` is supplied as an external dependency to choose netty transport type. One can leave it as `auto` to let the application handle it for you. Also in `EventLoopGroup.auto(numThreads)` you can choose number of threads based on number of available processors. ### Binding Server to a socket address