help icon indicating copy to clipboard operation
help copied to clipboard

Is there a way to create a http server based on Fetch API? (Request, Response, Headers, ...)

Open krutoo opened this issue 2 years ago • 8 comments

Details

I want to create basic HTTP server with Node.js. I also want to declare request handler based on Fetch API like this:

import { serve } from 'node:http/nonexistent';

async function handler(request) {
  await doSomething();
  return new Response('{}', { headers: { 'content-type': 'application/json' } });
}

serve(handler, { port: 1234 });

Are there any built-in packages to achieve this?

If not, how to properly use the http package and convert IncomingMessage to Request and use the Response to send response in the handler of createServer function?

Node.js version

18+

Example code

Here is my naive implementation of the serve function. I have several quetions about it:

  • will such an implementation work fast enough? Or there are clear indicators of speed drawdown
  • can anyone suggest what use cases i'm missing (other than error handling)?
import { createServer } from 'node:http';
import { Readable } from 'node:stream';

export function serve({ port, fetch }) {
  const base = `http://localhost:${port}`;

  const server = createServer(async (req, res) => {
    const response = await fetch(
      new Request(new URL(req.url ?? '', base), {
        // body: ???
        headers: toHeaders(req.headers),
      }),
    );

    res.writeHead(response.status, [...response.headers]);

    if (response.body) {
      Readable.fromWeb(response.body).pipe(res);
    } else {
      res.end();
    }
  });

  server.listen(port);
}

function toHeaders(headers) {
  return Object.entries(headers).reduce((acc, [name, value]) => {
    if (typeof value === 'string') {
      acc.push([name, value]);
    } else if (Array.isArray(value)) {
      value.forEach(item => acc.push([name, item]));
    }

    return acc;
  }, []);
}

Operating system

macos

Scope

runtime

Module and version

Not applicable.

krutoo avatar Jun 05 '23 17:06 krutoo

Can you show how the request looks like

preveen-stack avatar Jun 13 '23 05:06 preveen-stack

@preveen-stack not quite understand what the request means?

krutoo avatar Jun 13 '23 08:06 krutoo

If not, how to properly use the http package and convert IncomingMessage to Request and use the Response to send response in the handler of createServer function? the "Request" you mentioned in the issue

preveen-stack avatar Jun 13 '23 08:06 preveen-stack

@preveen-stack global Node.js constructors Request and Response from Fetch API:

new Request('http://site.com', { method: 'POST' });
new Response('Not found', { status: 404 });

krutoo avatar Jun 13 '23 10:06 krutoo

This seems like a pretty nice thing for Node.js to have. I'm trying to write these conversion methods myself but it's easy to mis something 😅 could this be a rework of createServer

jensmeindertsma avatar Oct 28 '23 15:10 jensmeindertsma

Stumbled upon this while looking for solutions on how to use itty-router with node.js. Found this so far https://www.npmjs.com/package/@whatwg-node/server ... but it says it ponyfills, which is better than polyfilling, but it still does too much magic for my liking

bra1nDump avatar Nov 08 '23 06:11 bra1nDump

It seems there has been no activity on this issue for a while, and it is being closed in 30 days. If you believe this issue should remain open, please leave a comment. If you need further assistance or have questions, you can also search for similar issues on Stack Overflow. Make sure to look at the README file for the most updated links.

github-actions[bot] avatar May 07 '24 01:05 github-actions[bot]

@bra1nDump @whatwg-node/server is great, thanks

But it looks like a little tricky solution and i dont think this is get great performance

krutoo avatar May 07 '24 11:05 krutoo

It seems there has been no activity on this issue for a while, and it is being closed in 30 days. If you believe this issue should remain open, please leave a comment. If you need further assistance or have questions, you can also search for similar issues on Stack Overflow. Make sure to look at the README file for the most updated links.

github-actions[bot] avatar Nov 28 '24 01:11 github-actions[bot]

Are there any plans to add builtin utilities for creating an HTTP server on Fetch API in Node.js?

krutoo avatar Nov 28 '24 07:11 krutoo

You can use expressjs to create a fetch api.

Creating express project

  1. Create a directory for your project
mkdir my-express-app
cd my-express-app
  1. Install expressjs
npm install express
  1. Create your app file. For example, app.js
vim app.js
  1. In the app.js file, create your api
const express = require('express');    // import express 
const app = express();    // create an express app
const PORT = 3000;    // specify a port for the app to listen to

// Code your api here. For example:
app.get("/", (req, res) => {
    res.status(200).send("This is an example response.");
});    // replaceable

app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);
});    // this is required
  1. Save the file and run it with node
node app.js

karthikyadavgit avatar Dec 12 '24 08:12 karthikyadavgit

I'm closing this issue due to inactivity. At the current time, the only comments resolving the stalebot weren't relevant to resolving this issue, so I'll assume this is still stale.

To answer the question, no, there is not currently a way to write a server via the Fetch API, although you can always implement one :-).

avivkeller avatar Apr 07 '25 17:04 avivkeller

Is this still not even under consideration? Nowadays, pretty much every JS-runtime except Node supports this: see https://blog.val.town/blog/the-api-we-forgot-to-name/ or https://marvinh.dev/blog/modern-way-to-write-javascript-servers/

mb21 avatar Sep 27 '25 13:09 mb21