serveAndOpen sends JS, CSS and JSON as application/octet-stream
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- node.js, typescript
Research direction
Start in packages/cli/src/lib/serveAndOpen.ts at mimeTypeOfName() and its extname() lookup. Add regression checks through the actual server for JavaScript, CSS, JSON, source maps, unknown extensions, and the explicit HTML route. Done means recognized media types are returned for the listed extensions, unknown files keep the binary fallback, and HTML remains text/html.
Written by the indexing model from the issue text.
Description
Summary
The CLI's packaged serveAndOpen server sends JavaScript, CSS and JSON with
Content-Type: application/octet-stream. Its MIME table uses extension names without
a leading dot, but path.extname() returns dotted names. The HTML route supplies
text/html explicitly and is unaffected by this lookup.
Environment
- Official npm
@appland/appmap3.204.0, unmodified packaged server/assets. - Node 26.9.0, Linux; loopback HTTP server. Source inspection finds the same
lookup in the 3.196.1 release tag. - A separate Chromium 153.0.8010.47 observation also recorded these JS/CSS/JSON
media types. This report concerns the MIME lookup, not a claim that MIME alone
prevents script execution or explains other viewer failures.
Reproduction
In a disposable directory where the existing package is resolvable, save this as
mime-repro.cjs and run node mime-repro.cjs. It uses the genuine packaged server,
with no browser auto-open, response interception or installed-source modification.
The small JSON file is only a media-type fixture, not a rendering fixture.
const fs = require('node:fs');
const path = require('node:path');
const root = path.dirname(require.resolve('@appland/appmap/package.json'));
const serve = require(path.join(root, 'built/lib/serveAndOpen.js')).default;
fs.writeFileSync('mime-fixture.json', '{}\n');
serve('sequenceDiagram.html', {}, true, async (url) => {
const base = new URL(url);
base.hostname = '127.0.0.1';
try {
for (const name of ['/', '/sequenceDiagram.js', '/sequenceDiagram.css',
'/resource?mime-fixture.json']) {
const response = await fetch(new URL(name, base));
console.log(name, response.status, response.headers.get('content-type'));
await response.arrayBuffer();
}
process.exit(0);
} catch (error) {
console.error(error);
process.exit(1);
}
}, false);
Expected and actual
Observed on 3.204.0:
/ 200 text/html
/sequenceDiagram.js 200 application/octet-stream
/sequenceDiagram.css 200 application/octet-stream
/resource?mime-fixture.json 200 application/octet-stream
Expected: a recognized JavaScript media type for .js, text/css for .css, and
application/json for .json. Unknown extensions can retain the existing binary
fallback. The explicit HTML response should remain text/html.
Source analysis
In the 3.204.0 source,
mimeTypeOfName() indexes a table whose keys are js, css, json and map with
extname(filename). For sequenceDiagram.js, the returned key is .js, so the
lookup misses and selects the fallback. The resource route uses the same function.
The .map case has the same static mismatch; the observations above cover
JS/CSS/JSON rather than claiming an executed source-map check.
The same lookup is present in
3.196.1.
Suggested fix
Use dotted table keys while retaining the binary fallback for unknown extensions.
Add regression checks through the actual server for JS, CSS, JSON, source maps,
unknown extensions and the explicit HTML route. These are proposed owner-side
changes, not a workaround applied to the published artifact.
Related
#1597 and
#2362 concern absent packaged HTML;
#1399 concerns double-sent headers.
They appear related to serving/publication, but not this extension-key mismatch.
The shipped compiled viewer assets are present; this report does not claim all UI
assets are missing or that correcting MIME will fix an independent runtime exception.
- Dominant language
- TypeScript
- Stars
- 55
- Forks
- 18
- Avg merge
- 4d 8h
- Merged PRs (30d)
- 3
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from getappmap/appmap-js
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
-
Difficulty 4/5 3-5 days Newbie friendliness 58/100
-
secret-in-log is unreliable against sanitized gold tracesMay be free again @kgilpin claimed this 47 days ago, and no pull request is open. Open
-
Difficulty 3/5 1-2 days Newbie friendliness 38/100
All issues in getappmap/appmap-js
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
grafana/profiles-drilldown#1212 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
grafana/traces-drilldown#980 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
openremote/openremote#3487 · 1 comment ·
-
triage:needs-human
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
garrytan/gbrain#7635 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
coollabsio/jean#867 ·
Maintainers usually reply within 1 day