# Fetch Handler

> Get familiar with srvx fetch server handler and ServerRequest.

Request handler is defined via `fetch` key since it is similar to [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) API. The input is a [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object and handler should return a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) or a promise if the server handler is async.

**Example:**

```js
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`.

</tip>

### `request.ip?`

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

```js
import { serve } from "srvx";

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

### `request.waitUntil?`

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

```js
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](https://nodejs.org/) is supported through a proxy that wraps [node:IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) and converting final state of [node:ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) to [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response).

If access to the underlying [Node.js](https://nodejs.org/) request and response objects is required (only in Node.js runtime), you can access them via `request.runtime?.node?.req` ([node:IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)) and `request.runtime?.node?.res` ([node:ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse)).

```js
import { serve } from "srvx";

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

<tip>

srvx implementation of [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) proxy directly uses the underlying [node:IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) as source of trust. Any changes to [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) will be reflected to the underlying [node:IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) and vise-versa.

</tip>

<read-more title="Node.js support" to="/guide/node">



</read-more>
