Reading the client IP address
Getting the client IP address in Kaito differs depending on what server runtime you’re using and also if you are using a reverse proxy or not.
For example, if you are using a reverse proxy like Cloudflare, you’ll need to use the cf-connecting-ip header to get the client IP address.
Cloudflare proxy example
import {create, KaitoError} from '@kaito-http/core';
export const router = create({
getContext: async req => ({req}),
});
export const myRouter = router.get('/ip', async ({ctx}) => {
const ip = ctx.req.headers.get('cf-connecting-ip'); // you must pass `.req` in your context object
if (!ip) {
throw new KaitoError(400, 'Probably not behind Cloudflare!');
}
return ip;
});Other reverse proxies will have different headers, nginx for example uses x-forwarded-for. Consult the docs of your reverse proxy to see how to get the client IP address.
Most production applications run behind reverse proxies, so you’ll typically want the client’s original IP address rather than the proxy’s connection IP. If you actually do need the direct connection IP, you’ll have to consult the docs of your server runtime. Below are a couple snippets that may be helpful, though.
Bun
With Bun.serve(), you can access the client IP address with the server’s .remoteIP method. We recommend storing this in AsyncLocalStorage so you can access it in your route handlers.
Bear in mind that you can move the ip property to your context object to make it cleaner to access. Below is a lightweight example.
import {AsyncLocalStorage} from 'node:async_hooks';
import {create} from '@kaito-http/core';
const ipStore = new AsyncLocalStorage<string>();
const router = create();
const app = router.get('/ip', async ({ctx}) => {
const ip = ipStore.getStore()!;
return ip;
});
const handle = app.serve();
const server = Bun.serve({
port: 3000,
fetch: async (request, server) => {
const ip = server.remoteIP(request);
return ipStore.run(ip, () => handle(request));
},
});Node.js
Since you’ll be using @kaito-http/uws with Node.js, the client IP address is available through the context parameter passed to your fetch handler. If you need to access it in nested functions or route handlers, you can use AsyncLocalStorage to make it available throughout the request lifecycle.
import {create} from '@kaito-http/core';
import {Server, getRemoteAddress} from '@kaito-http/uws';
const router = create({
getContext: async req => ({req}),
});
const app = router.get('/ip', async ({ctx}) => {
// getRemoteAddress works during the request lifecycle when using @kaito-http/uws
const ip = getRemoteAddress(ctx.req);
return ip;
});
const handle = app.serve();
const server = await Server.serve({
port: 3000,
fetch: handle,
});If you’re not using Bun or Node.js, you should consult the docs of your server runtime to see how to get the client IP address. We’ll happily accept a PR to this docs page to add snippets for other server runtimes.
Older versions
Previous versions of Kaito were Node.js only, so you could access req.socket.remoteAddress directly. The Web Fetch API does not have a .socket property on requests, so you will need to use whatever your server runtime provides instead.