@profullstack/x402-gateway 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/edge.js +16 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/x402-gateway",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "Sell crawl access to AI training crawlers by the day over x402, settled by CoinPay. One middleware: 402 with an offer, a sales page with CLI instructions, signed passes, and a robots.txt that keeps search crawlers welcome.",
6
6
  "keywords": [
package/src/edge.js CHANGED
@@ -59,16 +59,25 @@ export function inCidrs(ip, compiled) {
59
59
  /**
60
60
  * The caller's address, as the edge reported it.
61
61
  *
62
- * `x-forwarded-for` is a list the client can seed; the LAST hop appended by
63
- * our own edge is trustworthy and the first is not, but every platform in
64
- * front of these sites (Railway, a bare droplet behind nginx) puts the real
65
- * client first and nothing else, so first is what is used. `x-real-ip` is the
66
- * nginx spelling of the same thing.
62
+ * `x-forwarded-for` is a list the client can seed, and a denylist read from
63
+ * its first entry is a denylist any client can step around by sending one.
64
+ * The entry our own edge appends is the LAST, on every platform in front of
65
+ * these sites (Railway's proxy, nginx with `$proxy_add_x_forwarded_for`), so
66
+ * last is what is used. `x-real-ip` is nginx's spelling of the same hop and
67
+ * is preferred when present, because nginx sets it from the socket and
68
+ * nothing a client sends survives into it.
69
+ *
70
+ * A CDN in front of the edge would make the last hop the CDN's; put its
71
+ * ranges nowhere near `denyCidrs` and this still fails safe: nothing is
72
+ * refused, nothing is charged, by this check.
67
73
  */
68
74
  export function clientIp(request) {
75
+ const real = request.headers.get('x-real-ip')?.trim();
76
+ if (real) return real;
69
77
  const xff = request.headers.get('x-forwarded-for');
70
- if (xff) return xff.split(',')[0].trim();
71
- return request.headers.get('x-real-ip')?.trim() ?? '';
78
+ if (!xff) return '';
79
+ const hops = xff.split(',').map((h) => h.trim()).filter(Boolean);
80
+ return hops[hops.length - 1] ?? '';
72
81
  }
73
82
 
74
83
  /* -------------------------------------------------------------- spoofing -- */