Socket
Socket
Sign inDemoInstall

rjweb-server

Package Overview
Dependencies
63
Maintainers
1
Versions
369
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 9.6.0 to 9.7.0

7

CHANGELOG.md
# Changelog
## 9.7.0
- Fix windows route file importing
- Cache empty arraybuffers
- Add `<HttpRequestContext>.$body`
- Add `<WsMessageContext>.$message`
## 9.6.0

@@ -4,0 +11,0 @@

@@ -65,2 +65,36 @@ "use strict";

/**
* The Request Body as a Blob-like Object
* @example
* ```
* const size = await ctr.$body().size()
*
* return ctr.print(`The size of the body is ${size} bytes`)
* ```
* @since 9.7.0
*/ $body() {
const self = this;
return {
text() {
return self.rawBody('utf-8');
}, async json() {
const data = await self.body();
if (self.context.body.type === 'json')
return data;
throw new Error('Body is not JSON (make sure the content-type sent is application/json)');
}, arrayBuffer() {
return self.rawBodyBytes();
}, async formData() {
const data = await self.body();
if (self.context.body.type === 'url-encoded')
return data;
throw new Error('Body is not Form Data (make sure the content-type sent is application/x-www-form-urlencoded)');
}, async blob() {
return new Blob([await self.rawBodyBytes()]);
}, async size() {
const data = await self.rawBodyBytes();
return data.byteLength;
}
};
}
/**
* The Request Body (JSON and Urlencoding Automatically parsed if enabled)

@@ -67,0 +101,0 @@ * @since 0.4.0

31

lib/cjs/classes/request/WsMessageContext.js

@@ -12,2 +12,30 @@ "use strict";

/**
* The Request Message as a Blob-like Object
* @example
* ```
* const size = await ctr.$message().size()
*
* return ctr.print(`The size of the message is ${size} bytes`)
* ```
* @since 9.7.0
*/ $message() {
const self = this;
return {
text() {
return self.rawMessage('utf-8');
}, json() {
const data = self.message();
if (self.context.body.type === 'json')
return data;
throw new Error('Message is not valid JSON');
}, arrayBuffer() {
return self.rawMessageBytes();
}, blob() {
return new Blob([self.rawMessageBytes()]);
}, size() {
return self.rawMessageBytes().byteLength;
}
};
}
/**
* The Websocket Message (JSON Automatically parsed if enabled)

@@ -17,3 +45,4 @@ * @since 5.4.0

const stringified = this.context.body.raw.toString();
if ((stringified.startsWith('{') && stringified.endsWith('}')) || (stringified.startsWith('[') && stringified.endsWith(']'))) {
if ((stringified[0] === '{' && stringified[stringified.length - 1] === '}') ||
(stringified[0] === '[' && stringified[stringified.length - 1] === ']')) {
try {

@@ -20,0 +49,0 @@ const json = JSON.parse(stringified);

4

lib/cjs/classes/router/File.js

@@ -13,2 +13,4 @@ "use strict";

const deepClone_1 = __importDefault(require("../../functions/deepClone"));
const os_1 = __importDefault(require("os"));
const platform = os_1.default.platform();
class File {

@@ -142,3 +144,3 @@ computePath(path) {

try {
const { default: router } = await eval(`import(${JSON.stringify(file.path)})`), // bypass ttsc converting to require() in cjs
const importPath = platform === 'win32' ? `file:///${file.path}` : file.path, { default: router } = await eval(`import(${JSON.stringify(importPath)})`), // bypass ttsc converting to require() in cjs
path = file.path.replace(resolved, '').replaceAll('index', '').replace(/\\/g, '/').split('.').slice(0, -1).join('.').concat('/');

@@ -145,0 +147,0 @@ if (router instanceof Path_1.default) {

@@ -19,3 +19,3 @@ "use strict";

* <p>${userInput}</p>
* `
* ` // XSS Vulnerable
*

@@ -25,3 +25,3 @@ * const secure = html`

* <p>${userInput}</p>
* `
* ` // XSS Safe
* ```

@@ -28,0 +28,0 @@ * @since 8.7.0

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mapping = {
const mapping = Object.freeze({
pdf: 'application/pdf',

@@ -82,4 +82,6 @@ js: 'text/javascript',

vcf: 'text/vcard',
ics: 'text/calendar'
};
ics: 'text/calendar',
abw: 'application/x-abiword',
azw: 'application/vnd.amazon.ebook'
});
/**

@@ -93,8 +95,10 @@ * Parse File Name into a Content Type or empty string

}
const end = name.split('.').at(-1);
const dot = name.lastIndexOf('.');
if (dot === -1)
return 'application/octet-stream';
const end = name.slice(dot + 1);
if (!end)
return 'application/octet-stream';
const type = mapping[end];
return type ?? 'application/octet-stream';
return mapping[end] ?? 'application/octet-stream';
}
exports.default = parseContentType;

@@ -9,3 +9,3 @@ "use strict";

const utils_1 = require("@rjweb/utils");
const trimString = (str) => {
function trimString(str) {
let start = 0, end = str.length - 1;

@@ -19,3 +19,3 @@ while (start < end && str[start] === ' ') {

return str.substring(start, end + 1);
};
}
exports.trimString = trimString;

@@ -45,5 +45,5 @@ /**

if (type === 'ValueCollection')
(0, utils_1.as)(values).set((0, exports.trimString)(keyValue.slice(progress, progress + equalPos)), decodedVal);
(0, utils_1.as)(values).set(trimString(keyValue.slice(progress, progress + equalPos)), decodedVal);
else
(0, utils_1.as)(values)[(0, exports.trimString)(keyValue.slice(progress, progress + equalPos))] = decodedVal;
(0, utils_1.as)(values)[trimString(keyValue.slice(progress, progress + equalPos))] = decodedVal;
progress = splitterPos + 1;

@@ -50,0 +50,0 @@ }

@@ -48,3 +48,3 @@ "use strict";

if (context.headers.get('if-none-match') === eTag) {
await rawContext.status(status_1.default.NOT_MODIFIED, 'Not Modified').write(new ArrayBuffer(0));
await rawContext.status(status_1.default.NOT_MODIFIED, 'Not Modified').write(context.global.cache.emptyArrayBuffer);
return false;

@@ -62,3 +62,3 @@ }

.status(context.response.status, context.response.statusText || http_1.STATUS_CODES[context.response.status] || 'Unknown')
.write(new ArrayBuffer(0));
.write(context.global.cache.emptyArrayBuffer);
return false;

@@ -65,0 +65,0 @@ }

{
"name": "rjweb-server",
"version": "9.6.0",
"version": "9.7.0",
"description": "Easy and Robust Way to create a Web Server with Many Easy-to-use Features in NodeJS",

@@ -49,3 +49,3 @@ "main": "./lib/cjs/index.js",

"@types/inquirer": "^9.0.7",
"@types/node": "^20.12.12",
"@types/node": "^20.14.2",
"@types/yargs": "^17.0.32",

@@ -61,5 +61,5 @@ "rjweb-server": "link:",

"dependencies": {
"@rjweb/utils": "^1.12.15",
"@rjweb/utils": "^1.12.20",
"content-disposition": "^0.5.4",
"inquirer": "^9.2.22",
"inquirer": "^9.2.23",
"openapi3-ts": "^4.3.2",

@@ -66,0 +66,0 @@ "yargs": "^17.7.2",

@@ -65,2 +65,6 @@ "use strict";

/**
* An Empty ArrayBuffer
* @since 9.7.0
*/ emptyArrayBuffer: new ArrayBuffer(0),
/**
* Cached ArrayBuffer Texts

@@ -67,0 +71,0 @@ * @since 9.0.0

@@ -11,2 +11,3 @@ "use strict";

const parseURL_1 = __importDefault(require("../../../functions/parseURL"));
const empty = Buffer.allocUnsafe(0);
class RequestContext {

@@ -85,3 +86,3 @@ constructor(context, middlewares, server, global) {

cookies: new ValueCollection_1.default(),
content: Buffer.allocUnsafe(0),
content: empty,
prettify: false

@@ -88,0 +89,0 @@ };

@@ -37,2 +37,36 @@ import { Status } from "../../types/global";

/**
* The Request Body as a Blob-like Object
* @example
* ```
* const size = await ctr.$body().size()
*
* return ctr.print(`The size of the body is ${size} bytes`)
* ```
* @since 9.7.0
*/ $body() {
const self = this;
return {
text() {
return self.rawBody('utf-8');
}, async json() {
const data = await self.body();
if (self.context.body.type === 'json')
return data;
throw new Error('Body is not JSON (make sure the content-type sent is application/json)');
}, arrayBuffer() {
return self.rawBodyBytes();
}, async formData() {
const data = await self.body();
if (self.context.body.type === 'url-encoded')
return data;
throw new Error('Body is not Form Data (make sure the content-type sent is application/x-www-form-urlencoded)');
}, async blob() {
return new Blob([await self.rawBodyBytes()]);
}, async size() {
const data = await self.rawBodyBytes();
return data.byteLength;
}
};
}
/**
* The Request Body (JSON and Urlencoding Automatically parsed if enabled)

@@ -39,0 +73,0 @@ * @since 0.4.0

@@ -7,2 +7,30 @@ import WsOpenContext from "./WsOpenContext";

/**
* The Request Message as a Blob-like Object
* @example
* ```
* const size = await ctr.$message().size()
*
* return ctr.print(`The size of the message is ${size} bytes`)
* ```
* @since 9.7.0
*/ $message() {
const self = this;
return {
text() {
return self.rawMessage('utf-8');
}, json() {
const data = self.message();
if (self.context.body.type === 'json')
return data;
throw new Error('Message is not valid JSON');
}, arrayBuffer() {
return self.rawMessageBytes();
}, blob() {
return new Blob([self.rawMessageBytes()]);
}, size() {
return self.rawMessageBytes().byteLength;
}
};
}
/**
* The Websocket Message (JSON Automatically parsed if enabled)

@@ -12,3 +40,4 @@ * @since 5.4.0

const stringified = this.context.body.raw.toString();
if ((stringified.startsWith('{') && stringified.endsWith('}')) || (stringified.startsWith('[') && stringified.endsWith(']'))) {
if ((stringified[0] === '{' && stringified[stringified.length - 1] === '}') ||
(stringified[0] === '[' && stringified[stringified.length - 1] === ']')) {
try {

@@ -15,0 +44,0 @@ const json = JSON.parse(stringified);

@@ -8,2 +8,4 @@ import Route from "../Route";

import deepClone from "../../functions/deepClone";
import os from "os";
const platform = os.platform();
export default class File {

@@ -137,3 +139,3 @@ computePath(path) {

try {
const { default: router } = await eval(`import(${JSON.stringify(file.path)})`), // bypass ttsc converting to require() in cjs
const importPath = platform === 'win32' ? `file:///${file.path}` : file.path, { default: router } = await eval(`import(${JSON.stringify(importPath)})`), // bypass ttsc converting to require() in cjs
path = file.path.replace(resolved, '').replaceAll('index', '').replace(/\\/g, '/').split('.').slice(0, -1).join('.').concat('/');

@@ -140,0 +142,0 @@ if (router instanceof Path) {

@@ -17,3 +17,3 @@ const replace = {

* <p>${userInput}</p>
* `
* ` // XSS Vulnerable
*

@@ -23,3 +23,3 @@ * const secure = html`

* <p>${userInput}</p>
* `
* ` // XSS Safe
* ```

@@ -26,0 +26,0 @@ * @since 8.7.0

@@ -1,2 +0,2 @@

const mapping = {
const mapping = Object.freeze({
pdf: 'application/pdf',

@@ -80,4 +80,6 @@ js: 'text/javascript',

vcf: 'text/vcard',
ics: 'text/calendar'
};
ics: 'text/calendar',
abw: 'application/x-abiword',
azw: 'application/vnd.amazon.ebook'
});
/**

@@ -91,7 +93,9 @@ * Parse File Name into a Content Type or empty string

}
const end = name.split('.').at(-1);
const dot = name.lastIndexOf('.');
if (dot === -1)
return 'application/octet-stream';
const end = name.slice(dot + 1);
if (!end)
return 'application/octet-stream';
const type = mapping[end];
return type ?? 'application/octet-stream';
return mapping[end] ?? 'application/octet-stream';
}
import ValueCollection from "../classes/ValueCollection";
import { as } from "@rjweb/utils";
export const trimString = (str) => {
export function trimString(str) {
let start = 0, end = str.length - 1;

@@ -12,3 +12,3 @@ while (start < end && str[start] === ' ') {

return str.substring(start, end + 1);
};
}
/**

@@ -15,0 +15,0 @@ * Efficiently parse Key-Value Strings into ValueCollections

@@ -43,3 +43,3 @@ import toETag from "./toETag";

if (context.headers.get('if-none-match') === eTag) {
await rawContext.status(Status.NOT_MODIFIED, 'Not Modified').write(new ArrayBuffer(0));
await rawContext.status(Status.NOT_MODIFIED, 'Not Modified').write(context.global.cache.emptyArrayBuffer);
return false;

@@ -57,3 +57,3 @@ }

.status(context.response.status, context.response.statusText || STATUS_CODES[context.response.status] || 'Unknown')
.write(new ArrayBuffer(0));
.write(context.global.cache.emptyArrayBuffer);
return false;

@@ -60,0 +60,0 @@ }

{
"name": "rjweb-server",
"version": "9.6.0",
"version": "9.7.0",
"description": "Easy and Robust Way to create a Web Server with Many Easy-to-use Features in NodeJS",

@@ -49,3 +49,3 @@ "main": "./lib/cjs/index.js",

"@types/inquirer": "^9.0.7",
"@types/node": "^20.12.12",
"@types/node": "^20.14.2",
"@types/yargs": "^17.0.32",

@@ -61,5 +61,5 @@ "rjweb-server": "link:",

"dependencies": {
"@rjweb/utils": "^1.12.15",
"@rjweb/utils": "^1.12.20",
"content-disposition": "^0.5.4",
"inquirer": "^9.2.22",
"inquirer": "^9.2.23",
"openapi3-ts": "^4.3.2",

@@ -66,0 +66,0 @@ "yargs": "^17.7.2",

@@ -60,2 +60,6 @@ import ValueCollection from "../../../classes/ValueCollection";

/**
* An Empty ArrayBuffer
* @since 9.7.0
*/ emptyArrayBuffer: new ArrayBuffer(0),
/**
* Cached ArrayBuffer Texts

@@ -62,0 +66,0 @@ * @since 9.0.0

@@ -6,2 +6,3 @@ import Middleware from "../../../classes/Middleware";

import parseURL from "../../../functions/parseURL";
const empty = Buffer.allocUnsafe(0);
export default class RequestContext {

@@ -80,3 +81,3 @@ constructor(context, middlewares, server, global) {

cookies: new ValueCollection(),
content: Buffer.allocUnsafe(0),
content: empty,
prettify: false

@@ -83,0 +84,0 @@ };

@@ -6,3 +6,3 @@ /// <reference types="node" />

import { HttpContext } from "../../types/implementation/contexts/http";
import { Content, ParsedBody, RatelimitInfos } from "../../types/global";
import { Content, JSONParsed, ParsedBody, RatelimitInfos } from "../../types/global";
import Base from "./Base";

@@ -81,3 +81,6 @@ import { ZodResponse } from "../../types/internal";

GATEWAY_TIMEOUT: 504;
HTTP_VERSION_NOT_SUPPORTED: 505;
/**
* HTTP Abort Controller (please use to decrease server load)
* @since 9.0.0
*/ HTTP_VERSION_NOT_SUPPORTED: 505;
VARIANT_ALSO_NEGOTIATES: 506;

@@ -95,2 +98,19 @@ INSUFFICIENT_STORAGE: 507;

/**
* The Request Body as a Blob-like Object
* @example
* ```
* const size = await ctr.$body().size()
*
* return ctr.print(`The size of the body is ${size} bytes`)
* ```
* @since 9.7.0
*/ $body(): {
text(): Promise<string>;
json(): Promise<JSONParsed>;
arrayBuffer(): Promise<Buffer>;
formData(): Promise<Record<string, string>>;
blob(): Promise<Blob>;
size(): Promise<number>;
};
/**
* The Request Body (JSON and Urlencoding Automatically parsed if enabled)

@@ -97,0 +117,0 @@ * @since 0.4.0

@@ -6,6 +6,22 @@ /// <reference types="node" />

import WsOpenContext from "./WsOpenContext";
import { ParsedBody, RatelimitInfos } from "../../types/global";
import { JSONParsed, ParsedBody, RatelimitInfos } from "../../types/global";
export default class WsMessageContext<Context extends Record<any, any> = {}> extends WsOpenContext<'message', Context> {
constructor(context: InternalRequestContext, rawContext: WsContext, abort: AbortSignal);
/**
* The Request Message as a Blob-like Object
* @example
* ```
* const size = await ctr.$message().size()
*
* return ctr.print(`The size of the message is ${size} bytes`)
* ```
* @since 9.7.0
*/ $message(): {
text(): string;
json(): JSONParsed;
arrayBuffer(): Buffer;
blob(): Blob;
size(): number;
};
/**
* The Websocket Message (JSON Automatically parsed if enabled)

@@ -12,0 +28,0 @@ * @since 5.4.0

@@ -11,3 +11,3 @@ export type HTMLContent = string | number | boolean | undefined;

* <p>${userInput}</p>
* `
* ` // XSS Vulnerable
*

@@ -17,5 +17,5 @@ * const secure = html`

* <p>${userInput}</p>
* `
* ` // XSS Safe
* ```
* @since 8.7.0
*/ export default function html(parts: TemplateStringsArray, ...variables: HTMLContent[]): string;
import ValueCollection from "../classes/ValueCollection";
export declare const trimString: (str: string) => string;
export declare function trimString(str: string): string;
/**

@@ -4,0 +4,0 @@ * Efficiently parse Key-Value Strings into ValueCollections

@@ -84,2 +84,6 @@ import Route from "../../../classes/Route";

/**
* An Empty ArrayBuffer
* @since 9.7.0
*/ emptyArrayBuffer: ArrayBuffer;
/**
* Cached ArrayBuffer Texts

@@ -86,0 +90,0 @@ * @since 9.0.0

{
"name": "rjweb-server",
"version": "9.6.0",
"version": "9.7.0",
"description": "Easy and Robust Way to create a Web Server with Many Easy-to-use Features in NodeJS",

@@ -41,3 +41,3 @@ "main": "./lib/cjs/index.js",

"@types/inquirer": "^9.0.7",
"@types/node": "^20.12.12",
"@types/node": "^20.14.2",
"@types/yargs": "^17.0.32",

@@ -53,5 +53,5 @@ "rjweb-server": "link:",

"dependencies": {
"@rjweb/utils": "^1.12.15",
"@rjweb/utils": "^1.12.20",
"content-disposition": "^0.5.4",
"inquirer": "^9.2.22",
"inquirer": "^9.2.23",
"openapi3-ts": "^4.3.2",

@@ -58,0 +58,0 @@ "yargs": "^17.7.2",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc