summaryrefslogtreecommitdiff
path: root/docs/runtime/http_server_apis.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/runtime/http_server_apis.md')
-rw-r--r--docs/runtime/http_server_apis.md258
1 files changed, 0 insertions, 258 deletions
diff --git a/docs/runtime/http_server_apis.md b/docs/runtime/http_server_apis.md
deleted file mode 100644
index 0d20c49ee..000000000
--- a/docs/runtime/http_server_apis.md
+++ /dev/null
@@ -1,258 +0,0 @@
-## HTTP Server APIs
-
-As of Deno 1.9 and later, _native_ HTTP server APIs were introduced which allow
-users to create robust and performant web servers in Deno.
-
-The API tries to leverage as much of the web standards as is possible as well as
-tries to be simple and straight forward.
-
-> ℹ️ The APIs are currently unstable, meaning they can change in the future in
-> breaking ways and should be carefully considered before using in production
-> code. They require the `--unstable` flag to make them available.
-
-### Listening for a connection
-
-In order to accept requests, first you need to listen for a connection on a
-network port. To do this in Deno, you use `Deno.listen()`:
-
-```ts
-const server = Deno.listen({ port: 8080 });
-```
-
-> ℹ️ When supplying a port, Deno assumes you are going to listen on a TCP socket
-> as well as bind to the localhost. You can specify `transport: "tcp"` to be
-> more explicit as well as provide an IP address or hostname in the `hostname`
-> property as well.
-
-If there is an issue with opening the network port, `Deno.listen()` will throw,
-so often in a server sense, you will want to wrap it in the `try ... catch`
-block in order to handle exceptions, like the port already being in use.
-
-You can also listen for a TLS connection (e.g. HTTPS) using `Deno.listenTls()`:
-
-```ts
-const server = Deno.listenTls({
- port: 8443,
- certFile: "localhost.crt",
- keyFile: "localhost.key",
- alpnProtocols: ["h2", "http/1.1"],
-});
-```
-
-The `certFile` and `keyFile` options are required and point to the appropriate
-certificate and key files for the server. They are relative to the CWD for Deno.
-The `alpnProtocols` property is optional, but if you want to be able to support
-HTTP/2 on the server, you add the protocols here, as the protocol negotiation
-happens during the TLS negotiation with the client and server.
-
-> ℹ️ Generating SSL certificates is outside of the scope of this documentation.
-> There are many resources on the web which address this.
-
-### Handling connections
-
-Once we are listening for a connection, we need to handle the connection. The
-return value of `Deno.listen()` or `Deno.listenTls()` is a `Deno.Listener` which
-is an async iterable which yields up `Deno.Conn` connections as well as provide
-a couple methods for handling connections.
-
-To use it as an async iterable we would do something like this:
-
-```ts
-const server = Deno.listen({ port: 8080 });
-
-for await (const conn of server) {
- // ...handle the connection...
-}
-```
-
-Every connection made would yielded up a `Deno.Conn` assigned to `conn`. Then
-further processing can be applied to the connection.
-
-There is also the `.accept()` method on the listener which can be used:
-
-```ts
-const server = Deno.listen({ port: 8080 });
-
-while (true) {
- try {
- const conn = await server.accept();
- // ... handle the connection ...
- } catch (err) {
- // The listener has closed
- break;
- }
-}
-```
-
-Whether using the async iterator or the `.accept()` method, exceptions can be
-thrown and robust production code should handle these using `try ... catch`
-blocks. Especially when it comes to accepting TLS connections, there can be many
-conditions, like invalid or unknown certificates which can be surfaced on the
-listener and might need handling in the user code.
-
-A listener also has a `.close()` method which can be used to close the listener.
-
-### Serving HTTP
-
-Once a connection is accepted, you can use `Deno.serveHttp()` to handle HTTP
-requests and responses on the connection. `Deno.serveHttp()` returns a
-`Deno.HttpConn`. A `Deno.HttpConn` is like a `Deno.Listener` in that requests
-the connection receives from the client are asynchronously yielded up as a
-`Deno.RequestEvent`.
-
-To deal with HTTP requests as async iterable it would look something like this:
-
-```ts
-const server = Deno.listen({ port: 8080 });
-
-for await (const conn of server) {
- (async () => {
- const httpConn = Deno.serveHttp(conn);
- for await (const requestEvent of httpConn) {
- // ... handle requestEvent ...
- }
- })();
-}
-```
-
-The `Deno.HttpConn` also has the method `.nextRequest()` which can be used to
-await the next request. It would look something like this:
-
-```ts
-const server = Deno.listen({ port: 8080 });
-
-while (true) {
- try {
- const conn = await server.accept();
- (async () => {
- const httpConn = Deno.serveHttp(conn);
- while (true) {
- try {
- const requestEvent = await httpConn.nextRequest();
- // ... handle requestEvent ...
- } catch (err) {
- // the connection has finished
- break;
- }
- }
- })();
- } catch (err) {
- // The listener has closed
- break;
- }
-}
-```
-
-Note that in both cases we are using an IIFE to create an inner function to deal
-with each connection. If we awaited the HTTP requests in the same function scope
-as the one we were receiving the connections, we would be blocking accepting
-additional connections, which would make it seem that our server was "frozen".
-In practice, it might make more sense to have a separate function all together:
-
-```ts
-async function handle(conn: Deno.Conn) {
- const httpConn = Deno.serveHttp(conn);
- for await (const requestEvent of httpConn) {
- // ... handle requestEvent
- }
-}
-
-const server = Deno.listen({ port: 8080 });
-
-for await (const conn of server) {
- handle(conn);
-}
-```
-
-In the examples from this point on, we will focus on what would occur within an
-example `handle()` function and remove the listening and connection
-"boilerplate".
-
-### HTTP Requests and Responses
-
-HTTP requests and responses in Deno are essentially the inverse of web standard
-[Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). The
-Deno HTTP Server API and the Fetch API leverage the
-[`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and
-[`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object
-classes. So if you are familiar with the Fetch API you just need to flip them
-around in your mind and now it is a server API.
-
-As mentioned above, a `Deno.HttpConn` asynchronously yields up
-`Deno.RequestEvent`s. These request events contain a `.request` property and a
-`.respondWith()` method.
-
-The `.request` property is an instance of the `Request` class with the
-information about the request. For example, if we wanted to know what URL path
-was being requested, we would do something like this:
-
-```ts
-async function handle(conn: Deno.Conn) {
- const httpConn = Deno.serveHttp(conn);
- for await (const requestEvent of httpConn) {
- const url = new URL(requestEvent.request.url);
- console.log(`path: ${url.path}`);
- }
-}
-```
-
-The `.respondWith()` method is how we complete a request. The method takes
-either a `Response` object or a `Promise` which resolves with a `Response`
-object. Responding with a basic "hello world" would look like this:
-
-```ts
-async function handle(conn: Deno.Conn) {
- const httpConn = Deno.serveHttp(conn);
- for await (const requestEvent of httpConn) {
- await requestEvent.respondWith(
- new Response("hello world", {
- status: 200,
- }),
- );
- }
-}
-```
-
-Note that we awaited the `.respondWith()` method. It isn't required, but in
-practice any errors in processing the response will cause the promise returned
-from the method to be rejected, like if the client disconnected before all the
-response could be sent. While there may not be anything your application needs
-to do, not handling the rejection will cause an "unhandled rejection" to occur
-which will terminate the Deno process, which isn't so good for a server. In
-addition, you might want to await the promise returned in order to determine
-when to do any cleanup from for the request/response cycle.
-
-The web standard `Response` object is pretty powerful, allowing easy creation of
-complex and rich responses to a client, and Deno strives to provide a `Response`
-object that as closely matches the web standard as possible, so if you are
-wondering how to send a particular response, checkout out the documentation for
-the web standard
-[`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response).
-
-### HTTP/2 Support
-
-HTTP/2 support is effectively transparent within the Deno runtime. Typically
-HTTP/2 is negotiated between a client and a server during the TLS connection
-setup via
-[ALPN](https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation). To
-enable this, you need to provide the protocols you want to support when you
-start listening via the `alpnProtocols` property. This will enable the
-negotiation to occur when the connection is made. For example:
-
-```ts
-const server = Deno.listenTls({
- port: 8443,
- certFile: "localhost.crt",
- keyFile: "localhost.key",
- alpnProtocols: ["h2", "http/1.1"],
-});
-```
-
-The protocols are provided in order of preference. In practice, the only two
-protocols that are supported currently are HTTP/2 and HTTP/1.1 which are
-expressed as `h2` and `http/1.1`.
-
-Currently Deno does not support upgrading a plain-text HTTP/1.1 connection to an
-HTTP/2 cleartext connection via the `Upgrade` header (see:
-[#10275](https://github.com/denoland/deno/issues/10275)), so therefore HTTP/2
-support is only available via a TLS/HTTPS connection.