@adobe/aem-cli 16.0.7 → 16.0.8

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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [16.0.8](https://github.com/adobe/helix-cli/compare/v16.0.7...v16.0.8) (2023-11-17)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * don't respond when headers already sent ([#2278](https://github.com/adobe/helix-cli/issues/2278)) ([6be2f00](https://github.com/adobe/helix-cli/commit/6be2f00c9bf540433eb7836af7a1b7dcfbc174b4)), closes [#2276](https://github.com/adobe/helix-cli/issues/2276)
7
+
1
8
  ## [16.0.7](https://github.com/adobe/helix-cli/compare/v16.0.6...v16.0.7) (2023-11-16)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/aem-cli",
3
- "version": "16.0.7",
3
+ "version": "16.0.8",
4
4
  "description": "AEM CLI",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -74,7 +74,7 @@
74
74
  "yargs": "17.7.2"
75
75
  },
76
76
  "devDependencies": {
77
- "@adobe/eslint-config-helix": "2.0.4",
77
+ "@adobe/eslint-config-helix": "2.0.5",
78
78
  "@adobe/helix-shared-dom": "2.0.1",
79
79
  "@adobe/helix-testutils": "0.4.15",
80
80
  "@semantic-release/changelog": "6.0.3",
@@ -42,6 +42,7 @@ export class HelixServer extends BaseServer {
42
42
  async handleProxyModeRequest(req, res) {
43
43
  const sendFile = promisify(res.sendFile).bind(res);
44
44
  const ctx = new RequestContext(req, this._project);
45
+ const { id } = ctx;
45
46
  const { log } = this;
46
47
  const proxyUrl = new URL(this._project.proxyUrl);
47
48
 
@@ -56,10 +57,19 @@ export class HelixServer extends BaseServer {
56
57
  if (liveReload) {
57
58
  liveReload.startRequest(ctx.requestId, ctx.path);
58
59
  }
60
+ const pfx = log.level === 'silly' ? `[${id}] ` : '';
61
+
62
+ if (log.level === 'silly') {
63
+ log.trace(`${pfx}>>>--------------------------`);
64
+ log.trace(`${pfx}> ${req.method} ${req.url}`);
65
+ Object.entries(req.headers).forEach(([name, value]) => {
66
+ log.trace(`${pfx}> ${name}: ${value}`);
67
+ });
68
+ log.trace(`[${id}]`);
69
+ }
59
70
 
60
71
  // try to serve static
61
72
  try {
62
- log.debug('trying to serve local file', filePath);
63
73
  await sendFile(filePath, {
64
74
  dotfiles: 'allow',
65
75
  headers: {
@@ -69,9 +79,13 @@ export class HelixServer extends BaseServer {
69
79
  if (liveReload) {
70
80
  liveReload.registerFile(ctx.requestId, filePath);
71
81
  }
82
+ log.debug(`${pfx}served local file ${filePath}`);
72
83
  return;
73
84
  } catch (e) {
74
- log.debug(`Error while delivering resource ${ctx.path} - ${e.stack || e}`);
85
+ log.debug(`${pfx}unable to deliver local file ${ctx.path} - ${e.stack || e}`);
86
+ if (res.headersSent) {
87
+ return;
88
+ }
75
89
  } finally {
76
90
  if (liveReload) {
77
91
  liveReload.endRequest(ctx.requestId);
@@ -92,7 +106,7 @@ export class HelixServer extends BaseServer {
92
106
  file404html: this._project.file404html,
93
107
  });
94
108
  } catch (err) {
95
- log.error(`Failed to proxy AEM request ${ctx.path}: ${err.message}`);
109
+ log.error(`${pfx}failed to proxy AEM request ${ctx.path}: ${err.message}`);
96
110
  res.status(502).send(`Failed to proxy AEM request: ${err.message}`);
97
111
  }
98
112
 
@@ -12,6 +12,8 @@
12
12
  import { parse } from 'url';
13
13
  import utils from './utils.js';
14
14
 
15
+ let id = 0;
16
+
15
17
  /**
16
18
  * Context that is used during request handling.
17
19
  *
@@ -26,6 +28,8 @@ export default class RequestContext {
26
28
  const { url } = req;
27
29
  this._cfg = cfg || {};
28
30
  this._url = url;
31
+ // eslint-disable-next-line no-plusplus
32
+ this._id = id++;
29
33
  const purl = parse(url);
30
34
  this._path = purl.pathname || '/';
31
35
  this._queryString = purl.search || '';
@@ -74,6 +78,14 @@ export default class RequestContext {
74
78
  this._resourcePath = relPath;
75
79
  }
76
80
 
81
+ /**
82
+ * returns the request id / counter
83
+ * @return {*|number}
84
+ */
85
+ get id() {
86
+ return this._id;
87
+ }
88
+
77
89
  /**
78
90
  * the original request url
79
91
  */
@@ -215,7 +215,8 @@ window.LiveReloadOptions = {
215
215
  * @return {Promise} A promise that resolves when the stream is done.
216
216
  */
217
217
  async proxyRequest(ctx, url, req, res, opts = {}) {
218
- ctx.log.debug(`Proxy ${req.method} request to ${url}`);
218
+ const { id } = ctx;
219
+ ctx.log.debug(`[${id}] Proxy ${req.method} request to ${url}`);
219
220
 
220
221
  if (opts.cacheDirectory) {
221
222
  const cached = await utils.getFromCache(url, opts.cacheDirectory, ctx.log);
@@ -263,7 +264,7 @@ window.LiveReloadOptions = {
263
264
  });
264
265
  const contentType = ret.headers.get('content-type') || 'text/plain';
265
266
  const level = utils.status2level(ret.status, true);
266
- ctx.log[level](`Proxy ${req.method} request to ${url}: ${ret.status} (${contentType})`);
267
+ ctx.log[level](`[${id}] Proxy ${req.method} request to ${url}: ${ret.status} (${contentType})`);
267
268
 
268
269
  // because fetch decodes the response, we need to reset content encoding and length
269
270
  const respHeaders = Object.fromEntries(ret.headers.entries());
@@ -271,11 +272,12 @@ window.LiveReloadOptions = {
271
272
  delete respHeaders['content-length'];
272
273
  delete respHeaders['x-frame-options'];
273
274
  delete respHeaders['content-security-policy'];
275
+ delete respHeaders.connection;
274
276
  respHeaders['access-control-allow-origin'] = '*';
275
277
  respHeaders.via = `${ret.httpVersion ?? '1.0'} ${new URL(url).hostname}`;
276
278
 
277
279
  if (ret.status === 404 && contentType.indexOf('text/html') === 0 && opts.file404html) {
278
- ctx.log.debug('serve local 404.html', opts.file404html);
280
+ ctx.log.debug(`[${id}] serve local 404.html ${opts.file404html}`);
279
281
  let textBody = await fs.readFile(opts.file404html, 'utf-8');
280
282
  if (opts.injectLiveReload) {
281
283
  textBody = utils.injectLiveReloadScript(textBody, ctx.config.server);
@@ -292,34 +294,19 @@ window.LiveReloadOptions = {
292
294
  const replaceHead = isHTML && opts.headHtml;
293
295
  const doIndex = isHTML && opts.indexer && url.indexOf('.plain.html') < 0;
294
296
 
297
+ if (ctx.log.level === 'silly') {
298
+ ctx.log.trace(`[${id}] -----------------------------`);
299
+ ctx.log.trace(`[${id}] < http/${ret.httpVersion} ${ret.status} ${ret.statusText}`);
300
+ Object.entries(ret.headers.raw()).forEach(([name, value]) => {
301
+ ctx.log.trace(`[${id}] < ${name}: ${value}`);
302
+ });
303
+ }
304
+
295
305
  if (isHTML) {
296
- let respBody;
297
- let textBody;
298
- if (contentType.startsWith('text/')) {
299
- textBody = await ret.text();
300
- } else {
301
- respBody = await ret.buffer();
302
- }
303
- const lines = ['----------------------------->'];
306
+ let textBody = await ret.text();
304
307
  if (ctx.log.level === 'silly') {
305
- lines.push(`${req.method} ${url}`);
306
- Object.entries(headers).forEach(([name, value]) => {
307
- lines.push(`${name}: ${value}`);
308
- });
309
- lines.push('');
310
- lines.push('<-----------------------------');
311
- lines.push('');
312
- lines.push(`http/${ret.httpVersion} ${ret.status} ${ret.statusText}`);
313
- ret.headers.forEach((name, value) => {
314
- lines.push(`${name}: ${value}`);
315
- });
316
- lines.push('');
317
- if (respBody) {
318
- lines.push(`<binary ${respBody.length} bytes>`);
319
- } else {
320
- lines.push(textBody);
321
- }
322
- ctx.log.trace(lines.join('\n'));
308
+ ctx.log.trace(textBody);
309
+ ctx.log.trace(`[${id}] <<<--------------------------`);
323
310
  }
324
311
  if (replaceHead) {
325
312
  await opts.headHtml.setCookie(req.headers.cookie);
@@ -344,7 +331,7 @@ window.LiveReloadOptions = {
344
331
  url,
345
332
  opts.cacheDirectory,
346
333
  {
347
- body: respBody || textBody,
334
+ body: textBody,
348
335
  headers: respHeaders,
349
336
  status: ret.status,
350
337
  },
@@ -353,12 +340,16 @@ window.LiveReloadOptions = {
353
340
  }
354
341
 
355
342
  res
356
- .status(ret.status)
357
343
  .set(respHeaders)
358
- .send(respBody || textBody);
344
+ .status(ret.status)
345
+ .send(textBody);
359
346
  return;
360
347
  }
361
348
 
349
+ if (ctx.log.level === 'silly') {
350
+ ctx.log.trace(`[${id}] <<<--------------------------`);
351
+ }
352
+
362
353
  if (opts.cacheDirectory) {
363
354
  const buffer = await ret.buffer();
364
355
  await utils.writeToCache(