Socket
Socket
Sign inDemoInstall

@tinyhttp/app

Package Overview
Dependencies
Maintainers
1
Versions
305
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tinyhttp/app - npm Package Compare versions

Comparing version 0.1.47 to 0.1.48

53

dist/index.d.ts

@@ -84,2 +84,21 @@ /// <reference types="node" />

// }
/* export const getFreshOrStale = (req: Request, res: Response) => {
const method = req.method
const status = res.statusCode
// GET or HEAD for weak freshness validation only
if (method !== 'GET' && method !== 'HEAD') return false
// 2xx or 304 as per rfc2616 14.26
if ((status >= 200 && status < 300) || 304 === status) {
const resHeaders = {
etag: res.get('ETag'),
'last-modified': res.get('Last-Modified'),
}
return fresh(req.headers, resHeaders)
}
return false
} */
// export const getRequestIs = (types: string | string[], ...args: string[]) => (req: Request) => {

@@ -94,3 +113,21 @@ // let arr = types

// }
declare const getFreshOrStale: (req: Request, res: Response) => boolean;
/* export const getFreshOrStale = (req: Request, res: Response) => {
const method = req.method
const status = res.statusCode
// GET or HEAD for weak freshness validation only
if (method !== 'GET' && method !== 'HEAD') return false
// 2xx or 304 as per rfc2616 14.26
if ((status >= 200 && status < 300) || 304 === status) {
const resHeaders = {
etag: res.get('ETag'),
'last-modified': res.get('Last-Modified'),
}
return fresh(req.headers, resHeaders)
}
return false
} */
declare const getAccepts: (req: Request) => (...types: string[]) => string | false | string[];

@@ -117,7 +154,11 @@ type Connection = IncomingMessage["socket"] & {

secret?: string | string[];
fresh: boolean;
stale: boolean;
/* fresh: boolean
stale: boolean
*/
body?: any;
}
declare const applyHandler: (h: Handler) => Handler;
type AppSettings = Partial<{
networkExtensions: boolean;
}>;
declare class App extends Router {

@@ -128,5 +169,7 @@ middleware: Middleware[];

onError: ErrorHandler;
settings: AppSettings;
constructor(options?: Partial<{
noMatchHandler: Handler;
onError: ErrorHandler;
settings: AppSettings;
}>);

@@ -136,3 +179,3 @@ handler(mw: Middleware[], req: Request, res: Response): Promise<void>;

}
declare const extendMiddleware: () => (req: Request, res: Response) => void;
export { applyHandler, App, getQueryParams, URLParams, getURLParams, getRouteFromApp, getProtocol, getRequestHeader, setRequestHeader, getRangeFromHeader, checkIfXMLHttpRequest, getHostname, getIP, getFreshOrStale, getAccepts, Connection, Protocol, Request, json, send, status, setCookie, clearCookie, setHeader, setLocationHeader, getResponseHeader, setLinksHeader, sendStatus, Response, NextFunction, SyncHandler, AsyncHandler, Handler, ErrorHandler, Middleware, Router, extendMiddleware };
declare const extendMiddleware: ({ networkExtensions }: AppSettings) => (req: Request, res: Response) => void;
export { applyHandler, AppSettings, App, getQueryParams, URLParams, getURLParams, getRouteFromApp, getProtocol, getRequestHeader, setRequestHeader, getRangeFromHeader, checkIfXMLHttpRequest, getHostname, getIP, getAccepts, Connection, Protocol, Request, json, send, status, setCookie, clearCookie, setHeader, setLocationHeader, getResponseHeader, setLinksHeader, sendStatus, Response, NextFunction, SyncHandler, AsyncHandler, Handler, ErrorHandler, Middleware, Router, extendMiddleware };

@@ -1,1 +0,534 @@

import{STATUS_CODES as e,METHODS as t,createServer as r}from"http";import n from"regexparam";import{parse as s}from"url";import o from"range-parser";import a from"proxy-addr";import i from"@foxify/fresh";import d from"es-accepts";import{sign as h}from"@tinyhttp/cookie-signature";import{lookup as l}from"es-mime-types";import{serialize as p}from"@tinyhttp/cookie";import{format as c,parse as u}from"es-content-type";import f from"@tinyhttp/etag";const m=e=>"function"==typeof e?e:!0===e?function(){return!0}:"number"==typeof e?(t,r)=>{if(e)return r<e}:("string"==typeof e&&(e=e.split(/ *, */)),a.compile(e||[])),y=(e="/")=>s(e,!0).query,g=(e="/",t="/")=>((e,t)=>{let r=0,n={},s=t.pattern.exec(e);for(;r<t.keys.length;)n[t.keys[r]]=(null==s?void 0:s[++r])||null;return n})(e,n(t)),w=(e,t)=>e.middleware.find(e=>e.handler.name===t.name),H=e=>{const t=e.connection.encrypted?"https":"http";if(!m(e.connection.remoteAddress))return t;const r=e.headers["X-Forwarded-Proto"]||t,n=r.indexOf(",");return-1!==n?r.substring(0,n).trim():r.trim()},C=e=>t=>{const r=t.toLowerCase();switch(r){case"referer":case"referrer":return e.headers.referrer||e.headers.referer;default:return e.headers[r]}},T=e=>(t,r)=>e.headers[t.toLowerCase()]=r,x=e=>(t,r)=>{const n=e.get("Range");if(n)return o(t,n,r)},E=e=>"XMLHttpRequest"===e.headers["X-Requested-With"],b=e=>{let t=e.get("X-Forwarded-Host");if(t&&m(e.connection.remoteAddress)||(t=e.get("Host")),!t)return;const r="["===t[0]?t.indexOf("]")+1:0,n=t.indexOf(":",r);return-1!==n?t.substring(0,n):t},k=e=>a(e,m),A=(e,t)=>{const r=e.method,n=t.statusCode;if("GET"!==r&&"HEAD"!==r)return!1;if(n>=200&&n<300||304===n){const r={etag:t.get("ETag"),"last-modified":t.get("Last-Modified")};return i(e.headers,r)}return!1},O=e=>(...t)=>new d(e).types(t),S=(t,r,n)=>{const s=n.statusCode=t.code||t.status||500;"string"==typeof t||Buffer.isBuffer(t)?n.end(t):n.end(t.message||e[s])},j=e=>({path:t,handler:r,method:n,handlers:s,type:o})=>{const a=(({path:e,handler:t,method:r})=>({method:r,handler:t||e,path:"string"==typeof e?e:"/"}))({path:t,handler:r,method:n,type:o}),i=s.map(e=>({handler:e}));for(const t of[a,...i])e.push({...t,type:o})};class L{get(e,t,...r){return j(this.middleware)({path:e,handler:t,handlers:r,method:"GET",type:"route"}),this}post(e,t,...r){return j(this.middleware)({path:e,handler:t,handlers:r,method:"POST",type:"route"}),this}put(e,t,...r){return j(this.middleware)({path:e,handler:t,handlers:r,method:"PUT",type:"route"}),this}patch(e,t,...r){return j(this.middleware)({path:e,handler:t,handlers:r,method:"PATCH",type:"route"}),this}head(e,t,...r){return j(this.middleware)({path:e,handler:t,handlers:r,method:"HEAD",type:"route"}),this}delete(e,t,...r){return j(this.middleware)({path:e,handler:t,handlers:r,method:"DELETE",type:"route"}),this}options(e,t,...r){return j(this.middleware)({path:e,handler:t,handlers:r,method:"OPTIONS",type:"route"}),this}all(e,r,...n){for(const s of t)j(this.middleware)({path:e,handler:r,method:s,handlers:n,type:"route"});return this}use(e,t,...r){return j(this.middleware)({path:e,handler:"string"==typeof e?t:e,handlers:r,type:"mw"}),this}}const B=(e,t)=>{const r=Buffer.isBuffer(e)?e:Buffer.from(e,t);return f(r,{weak:!0})};const D=(e,t)=>(e,...r)=>(t.setHeader("Content-Type","application/json"),"object"==typeof e&&null!=e?t.end(JSON.stringify(e,null,2),...r):"string"==typeof e&&t.end(e,...r),t),v=(e,t)=>r=>{let n=r;if("object"==typeof r&&null!==r)n=JSON.stringify(r,null,2);else if("string"==typeof r){const e=t.getHeader("Content-Type");"string"==typeof e&&t.setHeader("Content-Type",function(e,t){const r=u(e);return r.parameters.charset=t,c(r)}(e,"utf-8"))}let s;return!t.getHeader("etag")&&(s=B(n,"utf8"))&&t.setHeader("etag",s),204!==t.statusCode&&304!==t.statusCode||(t.removeHeader("Content-Type"),t.removeHeader("Content-Length"),t.removeHeader("Transfer-Encoding"),n=""),"HEAD"===e.method&&t.end(""),"object"==typeof r?null===r?t.end(""):Buffer.isBuffer(r)?t.getHeader("Content-Type")||t.setHeader("content-type","application/octet-stream"):D(0,t)(n,"utf8"):t.end(n,"utf8"),t},P=(e,t)=>e=>(t.statusCode=e,t),q=(e,t)=>(r,n,s)=>{const o=e.secret,a=s.signed;if(a&&!o)throw new Error('cookieParser("secret") required for signed cookies');let i="object"==typeof n?"j:"+JSON.stringify(n):String(n);return a&&(i="s:"+h(i,o)),s.maxAge&&(s.expires=new Date(Date.now()+s.maxAge),s.maxAge/=1e3),null==s.path&&(s.path="/"),t.setHeader("Set-Cookie",p(r,String(i),s)),t},M=(e,t)=>(r,n)=>{const s=Object.assign({},{expires:new Date(1),path:"/"},n);return q(e,t)(r,"",s)},R=/;\s*charset\s*=/,N=(e,t)=>(e,r)=>{if("string"==typeof e){let n=Array.isArray(r)?r.map(String):String(r);if("content-type"===e.toLowerCase()){if(Array.isArray(n))throw new TypeError("Content-Type cannot be set to an Array");if(!R.test(n)){const e=l(n.split(";")[0]);e&&(n+="; charset="+e.toLowerCase())}}t.setHeader(e,n)}else for(const r in e)t.setHeader(r,e[r]);return t},X=(e,t)=>r=>{let n=r;return"back"===r&&(n=e.get("Referrer")||"/"),t.setHeader("Location",encodeURIComponent(n)),t},F=(e,t)=>e=>t.getHeader(e),J=(e,t)=>e=>{let r=t.get("Link")||"";return r&&(r+=", "),t.set("Link",r+Object.keys(e).map(t=>"<"+e[t]+'>; rel="'+t+'"').join(", "))},G=(t,r)=>t=>{const n=e[t]||String(t);return r.statusCode=t,r.set("Content-Type","text/plain"),r.send(n)},I=()=>(e,t)=>{t.get=F(0,t);const r=H(e),n="https"===r;e.protocol=r,e.secure=n,e.connection=Object.assign(e.socket,{encrypted:n}),e.query=y(e.url),e.fresh=A(e,t),e.stale=!e.fresh,e.get=C(e),e.set=T(e),e.range=x(e),e.accepts=O(e),e.xhr=E(e),e.hostname=b(e),t.header=t.set=N(0,t),t.send=v(e,t),t.json=D(0,t),t.status=P(0,t),t.sendStatus=G(0,t),t.location=X(e,t),t.links=J(0,t),t.cookie=q(e,t),t.clearCookie=M(e,t)},U=e=>async(t,r,n)=>{"AsyncFunction"===e[Symbol.toStringTag]?await e(t,r,n):e(t,r,n)};class W extends L{constructor(e={}){super(),this.locals=Object.create(null),this.middleware=[],this.onError=(null==e?void 0:e.onError)||S,this.noMatchHandler=(null==e?void 0:e.noMatchHandler)||this.onError.bind(null,{code:404})}async handler(e,t,r){I()(t,r);const s={handler:this.noMatchHandler,type:"mw",path:"/"};e.includes(s)||e.push(s);let o=0;const a=e.length-1,i=e=>{e?this.onError(e,t,r):h()},d=e=>async(t,r,s)=>{const{path:o,method:a,handler:i,type:d}=e;if("route"===d){if(t.method===a){const e=t.url.indexOf("?"),a=t.url.slice(0,-1===e?t.url.length:e);n(o).pattern.test(a)?(t.params=g(t.url,o),t.route=w(this,i),r.statusCode=200,U(i)(t,r,s)):h()}}else t.url.startsWith(o)?U(i)(t,r,s):h()};1===e.length&&d(e[0])(t,r);const h=()=>{r.writableEnded||o<a&&d(e[o++])(t,r,i)};h()}listen(e,t,n="localhost",s){return r((e,t)=>{this.handler(this.middleware,e,t)}).listen(e,n,s,t)}}export{W as App,L as Router,U as applyHandler,E as checkIfXMLHttpRequest,M as clearCookie,I as extendMiddleware,O as getAccepts,A as getFreshOrStale,b as getHostname,k as getIP,H as getProtocol,y as getQueryParams,x as getRangeFromHeader,C as getRequestHeader,F as getResponseHeader,w as getRouteFromApp,g as getURLParams,D as json,v as send,G as sendStatus,q as setCookie,N as setHeader,J as setLinksHeader,X as setLocationHeader,T as setRequestHeader,P as status};
import { STATUS_CODES, METHODS, createServer } from 'http';
import rg from 'regexparam';
import { parse } from 'url';
import parseRange from 'range-parser';
import proxyAddr from 'proxy-addr';
import Accepts from 'es-accepts';
import { sign } from '@tinyhttp/cookie-signature';
import { lookup } from 'es-mime-types';
import { serialize } from '@tinyhttp/cookie';
import { format, parse as parse$1 } from 'es-content-type';
import etag from '@tinyhttp/etag';
const compileTrust = (val) => {
if (typeof val === 'function')
return val;
if (val === true) {
// Support plain true/false
return function () {
return true;
};
}
if (typeof val === 'number') {
// Support trusting hop count
return (_, i) => {
if (val) {
return i < val;
}
};
}
if (typeof val === 'string') {
// Support comma-separated values
val = val.split(/ *, */);
}
return proxyAddr.compile(val || []);
};
const rgExec = (path, result) => {
let i = 0, out = {};
let matches = result.pattern.exec(path);
while (i < result.keys.length) {
out[result.keys[i]] = (matches === null || matches === void 0 ? void 0 : matches[++i]) || null;
}
return out;
};
const getQueryParams = (url = '/') => {
return parse(url, true).query;
};
const getURLParams = (reqUrl = '/', url = '/') => {
return rgExec(reqUrl, rg(url));
};
const getRouteFromApp = (app, handler) => {
return app.middleware.find((h) => h.handler.name === handler.name);
};
const getProtocol = (req) => {
const proto = req.connection.encrypted ? 'https' : 'http';
if (!compileTrust(req.connection.remoteAddress)) {
return proto;
}
const header = req.headers['X-Forwarded-Proto'] || proto;
const index = header.indexOf(',');
return index !== -1 ? header.substring(0, index).trim() : header.trim();
};
const getRequestHeader = (req) => (header) => {
const lc = header.toLowerCase();
switch (lc) {
case 'referer':
case 'referrer':
return req.headers.referrer || req.headers.referer;
default:
return req.headers[lc];
}
};
const setRequestHeader = (req) => (field, value) => {
return (req.headers[field.toLowerCase()] = value);
};
const getRangeFromHeader = (req) => (size, options) => {
const range = req.get('Range');
if (!range)
return;
return parseRange(size, range, options);
};
const checkIfXMLHttpRequest = (req) => {
if (req.headers['X-Requested-With'] === 'XMLHttpRequest') {
return true;
}
else {
return false;
}
};
const getHostname = (req) => {
let host = req.get('X-Forwarded-Host');
if (!host || !compileTrust(req.connection.remoteAddress)) {
host = req.get('Host');
}
if (!host)
return;
// IPv6 literal support
const offset = host[0] === '[' ? host.indexOf(']') + 1 : 0;
const index = host.indexOf(':', offset);
return index !== -1 ? host.substring(0, index) : host;
};
const getIP = (req) => {
return proxyAddr(req, compileTrust);
};
// export const getRequestIs = (types: string | string[], ...args: string[]) => (req: Request) => {
// let arr = types
// if (!Array.isArray(types)) {
// arr = new Array(args.length)
// for (let i = 0; i < arr.length; i++) {
// arr[i] = args[i]
// }
// }
// }
/* export const getFreshOrStale = (req: Request, res: Response) => {
const method = req.method
const status = res.statusCode
// GET or HEAD for weak freshness validation only
if (method !== 'GET' && method !== 'HEAD') return false
// 2xx or 304 as per rfc2616 14.26
if ((status >= 200 && status < 300) || 304 === status) {
const resHeaders = {
etag: res.get('ETag'),
'last-modified': res.get('Last-Modified'),
}
return fresh(req.headers, resHeaders)
}
return false
} */
const getAccepts = (req) => (...types) => {
return new Accepts(req).types(types);
};
const onErrorHandler = (err, _req, res) => {
const code = (res.statusCode = err.code || err.status || 500);
if (typeof err === 'string' || Buffer.isBuffer(err))
res.end(err);
else
res.end(err.message || STATUS_CODES[code]);
};
const isAsync = (fn) => fn[Symbol.toStringTag] === 'AsyncFunction';
const createMiddlewareFromRoute = ({ path, handler, method, }) => ({
method,
handler: handler || path,
path: typeof path === 'string' ? path : '/',
});
const pushMiddleware = (mw) => ({ path, handler, method, handlers, type, }) => {
const m = createMiddlewareFromRoute({ path, handler, method, type });
const waresFromHandlers = handlers.map((handler) => ({
handler,
}));
for (const mdw of [m, ...waresFromHandlers]) {
mw.push({ ...mdw, type });
}
};
class Router {
get(path, handler, ...handlers) {
pushMiddleware(this.middleware)({
path,
handler,
handlers,
method: 'GET',
type: 'route',
});
return this;
}
post(path, handler, ...handlers) {
pushMiddleware(this.middleware)({
path,
handler,
handlers,
method: 'POST',
type: 'route',
});
return this;
}
put(path, handler, ...handlers) {
pushMiddleware(this.middleware)({
path,
handler,
handlers,
method: 'PUT',
type: 'route',
});
return this;
}
patch(path, handler, ...handlers) {
pushMiddleware(this.middleware)({
path,
handler,
handlers,
method: 'PATCH',
type: 'route',
});
return this;
}
head(path, handler, ...handlers) {
pushMiddleware(this.middleware)({
path,
handler,
handlers,
method: 'HEAD',
type: 'route',
});
return this;
}
delete(path, handler, ...handlers) {
pushMiddleware(this.middleware)({
path,
handler,
handlers,
method: 'DELETE',
type: 'route',
});
return this;
}
options(path, handler, ...handlers) {
pushMiddleware(this.middleware)({
path,
handler,
handlers,
method: 'OPTIONS',
type: 'route',
});
return this;
}
all(path, handler, ...handlers) {
for (const method of METHODS) {
pushMiddleware(this.middleware)({
path,
handler,
method,
handlers,
type: 'route',
});
}
return this;
}
use(path, handler, ...handlers) {
pushMiddleware(this.middleware)({
path,
handler: typeof path === 'string' ? handler : path,
handlers,
type: 'mw',
});
return this;
}
}
const createETag = (body, encoding) => {
const buf = !Buffer.isBuffer(body) ? Buffer.from(body, encoding) : body;
return etag(buf, { weak: true });
};
function setCharset(type, charset) {
const parsed = parse$1(type);
parsed.parameters.charset = charset;
return format(parsed);
}
const json = (_req, 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);
}
return res;
};
const send = (req, res) => (body) => {
let bodyToSend = body;
// in case of object - turn it to json
if (typeof body === 'object' && body !== null) {
bodyToSend = JSON.stringify(body, null, 2);
}
else {
if (typeof body === 'string') {
// reflect this in content-type
const type = res.getHeader('Content-Type');
if (typeof type === 'string') {
res.setHeader('Content-Type', setCharset(type, 'utf-8'));
}
}
}
// Set encoding
const encoding = 'utf8';
// populate ETag
let etag;
if (!res.getHeader('etag') && (etag = createETag(bodyToSend, encoding))) {
res.setHeader('etag', etag);
}
// 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('');
}
if (typeof body === 'object') {
if (body === null) {
res.end('');
}
else if (Buffer.isBuffer(body)) {
if (!res.getHeader('Content-Type')) {
res.setHeader('content-type', 'application/octet-stream');
}
}
else {
json(req, res)(bodyToSend, encoding)
;
}
}
else {
{
// respond with encoding
res.end(bodyToSend, encoding);
}
}
return res;
};
const status = (_req, res) => (status) => {
res.statusCode = status;
return res;
};
const setCookie = (req, res) => (name, value, options) => {
const secret = req.secret;
const signed = options.signed;
if (signed && !secret) {
throw new Error('cookieParser("secret") required for signed cookies');
}
let val = typeof value === 'object' ? 'j:' + JSON.stringify(value) : String(value);
if (signed) {
val = 's:' + sign(val, secret);
}
if (options.maxAge) {
options.expires = new Date(Date.now() + options.maxAge);
options.maxAge /= 1000;
}
if (options.path == null) {
options.path = '/';
}
res.setHeader('Set-Cookie', serialize(name, String(val), options));
return res;
};
const clearCookie = (req, res) => (name, options) => {
const opts = Object.assign({}, { expires: new Date(1), path: '/' }, options);
return setCookie(req, res)(name, '', opts);
};
const charsetRegExp = /;\s*charset\s*=/;
const setHeader = (_req, res) => (field, val) => {
if (typeof field === 'string') {
let value = Array.isArray(val) ? val.map(String) : String(val);
// add charset to content-type
if (field.toLowerCase() === 'content-type') {
if (Array.isArray(value)) {
throw new TypeError('Content-Type cannot be set to an Array');
}
if (!charsetRegExp.test(value)) {
const charset = lookup(value.split(';')[0]);
if (charset)
value += '; charset=' + charset.toLowerCase();
}
}
res.setHeader(field, value);
}
else {
for (const key in field) {
res.setHeader(key, field[key]);
}
}
return res;
};
const setLocationHeader = (req, res) => (url) => {
let loc = url;
// "back" is an alias for the referrer
if (url === 'back') {
loc = req.get('Referrer') || '/';
}
// set location
res.setHeader('Location', encodeURIComponent(loc));
return res;
};
const getResponseHeader = (_req, res) => (field) => {
return res.getHeader(field);
};
const setLinksHeader = (_req, res) => (links) => {
let link = res.get('Link') || '';
if (link)
link += ', ';
return res.set('Link', link +
Object.keys(links)
.map((rel) => '<' + links[rel] + '>; rel="' + rel + '"')
.join(', '));
};
const sendStatus = (_req, res) => (statusCode) => {
const body = STATUS_CODES[statusCode] || String(statusCode);
res.statusCode = statusCode;
res.set('Content-Type', 'text/plain');
return res.send(body);
};
const extendMiddleware = ({ networkExtensions }) => (req, res) => {
/// Define extensions
res.get = getResponseHeader(req, res);
/*
Request extensions
*/
if (networkExtensions) {
const proto = getProtocol(req);
const secure = proto === 'https';
req.protocol = proto;
req.secure = secure;
req.connection = Object.assign(req.socket, {
encrypted: secure,
});
}
req.query = getQueryParams(req.url);
/* req.fresh = getFreshOrStale(req, res)
req.stale = !req.fresh */
req.get = getRequestHeader(req);
req.set = setRequestHeader(req);
req.range = getRangeFromHeader(req);
req.accepts = getAccepts(req);
req.xhr = checkIfXMLHttpRequest(req);
req.hostname = getHostname(req);
/*
Response extensions
*/
res.header = res.set = setHeader(req, res);
res.send = send(req, res);
res.json = json(req, res);
res.status = status(req, res);
res.sendStatus = sendStatus(req, res);
res.location = setLocationHeader(req, res);
res.links = setLinksHeader(req, res);
res.cookie = setCookie(req, res);
res.clearCookie = clearCookie(req, res);
};
const applyHandler = (h) => async (req, res, next) => {
if (isAsync(h)) {
await h(req, res, next);
}
else {
h(req, res, next);
}
};
class App extends Router {
constructor(options = {}) {
super();
this.locals = Object.create(null);
this.middleware = [];
this.onError = (options === null || options === void 0 ? void 0 : options.onError) || onErrorHandler;
this.noMatchHandler =
(options === null || options === void 0 ? void 0 : options.noMatchHandler) || this.onError.bind(null, { code: 404 });
this.settings = options.settings || {};
}
async handler(mw, req, res) {
extendMiddleware(this.settings)(req, res);
const noMatchMW = {
handler: this.noMatchHandler,
type: 'mw',
path: '/',
};
if (!mw.includes(noMatchMW))
mw.push(noMatchMW);
let idx = 0;
const len = mw.length - 1;
// skip handling if only one middleware
// TODO: Implement next(err) function properly
const next = (err) => {
if (err) {
this.onError(err, req, res);
}
else {
loop();
}
};
const handle = (mw) => async (req, res, next) => {
const { path, method, handler, type } = mw;
if (type === 'route') {
if (req.method === method) {
const queryParamStart = req.url.indexOf('?');
const reqUrlWithoutParams = req.url.slice(0, queryParamStart === -1 ? req.url.length : queryParamStart);
if (rg(path).pattern.test(reqUrlWithoutParams)) {
req.params = getURLParams(req.url, path);
req.route = getRouteFromApp(this, handler);
// route found, send Success 200
res.statusCode = 200;
applyHandler(handler)(req, res, next);
}
else {
loop();
}
}
}
else {
if (req.url.startsWith(path)) {
applyHandler(handler)(req, res, next);
}
else {
loop();
}
}
};
if (mw.length === 1)
handle(mw[0])(req, res);
const loop = () => {
if (!res.writableEnded) {
if (idx < len) {
handle(mw[idx++])(req, res, next);
}
}
};
loop();
}
listen(port, cb, host = 'localhost', backlog) {
const server = createServer((req, res) => {
this.handler(this.middleware, req, res);
});
return server.listen(port, host, backlog, cb);
}
}
export { App, Router, applyHandler, checkIfXMLHttpRequest, clearCookie, extendMiddleware, getAccepts, getHostname, getIP, getProtocol, getQueryParams, getRangeFromHeader, getRequestHeader, getResponseHeader, getRouteFromApp, getURLParams, json, send, sendStatus, setCookie, setHeader, setLinksHeader, setLocationHeader, setRequestHeader, status };

3

package.json
{
"name": "@tinyhttp/app",
"version": "0.1.47",
"version": "0.1.48",
"description": "tinyhttp core",

@@ -39,3 +39,2 @@ "type": "module",

"dependencies": {
"@foxify/fresh": "^1.1.0",
"@tinyhttp/cookie": "0.0.13",

@@ -42,0 +41,0 @@ "@tinyhttp/cookie-signature": "0.0.10",

Sorry, the diff of this file is not supported yet

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