Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using itty-router locally #106

Closed
dremekie opened this issue May 2, 2022 · 8 comments
Closed

Using itty-router locally #106

dremekie opened this issue May 2, 2022 · 8 comments

Comments

@dremekie
Copy link

dremekie commented May 2, 2022

Could you share a snippet of how I would use Node to create a local http server that uses itty-router?

Something like:

const { Router } = require('itty-router');
const http = require('http');

const ittyRouter = Router();
ittyRouter.get('/about', () => {
  return 'My response';
});

const server = http.createServer(function (req) {
  ittyRouter.handle(req);
});

server.listen(4444);

With the above, GET http://127.0.0.1:4444/about throws TypeError [ERR_INVALID_URL]: Invalid URL

@bever1337
Copy link

bever1337 commented May 5, 2022

A node http request+response pair have almost no overlap with the JS-standard http request+response pair. There is no host or hostname field on the Node request, so it is not possible to construct a fully qualified url with new URL from a node request object. I think something like this will get you closer to using an itty handler:

const MY_HOST_NAME = ...; // I don't know your host name, but I bet you do!
const response = ittyRouter.handle(new Request(new URL(req.url, MY_HOST_NAME), request)); // this is async, should 
// now be sure to use node `res`! Unlike service workers or CF workers, you have to manually write to the response instead of just resolving

@bever1337
Copy link

Is it possible to convert this into a discussion? I started a similar thread here: #107

Instead of using itty with a node http server, I am using itty inside a service worker. Service workers have unique requirements about responding to events synchronously which itty cannot do.

I wonder if the itty README examples can show some platform-specific nuances for each use-case?

@Rush
Copy link

Rush commented May 11, 2022

I was considering using itty-router for a hybrid Cloudflare worker/node server app but looks like it's not supported. I need my code to run either on Cloudflare or locally depending on a use case.

@janat08
Copy link
Contributor

janat08 commented May 12, 2022

There's h3 router.

@Rush
Copy link

Rush commented May 12, 2022

Will check out h3, thank you!

@janat08
Copy link
Contributor

janat08 commented May 12, 2022

Miniflare is a better place for this issue.

@gerukin
Copy link

gerukin commented May 15, 2022

If you want to use itty in a normal node environment (Node 18+) you can do something like this:

import http from 'http'
import { Router } from 'itty-router'

const HOST = 'localhost'
const PORT = 8000

const baseRouter = Router()
// healthcheck endpoint
baseRouter.get('/ok', () => new Response('🎉🎉🎉'))
// some json
baseRouter.get('/json', () => new Response(JSON.stringify({ status: 'ok' }), { headers: { 'content-type': 'application/json' } }))
// any other route is an error (should instead throw custom errors, with error codes and so on)
baseRouter.all('*', () => { throw new Error('💥💀💥') })

// start a regular node server
http.createServer(async (req, res) => {
	const resp = await baseRouter.handle(

		// ******************** 🙋‍♂️ ADAPTER STUFF : START ***********************
		// create a Request (requires node 18+) object from node's IncomingMessage,
		// which can be accepted by itty - router
		new Request(
			new URL(req.url, 'http://' + req.headers.host),
			{
				// should also map headers, body....
				method: req.method
			}
		)
		// *********************** ADAPTER STUFF : END ***********************

	).catch(err => new Response(err.message, { status: 500 }))

	// ******************** 🙋‍♂️ ADAPTER STUFF : START ***********************
	// map the Response to node's expected ServerResponse
	res.writeHead(resp.status, resp.statusText, resp.headers)
	res.end(await resp.text() + '\n')
	// *********************** ADAPTER STUFF : END ***********************

}).listen(PORT, HOST, err => {
	if (err) throw err
	console.log('Server listening on ' + HOST + ':' + PORT)
})

Haven't run any mem or perf benchmarks. I love itty in CF, but I'm not sure how this version with adapter in node compares to using h3, polka or other routers.

@ruslantalpa
Copy link

Or ... you could just add this line before calling handle

if (req.url && req.url[0] === '/') req.url = `http://${req.headers.host}${req.url}`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants