1+ import { IPAddress , IPv4 , IPv6 } from "@cldn/ip" ;
12import { Multipart } from "multipart-ts" ;
23import http , { OutgoingHttpHeader } from "node:http" ;
34import stream from "node:stream" ;
@@ -26,28 +27,37 @@ 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 /**
4958 * Create a new Request from a Node.js incoming HTTP request.
5059 * @throws {@link Request.BadUrlError } If the request URL is invalid.
60+ * @throws {@link Request.SocketClosedError } If the request socket was closed before the request could be handled.
5161 */
5262 public static incomingMessage ( incomingMessage : http . IncomingMessage ) {
5363 const auth =
@@ -66,7 +76,11 @@ export class Request {
6676
6777 const headers = Request . headersFromNodeDict ( incomingMessage . headers ) ;
6878
69- return new Request ( incomingMessage . method as Request . Method , new URL ( url ) , headers , incomingMessage ) ;
79+ const remoteAddress = incomingMessage . socket . remoteAddress ;
80+ if ( remoteAddress === undefined )
81+ throw new Request . SocketClosedError ( ) ;
82+
83+ return new Request ( incomingMessage . method as Request . Method , new URL ( url ) , headers , incomingMessage , IPAddress . fromString ( remoteAddress ) ) ;
7084 }
7185
7286 /**
@@ -212,4 +226,13 @@ export namespace Request {
212226 UNLOCK = "UNLOCK" ,
213227 UNSUBSCRIBE = "UNSUBSCRIBE" ,
214228 }
229+
230+ /**
231+ * Socket closed by peer.
232+ */
233+ export class SocketClosedError extends Error {
234+ public constructor ( ) {
235+ super ( "The socker was closed by the peer." ) ;
236+ }
237+ }
215238}
0 commit comments