Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"typescript": "^5.7.2"
},
"dependencies": {
"@cldn/ip": "^1.0.3",
"multipart-ts": "^1.3.2"
}
}
24 changes: 23 additions & 1 deletion src/Request.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {IPAddress, IPv4, IPv6} from "@cldn/ip";
import {Multipart} from "multipart-ts";
import http, {OutgoingHttpHeader} from "node:http";
import stream from "node:stream";
Expand Down Expand Up @@ -26,23 +27,31 @@ export class Request {
*/
public readonly bodyStream: stream.Readable;

/**
* IP address of request sender.
*/
public readonly ip: IPv4 | IPv6;

/**
* Construct a new Request.
* @param method See {@link Request#method}.
* @param url See {@link Request#url}.
* @param headers See {@link Request#headers}.
* @param bodyStream See {@link Request#bodyStream}.
* @param ip See {@link Request#ip}.
*/
protected constructor(
method: Request["method"],
url: Request["url"],
headers: Request["headers"],
bodyStream: Request["bodyStream"],
ip: Request["ip"],
) {
this.method = method;
this.url = url;
this.headers = headers;
this.bodyStream = bodyStream;
this.ip = ip;
}

/**
Expand All @@ -66,7 +75,11 @@ export class Request {

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

return new Request(incomingMessage.method as Request.Method, new URL(url), headers, incomingMessage);
const remoteAddress = incomingMessage.socket.remoteAddress;
if (remoteAddress === undefined)
throw new Request.SocketClosedError();

return new Request(incomingMessage.method as Request.Method, new URL(url), headers, incomingMessage, IPAddress.fromString(remoteAddress));
}

/**
Expand Down Expand Up @@ -212,4 +225,13 @@ export namespace Request {
UNLOCK = "UNLOCK",
UNSUBSCRIBE = "UNSUBSCRIBE",
}

/**
* Socket closed by peer.
*/
export class SocketClosedError extends Error {
public constructor() {
super("The socker was closed by the peer.");
}
}
}
2 changes: 2 additions & 0 deletions src/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class Server {
this.errors._get(ServerErrorRegistry.ErrorCodes.BAD_URL)._send(res, this);
return;
}
if (e instanceof Request.SocketClosedError)
return;
throw e;
}

Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Auto-generated by generateIndices.sh */
export * from "./Request.js";
export * from "./Server.js";
export * from "./Request.js";
export * from "./ServerErrorRegistry.js";
export * from "./response/index.js";
export * from "./routing/index.js";
4 changes: 2 additions & 2 deletions src/response/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Auto-generated by generateIndices.sh */
export * from "./Response.js";
export * from "./EmptyResponse.js";
export * from "./BufferResponse.js";
export * from "./JsonResponse.js";
export * from "./TextResponse.js";
export * from "./JsonResponse.js";
export * from "./Response.js";