expressjs / expressjs/express

res.set('Content-Type') silently sets header to literal string 'false' for unknown types

Open
#7,034 5 comments 0 reactions 1 assignee Claimed by @blakeembrey View on GitHub
discuss
Dominant language
JavaScript
Stars
69.5k
Forks
25k
Avg merge
4d 20h
Merged PRs (30d)
9

Description

When calling `res.set('Content-Type', value)` where the value doesn't contain a `/` (like a bare extension or shorthand), `mime.contentType(value)` is used to resolve the full MIME type. However, if `mime.contentType()` returns `false` (for unrecognized types), the Content-Type header is set to the literal string `"false"` instead of keeping the original value.

**Reproduction:**

```js
const express = require('express');
const app = express();

app.get('/', (req, res) => {
res.set('Content-Type', 'some-custom-type');
res.send('hello');
});

app.listen(3000);
```

Requesting `/` returns `Content-Type: false` in the response headers.

**Root cause:**

In `res.set()` (response.js), the Content-Type branch does:

```js
if (field.toLowerCase() === 'content-type') {
if (Array.isArray(value)) {
throw new TypeError('Content-Type cannot be set to an Array');
}
value = mime.contentType(value) // can return false!
}
this.setHeader(field, value);
```

When `mime.contentType(value)` returns `false`, the value `false` is passed to `setHeader`, which coerces it to the string `"false"`.

Contrast with `res.type()` which handles this correctly:
```js
var ct = type.indexOf('/') === -1
? (mime.contentType(type) || 'application/octet-stream')
: type;
```

**Expected behavior:**

When `mime.contentType()` returns `false`, `res.set` should fall back to the original string value rather than setting the header to `"false"`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.