Skip to content

Commit

Permalink
feat: Add @arcjet/ip utility (#322)
Browse files Browse the repository at this point in the history
  • Loading branch information
blaine-arcjet authored Dec 13, 2024
1 parent 38483dc commit a7a2fe0
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 6 deletions.
79 changes: 79 additions & 0 deletions src/content/docs/ip.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
title: "Arcjet IP detection reference"
description: "Reference for the Arcjet IP detection library"
prev: false
next: false
---

import { Code } from "@astrojs/starlight/components";
import DisplayType from "@/components/DisplayType.astro";
import WhatAreArcjetUtilities from "@/components/WhatAreArcjetUtilities.astro";
import Comments from "@/components/Comments.astro";

The Arcjet IP detection library provides a utility to find the public IP of a
Request.

<WhatAreArcjetUtilities />

## Why

The public IP of a Request is difficult to discern, but some platforms provide
specific mechanisms for accessing it—such as the `X-Real-IP` header added or
overwritten by Vercel. The `@arcjet/ip` library provides a streamlined API over
these mechanisms based on the current platform.

:::caution[Considerations]
The IP should not be trusted as it can be spoofed in most cases, especially when
loaded via the `Headers` object. We apply additional platform guards if a
platform is supplied in the `options` argument.

If a private/internal address is encountered, it will be skipped. If only those
are detected, an empty string is returned.
:::

## Install

```sh
npm install -S @arcjet/ip
```

## Usage

import IpUsage from "@/snippets/ip/usage.ts?raw";

<Code code={IpUsage} lang="ts" />

### Platform protections

Additional guards can be applied with the `platform` option, such as
`{ platform: "fly-io" }`, `{ platform: "cloudflare" }`, or
`{ platform: "vercel" }`.

import IpPlatform from "@/snippets/ip/platform.ts?raw";

<Code code={IpPlatform} lang="ts" />

### Proxy filtering

Most proxies will add themselves in the chain of public IP addresses. Trusted
proxies may be specified with the `proxies` option, and they will be
ignored when detecting a public IP.

import IpProxies from "@/snippets/ip/proxies.ts?raw";

<Code code={IpProxies} lang="ts" />

## API

### `ip(request: RequestLike, options?: Options)`

Look up an IP address in a Request-like object, such as `Request`, Node's
`http.IncomingMessage`, or Next.js' `NextRequest`.

**Types:**

<DisplayType type="RequestLike" from="@arcjet/ip" />
<DisplayType type="Options" from="@arcjet/ip" />
<DisplayType type="Platform" from="@arcjet/ip" />

<Comments />
16 changes: 10 additions & 6 deletions src/lib/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,30 +277,34 @@ export const main = [
collapsed: false,
items: [
{
label: "Redact",
label: "Nosecone",
collapsed: true,
items: [
{
label: "Quick start",
link: "/redact/quick-start",
link: "/nosecone/quick-start",
},
{
label: "Reference",
link: "/redact/reference",
link: "/nosecone/reference",
},
],
},
{
label: "Nosecone",
label: "@arcjet/ip",
link: "/ip",
},
{
label: "@arcjet/redact",
collapsed: true,
items: [
{
label: "Quick start",
link: "/nosecone/quick-start",
link: "/redact/quick-start",
},
{
label: "Reference",
link: "/nosecone/reference",
link: "/redact/reference",
},
],
},
Expand Down
9 changes: 9 additions & 0 deletions src/snippets/ip/platform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import ip from "@arcjet/ip";

// Some Request-like object, such as node's `http.IncomingMessage`, `Request` or
// Next.js' `NextRequest`
const request = new Request("/your-route");

// Also optionally takes a platform for additional protection
const platformGuardedPublicIp = ip(request, { platform: "fly-io" });
console.log(platformGuardedPublicIp);
9 changes: 9 additions & 0 deletions src/snippets/ip/proxies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import ip from "@arcjet/ip";

// Some Request-like object, such as node's `http.IncomingMessage`, `Request` or
// Next.js' `NextRequest`
const request = new Request("/your-route");

// You can also pass a list of trusted proxies to ignore
const proxyExcludedPublicIp = ip(request, { proxies: ["103.31.4.0"] });
console.log(proxyExcludedPublicIp);
9 changes: 9 additions & 0 deletions src/snippets/ip/usage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import ip from "@arcjet/ip";

// Some Request-like object, such as node's `http.IncomingMessage`, `Request` or
// Next.js' `NextRequest`
const request = new Request("/your-route");

// Returns the first non-private IP address detected
const publicIp = ip(request);
console.log(publicIp);

0 comments on commit a7a2fe0

Please sign in to comment.