Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@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.20 to 0.1.21

LICENSE

33

dist/index.d.ts

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

import { Ranges, Options } from "range-parser";
import { SerializeOptions } from "@tinyhttp/cookie";
declare const getQueryParams: (url?: string) => ParsedUrlQuery;

@@ -13,3 +14,2 @@ type URLParams = {

declare const getRouteFromApp: (app: App, handler: Handler) => Middleware;
declare const compileTrust: (val: any) => any;
declare const getProtocol: (req: Request) => Protocol;

@@ -26,2 +26,3 @@ declare const getHeader: (req: Request) => (header: string) => string | string[];

interface Request extends IncomingMessage {
app: App;
query: ParsedUrlQuery;

@@ -37,14 +38,32 @@ params: URLParams;

range: (size: number, options?: any) => -1 | -2 | Ranges | undefined;
cookies?: any;
signedCookies?: any;
secret?: string | string[];
}
declare const json: (_: Request, res: Response) => (body: any, ...args: any[]) => Response;
declare const json: (_req: Request, res: Response) => (body: any, ...args: any[]) => Response;
declare const send: (req: Request, res: Response) => (body: any) => Response;
declare const status: (_: Request, res: Response) => (status: number) => Response;
declare const status: (_req: Request, res: Response) => (status: number) => Response;
declare const setCookie: (req: Request, res: Response) => (name: string, value: string | object, options?: SerializeOptions & Partial<{
signed: boolean;
}>) => Response;
declare const clearCookie: (req: Request, res: Response) => (name: string, options?: SerializeOptions) => Response;
declare const setHeader: (_req: Request, res: Response) => (field: string | object, val: string | any[]) => Response;
declare const setLocationHeader: (req: Request, res: Response) => (url: string) => void;
interface Response extends ServerResponse {
app: App;
header(field: string | object, val: string | any[]): Response;
set(field: string | object, val: string | any[]): Response;
send(body: unknown): Response;
json(body: unknown): Response;
status(status: number): Response;
cookie(name: string, value: string | object, options?: SerializeOptions & Partial<{
signed: boolean;
}>): Response;
clearCookie(name: string, options?: SerializeOptions): Response;
location(url: string): Response;
}
declare const METHODS: string[];
type Handler = (req: Request, res: Response) => void | Promise<void>;
type Handler = (req: Request, res: Response, next?: () => void) => void | Promise<void>;
type Method = "GET" | "POST" | "PUT" | "PATCH" | "HEAD" | string;
declare const onError: (err: any, _req: Request, res: Response, _next: () => void) => void;
interface Middleware {

@@ -58,3 +77,4 @@ method?: Method;

middleware: Middleware[];
constructor();
noMatchHandler: Handler;
constructor(noMatchHandler?: Handler);
get(url: string | Handler, handler?: Handler): this;

@@ -67,5 +87,6 @@ post(url: string | Handler, handler?: Handler): this;

use(handler: Handler): this;
handle(req: Request, res: Response): void;
listen(port?: number, cb?: () => void, host?: string, backlog?: number): import("http").Server;
}
declare const notFound: () => Handler;
export { METHODS, Handler, Method, Middleware, App, notFound, getQueryParams, URLParams, getURLParams, getRouteFromApp, compileTrust, getProtocol, getHeader, getRangeFromHeader, checkIfXMLHttpRequest, getHostname, getIP, Connection, Protocol, Request, json, send, status, Response };
export { METHODS, Handler, Method, onError, Middleware, App, notFound, getQueryParams, URLParams, getURLParams, getRouteFromApp, getProtocol, getHeader, getRangeFromHeader, checkIfXMLHttpRequest, getHostname, getIP, Connection, Protocol, Request, json, send, status, setCookie, clearCookie, setHeader, setLocationHeader, Response };

2

dist/index.esm.js

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

import{createServer as e}from"http";import t from"regexparam";import{parse as r}from"url";import n from"proxy-addr";import o from"range-parser";import{format as s,parse as d}from"content-type";import u from"@tinyhttp/etag";const a=(e="/")=>r(e,!0).query,i=(e="/",r="/")=>((e,t)=>{let r=0,n={},o=t.pattern.exec(e);for(;r<t.keys.length;)n[t.keys[r]]=(null==o?void 0:o[++r])||null;return n})(e,t(r)),l=(e,t)=>e.routes.find(e=>e.handler.name===t.name),h=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(/ *, */)),n.compile(e||[])),p=e=>{const t=e.connection.encrypted?"https":"http";if(!h(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()},f=e=>t=>e.headers[t.toLowerCase()],m=e=>(t,r)=>{const n=e.get("Range");if(n)return o(t,n,r)},c=e=>"XMLHttpRequest"===e.headers["X-Requested-With"],g=e=>{let t=e.get("X-Forwarded-Host");if(t&&h(e.connection.remoteAddress)||(t=e.get("Host")),t){var r="["===t[0]?t.indexOf("]")+1:0,n=t.indexOf(":",r);return-1!==n?t.substring(0,n):t}},y=e=>n(e,h),H=(e,t)=>{const r=Buffer.isBuffer(e)?e:Buffer.from(e,t);return u(r,{weak:!0})};const C=(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),T=(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=d(e);return r.parameters.charset=t,s(r)}(e,"utf-8"))}let o;return!t.getHeader("etag")&&(o=H(n,"utf8"))&&t.setHeader("etag",o),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"):C(0,t)(n,"utf8"):t.end(n,"utf8"),t},w=(e,t)=>e=>(t.statusCode=e,t),b=()=>(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))},E=["GET","POST","PUT","PATCH","HEAD"],x=({url:e,handler:t,method:r})=>({method:r,handler:t||e,url:"string"==typeof e?e:"*"});class O{constructor(){this.routes=[],this.middleware=[]}get(e,t){return this.routes.push(x({url:e,handler:t,method:"GET"})),this}post(e,t){return this.routes.push(x({url:e,handler:t,method:"POST"})),this}put(e,t){return this.routes.push(x({url:e,handler:t,method:"PUT"})),this}patch(e,t){return this.routes.push(x({url:e,handler:t,method:"PATCH"})),this}head(e,t){return this.routes.push(x({url:e,handler:t,method:"HEAD"})),this}all(e,t){for(const r of E)this.routes.push(x({url:e,handler:t,method:r}));return this}use(e){return this.middleware.push({handler:e}),this}listen(r,n=(()=>console.log(`Started on http://${o}:${r}`)),o="localhost",s){return e((e,r)=>{const n=p(e),o="https"===n;e.protocol=n,e.secure=o,e.connection=Object.assign(e.socket,{encrypted:o}),e.query=a(e.url),e.get=f(e),e.range=m(e),e.xhr=c(e),e.hostname=g(e),r.send=T(e,r),r.json=C(0,r),r.status=w(0,r),this.routes.map(({url:n,method:o,handler:s})=>{e.method===o&&n&&e.url&&t(n).pattern.test(e.url)&&(e.params=i(e.url,n),e.route=l(this,s),r.writableEnded||(r.statusCode=200,s(e,r)))});let s=this.middleware.filter(e=>"logger"!==e.handler.name);s.push({handler:(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))}});const d=this.middleware.find(e=>"logger"===e.handler.name);d&&s.push(d),s.map(({handler:t})=>{t(e,r)})}).listen(r,o,s,n)}}export{O as App,E as METHODS,c as checkIfXMLHttpRequest,h as compileTrust,f as getHeader,g as getHostname,y as getIP,p as getProtocol,a as getQueryParams,m as getRangeFromHeader,l as getRouteFromApp,i as getURLParams,C as json,b as notFound,T as send,w as status};
import{STATUS_CODES as e,createServer as t}from"http";import r from"regexparam";import{parse as n}from"url";import o from"range-parser";import s from"proxy-addr";import a from"encodeurl";import{sign as i}from"@tinyhttp/cookie-signature";import d from"mime";import u from"@tinyhttp/cookie";import{format as h,parse as l}from"content-type";import p from"@tinyhttp/etag";const f=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(/ *, */)),s.compile(e||[])),c=(e="/")=>n(e,!0).query,m=(e="/",t="/")=>((e,t)=>{let r=0,n={},o=t.pattern.exec(e);for(;r<t.keys.length;)n[t.keys[r]]=(null==o?void 0:o[++r])||null;return n})(e,r(t)),g=(e,t)=>e.routes.find(e=>e.handler.name===t.name),y=e=>{const t=e.connection.encrypted?"https":"http";if(!f(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()},H=e=>t=>e.headers[t.toLowerCase()],C=e=>(t,r)=>{const n=e.get("Range");if(n)return o(t,n,r)},w=e=>"XMLHttpRequest"===e.headers["X-Requested-With"],T=e=>{let t=e.get("X-Forwarded-Host");if(t&&f(e.connection.remoteAddress)||(t=e.get("Host")),t){var r="["===t[0]?t.indexOf("]")+1:0,n=t.indexOf(":",r);return-1!==n?t.substring(0,n):t}},A=e=>s(e,f),b=(e,t)=>{const r=Buffer.isBuffer(e)?e:Buffer.from(e,t);return p(r,{weak:!0})};const x=(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),k=(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=l(e);return r.parameters.charset=t,h(r)}(e,"utf-8"))}let o;return!t.getHeader("etag")&&(o=b(n,"utf8"))&&t.setHeader("etag",o),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"):x(0,t)(n,"utf8"):t.end(n,"utf8"),t},E=(e,t)=>e=>(t.statusCode=e,t),S=(e,t)=>(r,n,o)=>{const s=e.secret,a=o.signed;if(a&&!s)throw new Error('cookieParser("secret") required for signed cookies');let d="object"==typeof n?"j:"+JSON.stringify(n):String(n);return a&&(d="s:"+i(d,s)),o.maxAge&&(o.expires=new Date(Date.now()+o.maxAge),o.maxAge/=1e3),null==o.path&&(o.path="/"),t.setHeader("Set-Cookie",u.serialize(r,String(d),o)),t},O=(e,t)=>(r,n)=>{const o=Object.assign({},{expires:new Date(1),path:"/"},n);return S(e,t)(r,"",o)},j=/;\s*charset\s*=/,P=(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(!j.test(n)){const e=d.getType(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},B=(e,t)=>r=>{let n=r;return"back"===r&&(n=e.get("Referrer")||"/"),t.setHeader("Location",a(n))},D=()=>(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))},L=["GET","POST","PUT","PATCH","HEAD"],q=(t,r,n,o)=>{let s=n.statusCode=t.code||t.status||500;"string"==typeof t||Buffer.isBuffer(t)?n.end(t):n.end(t.message||e[s])},v=({url:e,handler:t,method:r})=>({method:r,handler:t||e,url:"string"==typeof e?e:"*"});class N{constructor(e=((e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))})){this.routes=[],this.middleware=[],this.noMatchHandler=e}get(e,t){return this.routes.push(v({url:e,handler:t,method:"GET"})),this}post(e,t){return this.routes.push(v({url:e,handler:t,method:"POST"})),this}put(e,t){return this.routes.push(v({url:e,handler:t,method:"PUT"})),this}patch(e,t){return this.routes.push(v({url:e,handler:t,method:"PATCH"})),this}head(e,t){return this.routes.push(v({url:e,handler:t,method:"HEAD"})),this}all(e,t){for(const r of L)this.routes.push(v({url:e,handler:t,method:r}));return this}use(e){return this.middleware.push({handler:e}),this}handle(e,t){e.app=this;const n=y(e),o="https"===n;e.protocol=n,e.secure=o,e.connection=Object.assign(e.socket,{encrypted:o}),e.query=c(e.url),e.get=H(e),e.range=C(e),e.xhr=w(e),e.hostname=T(e),t.app=this,t.header=t.set=P(0,t),t.send=k(e,t),t.json=x(0,t),t.status=E(0,t),t.cookie=S(e,t),t.clearCookie=O(e,t);for(const n of this.routes){const{url:o,method:s,handler:a}=n;t.writableEnded||e.method===s&&o&&e.url&&r(o).pattern.test(e.url)&&(e.params=m(e.url,o),e.route=g(this,a),t.statusCode=200,a(e,t))}let s=this.middleware.filter(e=>"logger"!==e.handler.name);s.push({handler:this.noMatchHandler});const a=this.middleware.find(e=>"logger"===e.handler.name);a&&s.push(a),s.map(({handler:r})=>{r(e,t)})}listen(e,r=(()=>console.log(`Started on http://${n}:${e}`)),n="localhost",o){return t((e,t)=>{this.handle(e,t)}).listen(e,n,o,r)}}export{N as App,L as METHODS,w as checkIfXMLHttpRequest,O as clearCookie,H as getHeader,T as getHostname,A as getIP,y as getProtocol,c as getQueryParams,C as getRangeFromHeader,g as getRouteFromApp,m as getURLParams,x as json,D as notFound,q as onError,k as send,S as setCookie,P as setHeader,B as setLocationHeader,E as status};

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

"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("http"),r=e(require("regexparam")),s=require("url"),n=e(require("proxy-addr")),o=e(require("range-parser")),u=require("content-type"),a=e(require("@tinyhttp/etag"));const d=(e="/")=>s.parse(e,!0).query,i=(e="/",t="/")=>((e,t)=>{let r=0,s={},n=t.pattern.exec(e);for(;r<t.keys.length;)s[t.keys[r]]=(null==n?void 0:n[++r])||null;return s})(e,r(t)),p=(e,t)=>e.routes.find(e=>e.handler.name===t.name),l=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(/ *, */)),n.compile(e||[])),h=e=>{const t=e.connection.encrypted?"https":"http";if(!l(e.connection.remoteAddress))return t;const r=e.headers["X-Forwarded-Proto"]||t,s=r.indexOf(",");return-1!==s?r.substring(0,s).trim():r.trim()},c=e=>t=>e.headers[t.toLowerCase()],f=e=>(t,r)=>{const s=e.get("Range");if(s)return o(t,s,r)},m=e=>"XMLHttpRequest"===e.headers["X-Requested-With"],g=e=>{let t=e.get("X-Forwarded-Host");if(t&&l(e.connection.remoteAddress)||(t=e.get("Host")),t){var r="["===t[0]?t.indexOf("]")+1:0,s=t.indexOf(":",r);return-1!==s?t.substring(0,s):t}},y=(e,t)=>{const r=Buffer.isBuffer(e)?e:Buffer.from(e,t);return a(r,{weak:!0})};const x=(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),H=(e,t)=>r=>{let s=r;if("object"==typeof r&&"null"!==r)s=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.parse(e);return r.parameters.charset=t,u.format(r)}(e,"utf-8"))}let n;return!t.getHeader("etag")&&(n=y(s,"utf8"))&&t.setHeader("etag",n),204!==t.statusCode&&304!==t.statusCode||(t.removeHeader("Content-Type"),t.removeHeader("Content-Length"),t.removeHeader("Transfer-Encoding"),s=""),"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"):x(0,t)(s,"utf8"):t.end(s,"utf8"),t},T=(e,t)=>e=>(t.statusCode=e,t),C=()=>(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))},b=["GET","POST","PUT","PATCH","HEAD"],q=({url:e,handler:t,method:r})=>({method:r,handler:t||e,url:"string"==typeof e?e:"*"});exports.App=class{constructor(){this.routes=[],this.middleware=[]}get(e,t){return this.routes.push(q({url:e,handler:t,method:"GET"})),this}post(e,t){return this.routes.push(q({url:e,handler:t,method:"POST"})),this}put(e,t){return this.routes.push(q({url:e,handler:t,method:"PUT"})),this}patch(e,t){return this.routes.push(q({url:e,handler:t,method:"PATCH"})),this}head(e,t){return this.routes.push(q({url:e,handler:t,method:"HEAD"})),this}all(e,t){for(const r of b)this.routes.push(q({url:e,handler:t,method:r}));return this}use(e){return this.middleware.push({handler:e}),this}listen(e,s=(()=>console.log(`Started on http://${n}:${e}`)),n="localhost",o){return t.createServer((e,t)=>{const s=h(e),n="https"===s;e.protocol=s,e.secure=n,e.connection=Object.assign(e.socket,{encrypted:n}),e.query=d(e.url),e.get=c(e),e.range=f(e),e.xhr=m(e),e.hostname=g(e),t.send=H(e,t),t.json=x(0,t),t.status=T(0,t),this.routes.map(({url:s,method:n,handler:o})=>{e.method===n&&s&&e.url&&r(s).pattern.test(e.url)&&(e.params=i(e.url,s),e.route=p(this,o),t.writableEnded||(t.statusCode=200,o(e,t)))});let o=this.middleware.filter(e=>"logger"!==e.handler.name);o.push({handler:(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))}});const u=this.middleware.find(e=>"logger"===e.handler.name);u&&o.push(u),o.map(({handler:r})=>{r(e,t)})}).listen(e,n,o,s)}},exports.METHODS=b,exports.checkIfXMLHttpRequest=m,exports.compileTrust=l,exports.getHeader=c,exports.getHostname=g,exports.getIP=e=>n(e,l),exports.getProtocol=h,exports.getQueryParams=d,exports.getRangeFromHeader=f,exports.getRouteFromApp=p,exports.getURLParams=i,exports.json=x,exports.notFound=C,exports.send=H,exports.status=T;
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("http"),r=e(require("regexparam")),s=require("url"),o=e(require("range-parser")),n=e(require("proxy-addr")),a=e(require("encodeurl")),i=require("@tinyhttp/cookie-signature"),u=e(require("mime")),d=e(require("@tinyhttp/cookie")),p=require("content-type"),l=e(require("@tinyhttp/etag"));const h=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(/ *, */)),n.compile(e||[])),c=(e="/")=>s.parse(e,!0).query,f=(e="/",t="/")=>((e,t)=>{let r=0,s={},o=t.pattern.exec(e);for(;r<t.keys.length;)s[t.keys[r]]=(null==o?void 0:o[++r])||null;return s})(e,r(t)),g=(e,t)=>e.routes.find(e=>e.handler.name===t.name),m=e=>{const t=e.connection.encrypted?"https":"http";if(!h(e.connection.remoteAddress))return t;const r=e.headers["X-Forwarded-Proto"]||t,s=r.indexOf(",");return-1!==s?r.substring(0,s).trim():r.trim()},y=e=>t=>e.headers[t.toLowerCase()],x=e=>(t,r)=>{const s=e.get("Range");if(s)return o(t,s,r)},H=e=>"XMLHttpRequest"===e.headers["X-Requested-With"],C=e=>{let t=e.get("X-Forwarded-Host");if(t&&h(e.connection.remoteAddress)||(t=e.get("Host")),t){var r="["===t[0]?t.indexOf("]")+1:0,s=t.indexOf(":",r);return-1!==s?t.substring(0,s):t}},w=(e,t)=>{const r=Buffer.isBuffer(e)?e:Buffer.from(e,t);return l(r,{weak:!0})};const T=(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),A=(e,t)=>r=>{let s=r;if("object"==typeof r&&"null"!==r)s=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=p.parse(e);return r.parameters.charset=t,p.format(r)}(e,"utf-8"))}let o;return!t.getHeader("etag")&&(o=w(s,"utf8"))&&t.setHeader("etag",o),204!==t.statusCode&&304!==t.statusCode||(t.removeHeader("Content-Type"),t.removeHeader("Content-Length"),t.removeHeader("Transfer-Encoding"),s=""),"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"):T(0,t)(s,"utf8"):t.end(s,"utf8"),t},q=(e,t)=>e=>(t.statusCode=e,t),b=(e,t)=>(r,s,o)=>{const n=e.secret,a=o.signed;if(a&&!n)throw new Error('cookieParser("secret") required for signed cookies');let u="object"==typeof s?"j:"+JSON.stringify(s):String(s);return a&&(u="s:"+i.sign(u,n)),o.maxAge&&(o.expires=new Date(Date.now()+o.maxAge),o.maxAge/=1e3),null==o.path&&(o.path="/"),t.setHeader("Set-Cookie",d.serialize(r,String(u),o)),t},S=(e,t)=>(r,s)=>{const o=Object.assign({},{expires:new Date(1),path:"/"},s);return b(e,t)(r,"",o)},k=/;\s*charset\s*=/,E=(e,t)=>(e,r)=>{if("string"==typeof e){let s=Array.isArray(r)?r.map(String):String(r);if("content-type"===e.toLowerCase()){if(Array.isArray(s))throw new TypeError("Content-Type cannot be set to an Array");if(!k.test(s)){const e=u.getType(s.split(";")[0]);e&&(s+="; charset="+e.toLowerCase())}}t.setHeader(e,s)}else for(const r in e)t.setHeader(r,e[r]);return t},O=()=>(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))},P=["GET","POST","PUT","PATCH","HEAD"],j=({url:e,handler:t,method:r})=>({method:r,handler:t||e,url:"string"==typeof e?e:"*"});exports.App=class{constructor(e=((e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))})){this.routes=[],this.middleware=[],this.noMatchHandler=e}get(e,t){return this.routes.push(j({url:e,handler:t,method:"GET"})),this}post(e,t){return this.routes.push(j({url:e,handler:t,method:"POST"})),this}put(e,t){return this.routes.push(j({url:e,handler:t,method:"PUT"})),this}patch(e,t){return this.routes.push(j({url:e,handler:t,method:"PATCH"})),this}head(e,t){return this.routes.push(j({url:e,handler:t,method:"HEAD"})),this}all(e,t){for(const r of P)this.routes.push(j({url:e,handler:t,method:r}));return this}use(e){return this.middleware.push({handler:e}),this}handle(e,t){e.app=this;const s=m(e),o="https"===s;e.protocol=s,e.secure=o,e.connection=Object.assign(e.socket,{encrypted:o}),e.query=c(e.url),e.get=y(e),e.range=x(e),e.xhr=H(e),e.hostname=C(e),t.app=this,t.header=t.set=E(0,t),t.send=A(e,t),t.json=T(0,t),t.status=q(0,t),t.cookie=b(e,t),t.clearCookie=S(e,t);for(const s of this.routes){const{url:o,method:n,handler:a}=s;t.writableEnded||e.method===n&&o&&e.url&&r(o).pattern.test(e.url)&&(e.params=f(e.url,o),e.route=g(this,a),t.statusCode=200,a(e,t))}let n=this.middleware.filter(e=>"logger"!==e.handler.name);n.push({handler:this.noMatchHandler});const a=this.middleware.find(e=>"logger"===e.handler.name);a&&n.push(a),n.map(({handler:r})=>{r(e,t)})}listen(e,r=(()=>console.log(`Started on http://${s}:${e}`)),s="localhost",o){return t.createServer((e,t)=>{this.handle(e,t)}).listen(e,s,o,r)}},exports.METHODS=P,exports.checkIfXMLHttpRequest=H,exports.clearCookie=S,exports.getHeader=y,exports.getHostname=C,exports.getIP=e=>n(e,h),exports.getProtocol=m,exports.getQueryParams=c,exports.getRangeFromHeader=x,exports.getRouteFromApp=g,exports.getURLParams=f,exports.json=T,exports.notFound=O,exports.onError=(e,r,s,o)=>{let n=s.statusCode=e.code||e.status||500;"string"==typeof e||Buffer.isBuffer(e)?s.end(e):s.end(e.message||t.STATUS_CODES[n])},exports.send=A,exports.setCookie=b,exports.setHeader=E,exports.setLocationHeader=(e,t)=>r=>{let s=r;return"back"===r&&(s=e.get("Referrer")||"/"),t.setHeader("Location",a(s))},exports.status=q;
{
"name": "@tinyhttp/app",
"version": "0.1.20",
"description": "tinyhttp core",
"homepage": "https://github.com/talentlessguy/tinyhttp",
"repository": {
"type": "git",
"url": "https://github.com/talentlessguy/tinyhttp.git",
"directory": "packages/app"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"module": "dist/index.esm.js",
"files": [
"dist"
],
"engines": {
"node": ">=14"
},
"keywords": [
"tinyhttp",
"node.js",
"web framework",
"web",
"backend"
],
"author": "v1rtl",
"license": "MIT",
"dependencies": {
"@tinyhttp/etag": "workspace:*",
"content-type": "^1.0.4",
"proxy-addr": "^2.0.6",
"range-parser": "^1.2.1",
"regexparam": "^1.3.0"
},
"devDependencies": {
"@types/content-type": "^1.1.3",
"@types/proxy-addr": "^2.0.0",
"@types/range-parser": "^1.2.3"
}
"name": "@tinyhttp/app",
"version": "0.1.21",
"description": "tinyhttp core",
"homepage": "https://github.com/talentlessguy/tinyhttp",
"repository": {
"type": "git",
"url": "https://github.com/talentlessguy/tinyhttp.git",
"directory": "packages/app"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"module": "dist/index.esm.js",
"files": [
"dist"
],
"engines": {
"node": ">=14"
},
"keywords": [
"tinyhttp",
"node.js",
"web framework",
"web",
"backend"
],
"author": "v1rtl",
"license": "MIT",
"dependencies": {
"@tinyhttp/cookie": "^0.0.5",
"@tinyhttp/cookie-signature": "^0.0.4",
"@tinyhttp/etag": "^0.1.15",
"content-type": "^1.0.4",
"encodeurl": "^1.0.2",
"mime": "^2.4.6",
"proxy-addr": "^2.0.6",
"range-parser": "^1.2.1",
"regexparam": "^1.3.0"
},
"devDependencies": {
"@types/content-type": "^1.1.3",
"@types/encodeurl": "^1.0.0",
"@types/mime": "^2.0.2",
"@types/proxy-addr": "^2.0.0",
"@types/range-parser": "^1.2.3"
}
}

@@ -1,33 +0,75 @@

# @tinyhttp/app
![Twitter](https://img.shields.io/twitter/follow/v1rtl.svg?label=sub%20to%20twitter&style=flat-square) ![npm type definitions](https://img.shields.io/npm/types/@tinyhttp/app?style=flat-square)
![Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/npm/body-parsec.svg?style=flat-square)
![Last commit](https://img.shields.io/github/last-commit/talentlessguy/tinyhttp.svg?style=flat-square) ![NPM](https://img.shields.io/npm/l/@tinyhttp/app?style=flat-square)
tinyhttp core
# @tinyhttp/core
`tinyhttp` core module with `App`, `Request` and `Response` classes.
> ⚠ The project is incomplete. Please don't use in production.
**tinyhttp** is a modern Express-like web framework for Node.js. It uses a bare minimum amount of dependencies trying to avoid legacy.
## Installation
This is a [Node.js](https://nodejs.org/) module available through the
[npm registry](https://www.npmjs.com/). It can be installed using the
[`npm`](https://docs.npmjs.com/getting-started/installing-npm-packages-locally)
or
[`yarn`](https://yarnpkg.com/en/)
command line tools.
Node.js 13 is required.
```sh
npm install @tinyhttp/app --save
# npm
npm i @tinyhttp/app
# pnpm
pnpm i @tinyhttp/app
# yarn
yarn add @tinyhttp/app
```
## Dependencies
## Features
- [@tinyhttp/etag](https://ghub.io/@tinyhttp/etag): tinyhttp eTag module
- [content-type](https://ghub.io/content-type): Create and parse HTTP Content-Type header
- [proxy-addr](https://ghub.io/proxy-addr): Determine address of proxied request
- [range-parser](https://ghub.io/range-parser): Range header field string parser
- [regexparam](https://ghub.io/regexparam): A tiny (308B) utility that converts route patterns into RegExp. Limited alternative to `path-to-regexp` 🙇‍
- Compatible with Express
- Async routes [not tested yet]
- Smaller size
- 0 legacy dependencies
## Dev Dependencies
## Docs
- [@types/proxy-addr](https://ghub.io/@types/proxy-addr): TypeScript definitions for proxy-addr
- [@types/range-parser](https://ghub.io/@types/range-parser): TypeScript definitions for range-parser
Coming soon...
## License
## Example
MIT
At the moment there is only one basic example. I will add more of them once I add all the existing Express `req` / `res` extensions.
```ts
import { App } from '@tinyhttp/app'
import staticFolder from '@tinyhttp/static'
import logger from '@tinyhttp/logger'
const app = new App()
app.all('/', (req, res) => {
res.status(200).send(`
<h1>tinyhttp example</h1>
<ul>
<li>Protocol: ${req.protocol}</li>
<li>HTTPS: ${req.secure ? 'yes' : 'no'}</li>
<li>URL: ${req.url}</li>
<li>Method: ${req.method}</li>
<li>Host: ${req.hostname}</li>
<li>Status: ${res.statusCode}</li>
</ul>
<h2>Request headers</h2>
<pre>
${JSON.stringify(req.headers, null, 2)}
</pre>
`)
})
app.get('/:first/:second', (req, res) => {
res.json({ URLParams: req.params, QueryParams: req.query })
})
app.use(staticFolder())
app.use(logger())
app.listen(3000)
```
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