Skip to content

Commit d2eac13

Browse files
committed
Expose Request IP address
1 parent eff0d8d commit d2eac13

File tree

6 files changed

+36
-4
lines changed

6 files changed

+36
-4
lines changed

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"typescript": "^5.7.2"
3636
},
3737
"dependencies": {
38+
"@cldn/ip": "^1.0.3",
3839
"multipart-ts": "^1.3.0"
3940
}
4041
}

src/Request.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {IPAddress, IPv4, IPv6} from "@cldn/ip";
12
import {Multipart} from "multipart-ts";
23
import http, {OutgoingHttpHeader} from "node:http";
34
import stream from "node:stream";
@@ -26,23 +27,31 @@ export class Request {
2627
*/
2728
public readonly bodyStream: stream.Readable;
2829

30+
/**
31+
* IP address of request sender.
32+
*/
33+
public readonly ip: IPv4 | IPv6;
34+
2935
/**
3036
* Construct a new Request.
3137
* @param method See {@link Request#method}.
3238
* @param url See {@link Request#url}.
3339
* @param headers See {@link Request#headers}.
3440
* @param bodyStream See {@link Request#bodyStream}.
41+
* @param ip See {@link Request#ip}.
3542
*/
3643
protected constructor(
3744
method: Request["method"],
3845
url: Request["url"],
3946
headers: Request["headers"],
4047
bodyStream: Request["bodyStream"],
48+
ip: Request["ip"],
4149
) {
4250
this.method = method;
4351
this.url = url;
4452
this.headers = headers;
4553
this.bodyStream = bodyStream;
54+
this.ip = ip;
4655
}
4756

4857
/**
@@ -66,7 +75,11 @@ export class Request {
6675

6776
const headers = Request.headersFromNodeDict(incomingMessage.headers);
6877

69-
return new Request(incomingMessage.method as Request.Method, new URL(url), headers, incomingMessage);
78+
const remoteAddress = incomingMessage.socket.remoteAddress;
79+
if (remoteAddress === undefined)
80+
throw new Request.SocketClosedError();
81+
82+
return new Request(incomingMessage.method as Request.Method, new URL(url), headers, incomingMessage, IPAddress.fromString(remoteAddress));
7083
}
7184

7285
/**
@@ -212,4 +225,13 @@ export namespace Request {
212225
UNLOCK = "UNLOCK",
213226
UNSUBSCRIBE = "UNSUBSCRIBE",
214227
}
228+
229+
/**
230+
* Socket closed by peer.
231+
*/
232+
export class SocketClosedError extends Error {
233+
public constructor() {
234+
super("The socker was closed by the peer.");
235+
}
236+
}
215237
}

src/Server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class Server {
4747
this.errors._get(ServerErrorRegistry.ErrorCodes.BAD_URL)._send(res, this);
4848
return;
4949
}
50+
if (e instanceof Request.SocketClosedError)
51+
return;
5052
throw e;
5153
}
5254

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* Auto-generated by generateIndices.sh */
2-
export * from "./Request.js";
32
export * from "./Server.js";
3+
export * from "./Request.js";
44
export * from "./ServerErrorRegistry.js";
55
export * from "./response/index.js";
66
export * from "./routing/index.js";

src/response/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* Auto-generated by generateIndices.sh */
2-
export * from "./Response.js";
32
export * from "./EmptyResponse.js";
43
export * from "./BufferResponse.js";
5-
export * from "./JsonResponse.js";
64
export * from "./TextResponse.js";
5+
export * from "./JsonResponse.js";
6+
export * from "./Response.js";

0 commit comments

Comments
 (0)