@techiev2/vajra 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/examples/api.js +3 -0
- package/index.js +14 -7
- package/package.json +1 -1
package/examples/api.js
CHANGED
package/index.js
CHANGED
|
@@ -59,6 +59,11 @@ export default class Vajra {
|
|
|
59
59
|
res.sent = true; res.setHeader('Content-Type', 'text/html'); res.setHeader('Content-Length', Buffer.from(content).byteLength); res.write(content); res.end(); return res
|
|
60
60
|
}
|
|
61
61
|
req._headers = { ...req.headers }; req.headers = Object.fromEntries(req.rawHeaders.map((e, i) => i % 2 ? false : [e, req.rawHeaders[i + 1]]).filter(Boolean)); req.isPossibleJSON = req._headers['content-type'] === 'application/json'; req.params = {}
|
|
62
|
+
res.cookie = (k, v, options) => {
|
|
63
|
+
let { expires, path, maxAge, domain, secure, httpOnly, sameSite } = typeof options === 'object' ? options : typeof v === 'object' ? v : {}; const cookieOpts = [];!isNaN(+maxAge) && cookieOpts.push(`Max-Age=${Math.floor(maxAge)}`); !isNaN(+expires) && cookieOpts.push(`Expires=${new Date(expires).toUTCString()}`); expires instanceof Date && cookieOpts.push(`Expires=${expires.toUTCString()}`)
|
|
64
|
+
path && cookieOpts.push(`Path=${path}`); domain && cookieOpts.push(`Domain=${domain}`); !!secure && cookieOpts.push(`Secure`); !!httpOnly && cookieOpts.push(`HttpOnly`); sameSite = sameSite && (sameSite === true ? 'Strict' : typeof sameSite === 'string' ? sameSite.charAt(0).toUpperCase() + sameSite.slice(1).toLowerCase() : ''); !['Strict', 'Lax', 'None'].includes(sameSite) ? sameSite = 'Strict' : sameSite = sameSite; cookieOpts.push(`SameSite=${sameSite}`)
|
|
65
|
+
res.setHeader('Set-Cookie', (typeof k === 'object') ? Object.entries(k).map(([k_, v_]) => `${k_}=${encodeURIComponent(v_)}${cookieOpts.length ? `; ${cookieOpts.join('; ')}` : ''}`) : [...(res.getHeader('Set-Cookie') || []).filter(Boolean), `${k}=${encodeURIComponent(v)}${cookieOpts.length ? `; ${cookieOpts.join('; ')}` : ''}`])
|
|
66
|
+
}
|
|
62
67
|
let url = `http://${req.headers.host || req.headers.host}/${req.url}`; req.query = Object.fromEntries(new URL(url).searchParams)
|
|
63
68
|
if (req.method === 'GET' || req.method === 'HEAD') { return runMiddlwares() }
|
|
64
69
|
async function runMiddlwares() {
|
|
@@ -66,19 +71,21 @@ export default class Vajra {
|
|
|
66
71
|
await next();
|
|
67
72
|
}
|
|
68
73
|
setImmediate(() => {
|
|
69
|
-
req.body = {}; req.rawData = ''; req.formData = {};let dataSize = 0
|
|
74
|
+
req.body = {}; req.rawData = ''; req.formData = {}; let dataSize = 0
|
|
70
75
|
req.on('data', (chunk) => { dataSize += chunk.length; if (dataSize > Vajra.#MAX_FILE_SIZE) { return default_413(res) }; req.rawData+=chunk })
|
|
71
|
-
const formDataMatcher = /Content-Disposition: form-data; name=['"](?<name>[^"']+)['"]\s+(?<value>.*?)$/smi;
|
|
72
|
-
const fileDataMatcher = /^Content-Disposition:.*?name=["'](?<field>[^"']+)["'].*?filename=["'](?<fileName>[^"']+)["'].*?Content-Type:\s*(?<contentType>[^\r\n]*)\r?\n\r?\n(?<content>[\s\S]*)$/ims
|
|
76
|
+
const formDataMatcher = /Content-Disposition: form-data; name=['"](?<name>[^"']+)['"]\s+(?<value>.*?)$/smi;
|
|
77
|
+
let boundaryMatch = (req.headers['Content-Type'] || '').match(/boundary=(.*)/); const boundary = boundaryMatch ? '--' + boundaryMatch[1] : null; const fileDataMatcher = /^Content-Disposition:.*?name=["'](?<field>[^"']+)["'].*?filename=["'](?<fileName>[^"']+)["'].*?Content-Type:\s*(?<contentType>[^\r\n]*)\r?\n\r?\n(?<content>[\s\S]*)$/ims
|
|
73
78
|
req.on('end', async () => {
|
|
74
|
-
req.files = []; req.rawData.split(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
req.files = []; if (boundary) { req.rawData.split(boundary).filter(Boolean).map((line) => {
|
|
80
|
+
let key, value; if (line.includes('filename')) { req.files.push(fileDataMatcher.exec(line)?.groups || {}); return }
|
|
81
|
+
[key, value] = Object.values(line.match(formDataMatcher)?.groups || {}); (key && value) && Object.assign(req.formData, { [key]: value }); return
|
|
82
|
+
})
|
|
83
|
+
}
|
|
78
84
|
if (Object.keys(req.formData).length) { req.body = req.formData } else {
|
|
79
85
|
try { req.body = JSON.parse(req.rawData); req.isPossibleJSON = true } catch (_) { req.body = Object.fromEntries(req.rawData.split('&').map((pair) => pair.split('='))) }
|
|
80
86
|
}; setImmediate(runMiddlwares)
|
|
81
87
|
})
|
|
88
|
+
req.cookies = Object.fromEntries((req.headers.Cookie || req.headers.cookie || '').split(/;\s*/).map((k) => k.split('=')).map(([k, v]) => [k.trim(), decodeURIComponent(v).trim()]))
|
|
82
89
|
})
|
|
83
90
|
async function handleRoute() {
|
|
84
91
|
let match_; const directHandler = (Vajra.#straightRoutes[req.url] || {})[req.method.toLowerCase()]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techiev2/vajra",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Blazing-fast, zero-dependency Node.js server with routing, middleware, multipart uploads, and templating. 111 lines · ~95k req/s · ~52 MB idle.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"http-server",
|