Socket
Socket
Sign inDemoInstall

@tinyhttp/send

Package Overview
Dependencies
Maintainers
1
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tinyhttp/send - npm Package Compare versions

Comparing version 2.0.5 to 2.0.6

vite.config.ts

307

dist/index.js

@@ -1,197 +0,144 @@

import { format, parse } from 'es-content-type';
import { eTag } from '@tinyhttp/etag';
import { Stats, statSync, createReadStream } from 'fs';
import { STATUS_CODES } from 'http';
import { isAbsolute, join, extname } from 'path';
import { contentType } from 'es-mime-types';
/**
* Respond with stringified JSON object
* @param res Response
*/
import { parse, format } from "es-content-type";
import { eTag } from "@tinyhttp/etag";
import { Stats, statSync, createReadStream } from "fs";
import { STATUS_CODES } from "http";
import { isAbsolute, join, extname } from "path";
import { contentType } from "es-mime-types";
const json = (res) => (body, ...args) => {
res.setHeader('Content-Type', 'application/json');
if (typeof body === 'object' && body != null)
res.end(JSON.stringify(body, null, 2), ...args);
else if (typeof body === 'string')
res.end(body, ...args);
else if (body == null) {
res.removeHeader('Content-Length');
res.removeHeader('Transfer-Encoding');
res.end(null, ...args);
}
return res;
res.setHeader("Content-Type", "application/json");
if (typeof body === "object" && body != null)
res.end(JSON.stringify(body, null, 2), ...args);
else if (typeof body === "string")
res.end(body, ...args);
else if (body == null) {
res.removeHeader("Content-Length");
res.removeHeader("Transfer-Encoding");
res.end(null, ...args);
}
return res;
};
const createETag = (body, encoding) => {
if (body instanceof Stats) {
return eTag(body, { weak: true });
}
else {
return eTag(!Buffer.isBuffer(body) ? Buffer.from(body, encoding) : body, { weak: true });
}
if (body instanceof Stats) {
return eTag(body, { weak: true });
} else {
return eTag(!Buffer.isBuffer(body) ? Buffer.from(body, encoding) : body, { weak: true });
}
};
function setCharset(type, charset) {
const parsed = parse(type);
parsed.parameters.charset = charset;
return format(parsed);
const parsed = parse(type);
parsed.parameters.charset = charset;
return format(parsed);
}
/**
* Sends the HTTP response.
*
* The body parameter can be a Buffer object, a string, an object, or an array.
*
* This method performs many useful tasks for simple non-streaming responses.
* For example, it automatically assigns the Content-Length HTTP response header field (unless previously defined) and provides automatic HEAD and HTTP cache freshness support.
*
* @param req Request
* @param res Response
*/
const send = (req, res) => (body) => {
let bodyToSend = body;
if (Buffer.isBuffer(body)) {
bodyToSend = body;
}
else if (typeof body === 'object' && body !== null) {
// in case of object - turn it to json
bodyToSend = JSON.stringify(body, null, 2);
}
else if (typeof body === 'string') {
// reflect this in content-type
const type = res.getHeader('Content-Type');
if (type && typeof type === 'string') {
res.setHeader('Content-Type', setCharset(type, 'utf-8'));
}
else
res.setHeader('Content-Type', setCharset('text/html', 'utf-8'));
}
// Set encoding
const encoding = 'utf8';
// populate ETag
let etag;
if (body && !res.getHeader('etag') && (etag = createETag(bodyToSend, encoding))) {
res.setHeader('etag', etag);
}
// freshness
if (req.fresh)
res.statusCode = 304;
// strip irrelevant headers
if (res.statusCode === 204 || res.statusCode === 304) {
res.removeHeader('Content-Type');
res.removeHeader('Content-Length');
res.removeHeader('Transfer-Encoding');
bodyToSend = '';
}
if (req.method === 'HEAD') {
res.end('');
return res;
}
if (typeof body === 'object') {
if (body == null) {
res.end('');
return res;
}
else if (Buffer.isBuffer(body)) {
if (!res.getHeader('Content-Type'))
res.setHeader('content-type', 'application/octet-stream');
res.end(bodyToSend);
}
else
json(res)(bodyToSend, encoding) ;
}
else {
if (typeof bodyToSend !== 'string')
bodyToSend = bodyToSend.toString();
res.end(bodyToSend, encoding) ;
}
let bodyToSend = body;
if (Buffer.isBuffer(body)) {
bodyToSend = body;
} else if (typeof body === "object" && body !== null) {
bodyToSend = JSON.stringify(body, null, 2);
} else if (typeof body === "string") {
const type = res.getHeader("Content-Type");
if (type && typeof type === "string") {
res.setHeader("Content-Type", setCharset(type, "utf-8"));
} else
res.setHeader("Content-Type", setCharset("text/html", "utf-8"));
}
const encoding = "utf8";
let etag;
if (body && !res.getHeader("etag") && (etag = createETag(bodyToSend, encoding))) {
res.setHeader("etag", etag);
}
if (req.fresh)
res.statusCode = 304;
if (res.statusCode === 204 || res.statusCode === 304) {
res.removeHeader("Content-Type");
res.removeHeader("Content-Length");
res.removeHeader("Transfer-Encoding");
bodyToSend = "";
}
if (req.method === "HEAD") {
res.end("");
return res;
}
if (typeof body === "object") {
if (body == null) {
res.end("");
return res;
} else if (Buffer.isBuffer(body)) {
if (!res.getHeader("Content-Type"))
res.setHeader("content-type", "application/octet-stream");
res.end(bodyToSend);
} else
json(res)(bodyToSend, encoding);
} else {
if (typeof bodyToSend !== "string")
bodyToSend = bodyToSend.toString();
res.end(bodyToSend, encoding);
}
return res;
};
/**
* Sets the response HTTP status code to statusCode and send its string representation as the response body.
*
* If an unsupported status code is specified, the HTTP status is still set to statusCode and the string version of the code is sent as the response body.
*
* @param req Request
* @param res Response
*/
const sendStatus = (req, res) => (statusCode) => {
const body = STATUS_CODES[statusCode] || String(statusCode);
res.statusCode = statusCode;
res.setHeader('Content-Type', 'text/plain');
return send(req, res)(body);
const body = STATUS_CODES[statusCode] || String(statusCode);
res.statusCode = statusCode;
res.setHeader("Content-Type", "text/plain");
return send(req, res)(body);
};
/**
* Sets the HTTP status for the response. It is a chainable alias of Node’s `response.statusCode`.
*
* @param res Response
*/
const status = (res) => (status) => {
res.statusCode = status;
return res;
const status = (res) => (status2) => {
res.statusCode = status2;
return res;
};
const enableCaching = (res, caching) => {
let cc = caching.maxAge != null && `public,max-age=${caching.maxAge}`;
if (cc && caching.immutable)
cc += ',immutable';
else if (cc && caching.maxAge === 0)
cc += ',must-revalidate';
if (cc)
res.setHeader('Cache-Control', cc);
let cc = caching.maxAge != null && `public,max-age=${caching.maxAge}`;
if (cc && caching.immutable)
cc += ",immutable";
else if (cc && caching.maxAge === 0)
cc += ",must-revalidate";
if (cc)
res.setHeader("Cache-Control", cc);
};
/**
* Sends a file by piping a stream to response.
*
* It also checks for extension to set a proper `Content-Type` header.
*
* Path argument must be absolute. To use a relative path, specify the `root` option first.
*
* @param res Response
*/
const sendFile = (req, res) => (path, opts = {}, cb) => {
const { root, headers = {}, encoding = 'utf-8', caching, ...options } = opts;
if (!isAbsolute(path) && !root)
throw new TypeError('path must be absolute');
if (caching)
enableCaching(res, caching);
const filePath = root ? join(root, path) : path;
const stats = statSync(filePath);
headers['Content-Encoding'] = encoding;
headers['Last-Modified'] = stats.mtime.toUTCString();
headers['Content-Type'] = contentType(extname(path));
headers['ETag'] = createETag(stats, encoding);
let status = res.statusCode || 200;
if (req.headers['range']) {
status = 206;
const [x, y] = req.headers.range.replace('bytes=', '').split('-');
const end = (options.end = parseInt(y, 10) || stats.size - 1);
const start = (options.start = parseInt(x, 10) || 0);
if (start >= stats.size || end >= stats.size) {
res
.writeHead(416, {
'Content-Range': `bytes */${stats.size}`
})
.end();
return res;
}
headers['Content-Range'] = `bytes ${start}-${end}/${stats.size}`;
headers['Content-Length'] = end - start + 1;
headers['Accept-Ranges'] = 'bytes';
const { root, headers = {}, encoding = "utf-8", caching, ...options } = opts;
if (!isAbsolute(path) && !root)
throw new TypeError("path must be absolute");
if (caching)
enableCaching(res, caching);
const filePath = root ? join(root, path) : path;
const stats = statSync(filePath);
headers["Content-Encoding"] = encoding;
headers["Last-Modified"] = stats.mtime.toUTCString();
headers["Content-Type"] = contentType(extname(path));
headers["ETag"] = createETag(stats, encoding);
let status2 = res.statusCode || 200;
if (req.headers["range"]) {
status2 = 206;
const [x, y] = req.headers.range.replace("bytes=", "").split("-");
const end = options.end = parseInt(y, 10) || stats.size - 1;
const start = options.start = parseInt(x, 10) || 0;
if (start >= stats.size || end >= stats.size) {
res.writeHead(416, {
"Content-Range": `bytes */${stats.size}`
}).end();
return res;
}
else {
headers['Content-Length'] = stats.size;
}
for (const [k, v] of Object.entries(headers))
res.setHeader(k, v);
res.writeHead(status, headers);
const stream = createReadStream(filePath, options);
if (cb)
stream.on('error', (err) => cb(err)).on('end', () => cb());
stream.pipe(res);
return res;
headers["Content-Range"] = `bytes ${start}-${end}/${stats.size}`;
headers["Content-Length"] = end - start + 1;
headers["Accept-Ranges"] = "bytes";
} else {
headers["Content-Length"] = stats.size;
}
for (const [k, v] of Object.entries(headers))
res.setHeader(k, v);
res.writeHead(status2, headers);
const stream = createReadStream(filePath, options);
if (cb)
stream.on("error", (err) => cb(err)).on("end", () => cb());
stream.pipe(res);
return res;
};
export { enableCaching, json, send, sendFile, sendStatus, status };
export {
enableCaching,
json,
send,
sendFile,
sendStatus,
status
};
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import { IncomingMessage as I, ServerResponse as S } from 'http';

@@ -3,0 +5,0 @@ export declare type ReadStreamOptions = Partial<{

{
"name": "@tinyhttp/send",
"version": "2.0.5",
"version": "2.0.6",
"type": "module",

@@ -30,3 +30,3 @@ "description": "json, send, sendFile, status and sendStatus methods for tinyhttp",

"dependencies": {
"@tinyhttp/etag": "2.0.4",
"@tinyhttp/etag": "2.0.5",
"es-content-type": "^0.1.0",

@@ -36,4 +36,6 @@ "es-mime-types": "^0.1.4"

"scripts": {
"build": "rollup -c"
"dev": "vite",
"build": "vite build",
"postbuild": "tsc --emitDeclarationOnly"
}
}
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc