Fetch Handler

Get familiar with srvx fetch server handler and ServerRequest.

Request handler is defined via fetch key since it is similar to fetch API. The input is a Request object and handler should return a Response or a promise if the server handler is async.

Example:

import { serve } from "srvx";

serve({
  async fetch(request) {
    return new Response(
      `
        <h1>👋 Hello there</h1>
        <p>You are visiting ${request.url} from ${request.ip}</p>
      `,
      { headers: { "Content-Type": "text/html" } },
    );
  },
});

#Extended Request (ServerRequest)

Tip

You can use ServerRequest type export from srvx as type of request.

#request.ip?

Using request.ip allows to access connected client's IP address.

import { serve } from "srvx";

serve({
  fetch: (request) => new Response(`Your ip address is "${request.ip}"`),
});

#request.tls?

TLS connection state, including the client (peer) certificate, negotiated protocol and cipher. Added by the opt-in mtlsPlugin() (srvx/mtls); undefined for plain HTTP requests or when the plugin is not enabled.

Read more in TLS & mutual TLS.

#request.waitUntil?

Tell the runtime about an ongoing operation that shouldn't close until the promise resolves.

import { serve } from "srvx";

async function logRequest(request) {
  await fetch("https://telemetry.example.com", {
    method: "POST",
    body: JSON.stringify({
      method: request.method,
      url: request.url,
      ip: request.ip,
    }),
  });
}

serve({
  fetch: (request) => {
    request.waitUntil(logRequest(request));
    return new Response("OK");
  },
});

#request.runtime?.name?

Runtime name. Can be "bun", "deno", "node", "cloudflare" or any other string.

#request.runtime?.bun?

Using request.runtime.bun?.server you can access to the underlying Bun server.

#request.runtime?.deno?

Using request.runtime.deno?.server you can access to the underlying Deno server.

Using request.deno?.info you can access to the extra request information provided by Deno.

#request.runtime?.node?

Node.js is supported through a proxy that wraps node:IncomingMessage as Request and converting final state of node:ServerResponse to Response.

If access to the underlying Node.js request and response objects is required (only in Node.js runtime), you can access them via request.runtime?.node?.req (node:IncomingMessage) and request.runtime?.node?.res (node:ServerResponse).

import { serve } from "srvx";

serve({
  fetch: (request) => {
    if (request.runtime.node) {
      console.log("Node.js req url:", request.runtime.node?.req.url);
      request.runtime.node.res.statusCode = 418; // I'm a teapot!
    }
    return new Response("ok");
  },
});

Tip

srvx implementation of Request proxy directly uses the underlying node:IncomingMessage as source of truth. Any changes to Request will be reflected to the underlying node:IncomingMessage and vice versa.

Read more in Node.js support.