source: frontend/node_modules/webpack-dev-middleware/dist/utils/getFilenameFromUrl.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 4.6 KB
RevLine 
[9af201e]1"use strict";
2
3const path = require("path");
4
5const {
6 parse
7} = require("url");
8
9const querystring = require("querystring");
10
11const getPaths = require("./getPaths");
12/** @typedef {import("../index.js").IncomingMessage} IncomingMessage */
13
14/** @typedef {import("../index.js").ServerResponse} ServerResponse */
15
16
17const cacheStore = new WeakMap();
18/**
19 * @template T
20 * @param {Function} fn
21 * @param {{ cache?: Map<string, { data: T }> } | undefined} cache
22 * @param {(value: T) => T} callback
23 * @returns {any}
24 */
25// @ts-ignore
26
27const mem = (fn, {
28 cache = new Map()
29} = {}, callback) => {
30 /**
31 * @param {any} arguments_
32 * @return {any}
33 */
34 const memoized = (...arguments_) => {
35 const [key] = arguments_;
36 const cacheItem = cache.get(key);
37
38 if (cacheItem) {
39 return cacheItem.data;
40 }
41
42 let result = fn.apply(void 0, arguments_);
43 result = callback(result);
44 cache.set(key, {
45 data: result
46 });
47 return result;
48 };
49
50 cacheStore.set(memoized, cache);
51 return memoized;
52}; // eslint-disable-next-line no-undefined
53
54
55const memoizedParse = mem(parse, undefined, value => {
56 if (value.pathname) {
57 // eslint-disable-next-line no-param-reassign
58 value.pathname = decode(value.pathname);
59 }
60
61 return value;
62});
63const UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/;
64/**
65 * @typedef {Object} Extra
66 * @property {import("fs").Stats=} stats
67 * @property {number=} errorCode
68 */
69
70/**
71 * decodeURIComponent.
72 *
73 * Allows V8 to only deoptimize this fn instead of all of send().
74 *
75 * @param {string} input
76 * @returns {string}
77 */
78
79function decode(input) {
80 return querystring.unescape(input);
81}
82/**
83 * @template {IncomingMessage} Request
84 * @template {ServerResponse} Response
85 * @param {import("../index.js").Context<Request, Response>} context
86 * @param {string} url
87 * @param {Extra=} extra
88 * @returns {string | undefined}
89 */
90
91
92function getFilenameFromUrl(context, url, extra = {}) {
93 const {
94 options
95 } = context;
96 const paths = getPaths(context);
97 /** @type {string | undefined} */
98
99 let foundFilename;
100 /** @type {URL} */
101
102 let urlObject;
103
104 try {
105 // The `url` property of the `request` is contains only `pathname`, `search` and `hash`
106 urlObject = memoizedParse(url, false, true);
107 } catch (_ignoreError) {
108 return;
109 }
110
111 for (const {
112 publicPath,
113 outputPath
114 } of paths) {
115 /** @type {string | undefined} */
116 let filename;
117 /** @type {URL} */
118
119 let publicPathObject;
120
121 try {
122 publicPathObject = memoizedParse(publicPath !== "auto" && publicPath ? publicPath : "/", false, true);
123 } catch (_ignoreError) {
124 // eslint-disable-next-line no-continue
125 continue;
126 }
127
128 const {
129 pathname
130 } = urlObject;
131 const {
132 pathname: publicPathPathname
133 } = publicPathObject;
134
135 if (pathname && pathname.startsWith(publicPathPathname)) {
136 // Null byte(s)
137 if (pathname.includes("\0")) {
138 // eslint-disable-next-line no-param-reassign
139 extra.errorCode = 400;
140 return;
141 } // ".." is malicious
142
143
144 if (UP_PATH_REGEXP.test(path.normalize(`./${pathname}`))) {
145 // eslint-disable-next-line no-param-reassign
146 extra.errorCode = 403;
147 return;
148 } // Strip the `pathname` property from the `publicPath` option from the start of requested url
149 // `/complex/foo.js` => `foo.js`
150 // and add outputPath
151 // `foo.js` => `/home/user/my-project/dist/foo.js`
152
153
154 filename = path.join(outputPath, pathname.slice(publicPathPathname.length));
155
156 try {
157 // eslint-disable-next-line no-param-reassign
158 extra.stats =
159 /** @type {import("fs").statSync} */
160 context.outputFileSystem.statSync(filename);
161 } catch (_ignoreError) {
162 // eslint-disable-next-line no-continue
163 continue;
164 }
165
166 if (extra.stats.isFile()) {
167 foundFilename = filename;
168 break;
169 } else if (extra.stats.isDirectory() && (typeof options.index === "undefined" || options.index)) {
170 const indexValue = typeof options.index === "undefined" || typeof options.index === "boolean" ? "index.html" : options.index;
171 filename = path.join(filename, indexValue);
172
173 try {
174 // eslint-disable-next-line no-param-reassign
175 extra.stats =
176 /** @type {import("fs").statSync} */
177 context.outputFileSystem.statSync(filename);
178 } catch (__ignoreError) {
179 // eslint-disable-next-line no-continue
180 continue;
181 }
182
183 if (extra.stats.isFile()) {
184 foundFilename = filename;
185 break;
186 }
187 }
188 }
189 } // eslint-disable-next-line consistent-return
190
191
192 return foundFilename;
193}
194
195module.exports = getFilenameFromUrl;
Note: See TracBrowser for help on using the repository browser.