Buckets:
ktongue/docker_container / CAD_kevin /frontend /node_modules /webpack-dev-middleware /dist /middleware.js
| ; | |
| const path = require("path"); | |
| const mime = require("mime-types"); | |
| const parseRange = require("range-parser"); | |
| const getFilenameFromUrl = require("./utils/getFilenameFromUrl"); | |
| const { | |
| getHeaderNames, | |
| getHeaderFromRequest, | |
| getHeaderFromResponse, | |
| setHeaderForResponse, | |
| setStatusCode, | |
| send, | |
| sendError | |
| } = require("./utils/compatibleAPI"); | |
| const ready = require("./utils/ready"); | |
| /** @typedef {import("./index.js").NextFunction} NextFunction */ | |
| /** @typedef {import("./index.js").IncomingMessage} IncomingMessage */ | |
| /** @typedef {import("./index.js").ServerResponse} ServerResponse */ | |
| /** | |
| * @param {string} type | |
| * @param {number} size | |
| * @param {import("range-parser").Range} [range] | |
| * @returns {string} | |
| */ | |
| function getValueContentRangeHeader(type, size, range) { | |
| return `${type} ${range ? `${range.start}-${range.end}` : "*"}/${size}`; | |
| } | |
| /** | |
| * @param {string | number} title | |
| * @param {string} body | |
| * @returns {string} | |
| */ | |
| function createHtmlDocument(title, body) { | |
| return `${"<!DOCTYPE html>\n" + '<html lang="en">\n' + "<head>\n" + '<meta charset="utf-8">\n' + "<title>"}${title}</title>\n` + `</head>\n` + `<body>\n` + `<pre>${body}</pre>\n` + `</body>\n` + `</html>\n`; | |
| } | |
| const BYTES_RANGE_REGEXP = /^ *bytes/i; | |
| /** | |
| * @template {IncomingMessage} Request | |
| * @template {ServerResponse} Response | |
| * @param {import("./index.js").Context<Request, Response>} context | |
| * @return {import("./index.js").Middleware<Request, Response>} | |
| */ | |
| function wrapper(context) { | |
| return async function middleware(req, res, next) { | |
| const acceptedMethods = context.options.methods || ["GET", "HEAD"]; // fixes #282. credit @cexoso. in certain edge situations res.locals is undefined. | |
| // eslint-disable-next-line no-param-reassign | |
| res.locals = res.locals || {}; | |
| if (req.method && !acceptedMethods.includes(req.method)) { | |
| await goNext(); | |
| return; | |
| } | |
| ready(context, processRequest, req); | |
| async function goNext() { | |
| if (!context.options.serverSideRender) { | |
| return next(); | |
| } | |
| return new Promise(resolve => { | |
| ready(context, () => { | |
| /** @type {any} */ | |
| // eslint-disable-next-line no-param-reassign | |
| res.locals.webpack = { | |
| devMiddleware: context | |
| }; | |
| resolve(next()); | |
| }, req); | |
| }); | |
| } | |
| async function processRequest() { | |
| /** @type {import("./utils/getFilenameFromUrl").Extra} */ | |
| const extra = {}; | |
| const filename = getFilenameFromUrl(context, | |
| /** @type {string} */ | |
| req.url, extra); | |
| if (!filename) { | |
| await goNext(); | |
| return; | |
| } | |
| if (extra.errorCode) { | |
| if (extra.errorCode === 403) { | |
| context.logger.error(`Malicious path "${filename}".`); | |
| } | |
| sendError(req, res, extra.errorCode); | |
| return; | |
| } | |
| let { | |
| headers | |
| } = context.options; | |
| if (typeof headers === "function") { | |
| // @ts-ignore | |
| headers = headers(req, res, context); | |
| } | |
| /** | |
| * @type {{key: string, value: string | number}[]} | |
| */ | |
| const allHeaders = []; | |
| if (typeof headers !== "undefined") { | |
| if (!Array.isArray(headers)) { | |
| // eslint-disable-next-line guard-for-in | |
| for (const name in headers) { | |
| // @ts-ignore | |
| allHeaders.push({ | |
| key: name, | |
| value: headers[name] | |
| }); | |
| } | |
| headers = allHeaders; | |
| } | |
| headers.forEach( | |
| /** | |
| * @param {{key: string, value: any}} header | |
| */ | |
| header => { | |
| setHeaderForResponse(res, header.key, header.value); | |
| }); | |
| } | |
| if (!getHeaderFromResponse(res, "Content-Type")) { | |
| // content-type name(like application/javascript; charset=utf-8) or false | |
| const contentType = mime.contentType(path.extname(filename)); // Only set content-type header if media type is known | |
| // https://tools.ietf.org/html/rfc7231#section-3.1.1.5 | |
| if (contentType) { | |
| setHeaderForResponse(res, "Content-Type", contentType); | |
| } | |
| } | |
| if (!getHeaderFromResponse(res, "Accept-Ranges")) { | |
| setHeaderForResponse(res, "Accept-Ranges", "bytes"); | |
| } | |
| const rangeHeader = getHeaderFromRequest(req, "range"); | |
| let start; | |
| let end; | |
| if (rangeHeader && BYTES_RANGE_REGEXP.test(rangeHeader)) { | |
| const size = await new Promise(resolve => { | |
| /** @type {import("fs").lstat} */ | |
| context.outputFileSystem.lstat(filename, (error, stats) => { | |
| if (error) { | |
| context.logger.error(error); | |
| return; | |
| } | |
| resolve(stats.size); | |
| }); | |
| }); | |
| const parsedRanges = parseRange(size, rangeHeader, { | |
| combine: true | |
| }); | |
| if (parsedRanges === -1) { | |
| const message = "Unsatisfiable range for 'Range' header."; | |
| context.logger.error(message); | |
| const existingHeaders = getHeaderNames(res); | |
| for (let i = 0; i < existingHeaders.length; i++) { | |
| res.removeHeader(existingHeaders[i]); | |
| } | |
| setStatusCode(res, 416); | |
| setHeaderForResponse(res, "Content-Range", getValueContentRangeHeader("bytes", size)); | |
| setHeaderForResponse(res, "Content-Type", "text/html; charset=utf-8"); | |
| const document = createHtmlDocument(416, `Error: ${message}`); | |
| const byteLength = Buffer.byteLength(document); | |
| setHeaderForResponse(res, "Content-Length", Buffer.byteLength(document)); | |
| send(req, res, document, byteLength); | |
| return; | |
| } else if (parsedRanges === -2) { | |
| context.logger.error("A malformed 'Range' header was provided. A regular response will be sent for this request."); | |
| } else if (parsedRanges.length > 1) { | |
| context.logger.error("A 'Range' header with multiple ranges was provided. Multiple ranges are not supported, so a regular response will be sent for this request."); | |
| } | |
| if (parsedRanges !== -2 && parsedRanges.length === 1) { | |
| // Content-Range | |
| setStatusCode(res, 206); | |
| setHeaderForResponse(res, "Content-Range", getValueContentRangeHeader("bytes", size, | |
| /** @type {import("range-parser").Ranges} */ | |
| parsedRanges[0])); | |
| [{ | |
| start, | |
| end | |
| }] = parsedRanges; | |
| } | |
| } | |
| const isFsSupportsStream = typeof context.outputFileSystem.createReadStream === "function"; | |
| let bufferOtStream; | |
| let byteLength; | |
| try { | |
| if (typeof start !== "undefined" && typeof end !== "undefined" && isFsSupportsStream) { | |
| bufferOtStream = | |
| /** @type {import("fs").createReadStream} */ | |
| context.outputFileSystem.createReadStream(filename, { | |
| start, | |
| end | |
| }); | |
| byteLength = end - start + 1; | |
| } else { | |
| bufferOtStream = | |
| /** @type {import("fs").readFileSync} */ | |
| context.outputFileSystem.readFileSync(filename); | |
| ({ | |
| byteLength | |
| } = bufferOtStream); | |
| } | |
| } catch (_ignoreError) { | |
| await goNext(); | |
| return; | |
| } | |
| send(req, res, bufferOtStream, byteLength); | |
| } | |
| }; | |
| } | |
| module.exports = wrapper; |
Xet Storage Details
- Size:
- 7.4 kB
- Xet hash:
- dbe3347c16279fa42e1e7c1e8e6a2fa79adb49bceb24254b984e959a2b18205c
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.