5

I'm interested in capturing the Internet Protocol (IP) address of my users at their initial submit to my website. I was under the impression that a SvelteKit submit would be similar to other node.js server solution.

I've been all over this posting, and I'm just not seeing anything remotely like req.headers['x-forwarded-for'] or req.socket.remoteAddress in my request submit to API server in SvelteKit.

Here's what I do see in the request (via a console log in the API submit):

arg1:
    body: (... data ... )
    Headers:
        accept:'*/*'
        accept-encoding:'gzip, deflate'
        accept-language:'en-US,en;q=0.9'
        connection:'keep-alive'
        content-length:'141'
        content-type:'text/plain;charset=UTF-8'
        cookie:'userid=c03efd10-3085-46cb-bacd-9eaeb605426e'
        host:'192.168.1.22:3000'
        origin:'http://192.168.1.22:3000'
        referer:'http://192.168.1.22:3000/learn'
        user-agent:'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
    locals:
        userid: '....'
    method: 'POST'
    params: {}
    path: '/api/user_form'
    query: ...
    rawBody: ... 

Definitely no socket, no header for ['x-forwarded-for']

Note, I'm working this on local network. Host on one machine, client on another machine in the same network. In fact, host = 192.168.1.22:3000, client = 192.168.1.4

Note2, I'm running the program via svelte-kit dev --host 0.0.0.0

What am I not seeing? Is there a way to obtain a client user's IP address from a websubmit using Sveltekit?

zipzit
  • 3,778
  • 4
  • 35
  • 63
  • Perhaps a better way to access a more 'pure' request object would be to use middleware. In production this would depend on your adapter, but in dev mode see [here](https://kit.svelte.dev/faq#how-do-i-use-x-with-sveltekit-how-do-i-use-middleware). – Thomas Hennes Dec 29 '21 at 08:14

3 Answers3

4

Just to let ppl know... that's now possible, using event.clientAddress

evdama
  • 2,166
  • 1
  • 16
  • 17
  • @OliverDixon you need to use ADDRESS_HEADER and XFF_DEPTH probably (depending on your adapter), see https://kit.svelte.dev/docs/adapter-node#environment-variables-address-header-and-xff-depth – coyotte508 Jun 15 '23 at 21:43
3

Everything below is for production / build code.

> npm run build
> node build

Running your app in dev mode is different due to VITE.


The Svelte Adapter receives a Node Request which also includes the remote IP. The IP could be extracted with the methods mentioned here.

The Adapter however only forwards the values required for the Svelte IncomingRequest interface to the Svelte Render. This interface is then further extended by Svelte to a Request interface and includes the following values:

export interface Request<Locals = Record<string, any>, Body = unknown> {
    url: URL;
    method: string;
    headers: RequestHeaders;
    rawBody: RawBody;
    params: Record<string, string>;
    body: ParameterizedBody<Body>;
    locals: Locals;
}

Therefore, I see four possible ways to tackle this issue:

  1. Create an issue to update the Svelte IncomingRequest interface to include the remote IP. (This would also require an update in all Adapters)
  2. Create your own Middleware as an entry point for your application. The downside is, that you still wont get the remote IP anywhere in your Svelte handle or routes. You could however log the IP or block certain paths.
  3. Run your app behind a proxy, the proxy would populate ['x-forwarded-for'] in the request header and as shown in the interface above, the header is available in your Svelte Request object.
  4. Modify the Svelte IncomingRequest interface and Adapter Middleware on your own. (This is dirty and a mess to maintain)

Since 2. is the most applicable way, here is an example on how to set it up with polka - you could of course also use express or any other HTTP server.

/src/server.js file which is our Middleware in this case:

import polka from 'polka'
import { assetsMiddleware, prerenderedMiddleware, kitMiddleware } from '../build/middlewares.js'

const { PORT, DOMAIN } = process.env

polka()
  .use((req, res, next) => {
      console.log(req.socket.remoteAddress);
    next()
  })

  // Load the SvelteKit build
  .use(assetsMiddleware, prerenderedMiddleware, kitMiddleware)

  .listen(PORT)

/svelte.config.js to configure our Middleware as the entryPoint - minimal example using the default adapter-node:

import preprocess from 'svelte-preprocess';
import adapter from '@sveltejs/adapter-node';

/** @type {import('@sveltejs/kit').Config} */
const config = {
    preprocess: preprocess(),

    kit: {
        adapter: adapter({ entryPoint: './src/server.js' }),
        target: '#svelte'
    }
};

export default config;
miwin
  • 1,160
  • 10
  • 12
  • Thx for your reply. Its going to take me a few days to digest and test what you have written here. I didn’t understand the whole VITE and dev thing. I have been looking at [Nax-ipware](https://github.com/neekware/fullerstack/tree/main/libs/nax-ipware) library. – zipzit Dec 30 '21 at 15:11
  • @zipzit an implementation of Nax-ipware should be doable in your own middleware as shown in 2.) above. However, i explained how you can add middleware in front of the default adapter-node which only runs in prod/build. If you want to add middleware in dev mode, you should look into [VITE Plugins](https://kit.svelte.dev/faq#how-do-i-use-x-with-sveltekit-how-do-i-use-middleware) – miwin Dec 30 '21 at 19:13
1

There's a ticket in Sveltekit that might address this feature, hopefully soon https://github.com/sveltejs/kit/pull/3993

evdama
  • 2,166
  • 1
  • 16
  • 17