-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrest.js
More file actions
60 lines (56 loc) · 2.46 KB
/
rest.js
File metadata and controls
60 lines (56 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
* Detects multiple MIME types smuggled into a single Content-Type header.
* The following are the cases that should result in a 415 (not a 500)
- application/json text/plain
- application/json, text/plain
- text/plain; application/json
- text/plain; a=b, application/json
- application/json; a=b; text/plain;
- application/json; a=b text/plain;
- application/json; charset=utf-8, text/plain
- application/json;
* @param {string} contentType - Lowercased Content-Type header value
* @returns {boolean} True if multiple MIME types are detected
*/
const hasMultipleContentTypes = (contentType) => {
const segments = contentType.split(";")
const mimeSegment = segments[0].trim()
// No commas or spaces allowed in MIME types
if (mimeSegment.includes(",") || mimeSegment.includes(" ")) return true
// Parameter values are tokens (no spaces/commas) or quoted strings per RFC 2045.
// Commas or spaces outside quotes indicate a smuggled MIME type.
return segments.slice(1).some(segment => {
const trimmed = segment.trim()
if (!trimmed.includes("=")) return true
const withoutQuoted = trimmed.replace(/"[^"]*"/g, "")
if (withoutQuoted.includes(",") || withoutQuoted.includes(" ")) return true
return false
})
}
/**
* Middleware to verify Content-Type headers for endpoints receiving JSON bodies.
* Responds with a 415 Invalid Media Type for Content-Type headers that are not for JSON bodies.
*
* @param {Object} req - Express request object
* @param {Object} res - Express response object
* @param {Function} next - Express next middleware function
*/
const verifyJsonContentType = function (req, res, next) {
const contentType = (req.get("Content-Type") ?? "").toLowerCase()
const mimeType = contentType.split(";")[0].trim()
if (!mimeType) {
const err = new Error(`Missing or empty Content-Type header.`)
err.status = 415
return next(err)
}
if (hasMultipleContentTypes(contentType)) {
const err = new Error(`Multiple Content-Type values are not allowed. Provide exactly one Content-Type header.`)
err.status = 415
return next(err)
}
if (mimeType === "application/json" || mimeType === "application/ld+json") return next()
const err = new Error(`Unsupported Content-Type: ${contentType}. This endpoint requires application/json or application/ld+json.`)
err.status = 415
return next(err)
}
export default { verifyJsonContentType }