orator-static-server 2.0.1 → 2.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orator-static-server",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "Static file serving for Orator API servers.",
5
5
  "main": "source/Orator-Static-Server.js",
6
6
  "scripts": {
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "devDependencies": {
47
47
  "chai": "^4.3.7",
48
- "fable": "^3.1.55",
48
+ "fable": "^3.1.57",
49
49
  "mocha": "^10.2.0",
50
50
  "orator": "^6.0.1",
51
51
  "orator-serviceserver-restify": "^2.0.7",
@@ -161,15 +161,12 @@ class OratorStaticServer extends libFableServiceProviderBase
161
161
  return pRequest.url;
162
162
  };
163
163
 
164
- // When the URL is a directory (e.g. '/' or '/docs/'), use the default file for MIME detection
165
- // so the browser gets text/html instead of application/octet-stream
166
- let tmpMimeTarget = pRequest.url;
167
- if (tmpMimeTarget.endsWith('/') || tmpMimeTarget.indexOf('.') < 0)
168
- {
169
- tmpMimeTarget = tmpDefaultFile;
170
- }
171
- this.setMimeHeader(tmpMimeTarget, pResponse);
172
-
164
+ // Let serve-static handle Content-Type detection. It resolves
165
+ // the actual file path first (e.g. / → /index.html) and then
166
+ // sets the correct MIME type with charset. Pre-setting the
167
+ // header here would prevent serve-static from overriding it
168
+ // because the underlying `send` library skips Content-Type
169
+ // when the header is already present.
173
170
  const tmpServe = libServeStatic(servePath, Object.assign({ index: tmpDefaultFile }, pParams));
174
171
  tmpServe(pRequest, pResponse, libFinalHandler(pRequest, pResponse));
175
172
  // TODO: This may break things if a post request send handler is setup...
@@ -1308,6 +1308,175 @@ suite
1308
1308
  }
1309
1309
  );
1310
1310
 
1311
+ suite
1312
+ (
1313
+ 'MIME Type Resolution by serve-static',
1314
+ () =>
1315
+ {
1316
+ test
1317
+ (
1318
+ 'serve-static should set content-type with charset for HTML files',
1319
+ (fDone) =>
1320
+ {
1321
+ let tmpPort = getNextTestPort();
1322
+ let tmpHarness = createHarness(tmpPort);
1323
+
1324
+ startHarness(tmpHarness,
1325
+ (pError) =>
1326
+ {
1327
+ tmpHarness.orator.addStaticRoute(_StaticContentPath, 'index.html', '/mime/*', '/mime/');
1328
+
1329
+ makeRequest(tmpPort, '/mime/index.html',
1330
+ (pError, pStatusCode, pHeaders, pBody) =>
1331
+ {
1332
+ Expect(pError).to.equal(null);
1333
+ Expect(pStatusCode).to.equal(200);
1334
+ // serve-static sets charset on text types; a manual setMimeHeader would not
1335
+ Expect(pHeaders['content-type']).to.equal('text/html; charset=UTF-8');
1336
+ tmpHarness.orator.log.info(`HTML content-type with charset: ${pHeaders['content-type']}`);
1337
+ tmpHarness.orator.stopService(
1338
+ () =>
1339
+ {
1340
+ return fDone();
1341
+ });
1342
+ });
1343
+ });
1344
+ }
1345
+ );
1346
+
1347
+ test
1348
+ (
1349
+ 'serve-static should set content-type with charset for CSS files',
1350
+ (fDone) =>
1351
+ {
1352
+ let tmpPort = getNextTestPort();
1353
+ let tmpHarness = createHarness(tmpPort);
1354
+
1355
+ startHarness(tmpHarness,
1356
+ (pError) =>
1357
+ {
1358
+ tmpHarness.orator.addStaticRoute(_StaticContentPath, 'index.html', '/mimecss/*', '/mimecss/');
1359
+
1360
+ makeRequest(tmpPort, '/mimecss/style.css',
1361
+ (pError, pStatusCode, pHeaders, pBody) =>
1362
+ {
1363
+ Expect(pError).to.equal(null);
1364
+ Expect(pStatusCode).to.equal(200);
1365
+ // serve-static adds charset for text/* types
1366
+ Expect(pHeaders['content-type']).to.equal('text/css; charset=UTF-8');
1367
+ tmpHarness.orator.log.info(`CSS content-type with charset: ${pHeaders['content-type']}`);
1368
+ tmpHarness.orator.stopService(
1369
+ () =>
1370
+ {
1371
+ return fDone();
1372
+ });
1373
+ });
1374
+ });
1375
+ }
1376
+ );
1377
+
1378
+ test
1379
+ (
1380
+ 'directory request to / should get text/html from serve-static not application/octet-stream',
1381
+ (fDone) =>
1382
+ {
1383
+ let tmpPort = getNextTestPort();
1384
+ let tmpHarness = createHarness(tmpPort);
1385
+
1386
+ startHarness(tmpHarness,
1387
+ (pError) =>
1388
+ {
1389
+ tmpHarness.orator.addStaticRoute(_StaticContentPath, 'index.html', '/*', '/');
1390
+
1391
+ makeRequest(tmpPort, '/',
1392
+ (pError, pStatusCode, pHeaders, pBody) =>
1393
+ {
1394
+ Expect(pError).to.equal(null);
1395
+ Expect(pStatusCode).to.equal(200);
1396
+ // The core bug: mime.getType('/') returns null, falling back to
1397
+ // application/octet-stream. serve-static resolves / to /index.html
1398
+ // and correctly determines text/html with charset.
1399
+ Expect(pHeaders['content-type']).to.equal('text/html; charset=UTF-8');
1400
+ Expect(pHeaders['content-type']).to.not.contain('octet-stream');
1401
+ Expect(pBody).to.contain('Test Index');
1402
+ tmpHarness.orator.log.info(`Root / content-type: ${pHeaders['content-type']}`);
1403
+ tmpHarness.orator.stopService(
1404
+ () =>
1405
+ {
1406
+ return fDone();
1407
+ });
1408
+ });
1409
+ });
1410
+ }
1411
+ );
1412
+
1413
+ test
1414
+ (
1415
+ 'directory request to /subdir/ should get text/html from serve-static',
1416
+ (fDone) =>
1417
+ {
1418
+ let tmpPort = getNextTestPort();
1419
+ let tmpHarness = createHarness(tmpPort);
1420
+
1421
+ startHarness(tmpHarness,
1422
+ (pError) =>
1423
+ {
1424
+ tmpHarness.orator.addStaticRoute(_StaticContentPath, 'index.html', '/app/*', '/app/');
1425
+
1426
+ makeRequest(tmpPort, '/app/subsite/',
1427
+ (pError, pStatusCode, pHeaders, pBody) =>
1428
+ {
1429
+ Expect(pError).to.equal(null);
1430
+ Expect(pStatusCode).to.equal(200);
1431
+ // serve-static resolves /subsite/ to /subsite/index.html
1432
+ Expect(pHeaders['content-type']).to.equal('text/html; charset=UTF-8');
1433
+ Expect(pBody).to.contain('Subsite');
1434
+ tmpHarness.orator.log.info(`Subdir / content-type: ${pHeaders['content-type']}`);
1435
+ tmpHarness.orator.stopService(
1436
+ () =>
1437
+ {
1438
+ return fDone();
1439
+ });
1440
+ });
1441
+ });
1442
+ }
1443
+ );
1444
+
1445
+ test
1446
+ (
1447
+ 'JSON file should get application/json content-type from serve-static',
1448
+ (fDone) =>
1449
+ {
1450
+ let tmpPort = getNextTestPort();
1451
+ let tmpHarness = createHarness(tmpPort);
1452
+
1453
+ startHarness(tmpHarness,
1454
+ (pError) =>
1455
+ {
1456
+ tmpHarness.orator.addStaticRoute(_StaticContentPath, 'index.html', '/mj/*', '/mj/');
1457
+
1458
+ makeRequest(tmpPort, '/mj/data.json',
1459
+ (pError, pStatusCode, pHeaders, pBody) =>
1460
+ {
1461
+ Expect(pError).to.equal(null);
1462
+ Expect(pStatusCode).to.equal(200);
1463
+ // JSON should not have charset added by serve-static
1464
+ Expect(pHeaders['content-type']).to.contain('application/json');
1465
+ let tmpParsed = JSON.parse(pBody);
1466
+ Expect(tmpParsed.TestKey).to.equal('TestValue');
1467
+ tmpHarness.orator.log.info(`JSON content-type: ${pHeaders['content-type']}`);
1468
+ tmpHarness.orator.stopService(
1469
+ () =>
1470
+ {
1471
+ return fDone();
1472
+ });
1473
+ });
1474
+ });
1475
+ }
1476
+ );
1477
+ }
1478
+ );
1479
+
1311
1480
  suite
1312
1481
  (
1313
1482
  'addStaticRoute Parameter Defaults',