@nestjs/platform-fastify 12.1.1 → 12.1.2

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.
@@ -8,6 +8,7 @@ import middie from '@fastify/middie';
8
8
  import { loadPackage, tryLoadPackage, isNil, isString, isUndefined, } from '@nestjs/common/internal';
9
9
  import { AbstractHttpAdapter } from '@nestjs/core';
10
10
  import { LegacyRouteConverter } from '@nestjs/core/internal';
11
+ import { getMediaTypeVersion } from './utils/get-media-type-version.util.js';
11
12
  const { kRouteContext } = fastifySymbols;
12
13
  // Fastify uses `fast-querystring` internally to quickly parse URL query strings.
13
14
  import { parse as querystringParse } from 'fast-querystring';
@@ -22,6 +23,12 @@ function isFastifyMultipartPlugin(plugin) {
22
23
  (fn[Symbol.for('plugin-meta')]?.name === '@fastify/multipart' ||
23
24
  fn.name === 'fastifyMultipart'));
24
25
  }
26
+ // Covers "application/json" and the "+json" structured syntax suffix (RFC 6839),
27
+ // e.g. "application/problem+json", with or without parameters.
28
+ function isJsonContentType(contentType) {
29
+ const mediaType = contentType.split(';')[0].trim().toLowerCase();
30
+ return (mediaType.startsWith('application/json') || mediaType.endsWith('+json'));
31
+ }
25
32
  /**
26
33
  * @publicApi
27
34
  */
@@ -79,13 +86,12 @@ export class FastifyAdapter extends AbstractHttpAdapter {
79
86
  // Media Type (Accept Header) Versioning Handler
80
87
  if (this.versioningOptions?.type === VersioningType.MEDIA_TYPE) {
81
88
  const MEDIA_TYPE_HEADER = 'Accept';
82
- const acceptHeaderValue = (req.headers?.[MEDIA_TYPE_HEADER] || req.headers?.[MEDIA_TYPE_HEADER.toLowerCase()]);
83
- const acceptHeaderVersionParameter = acceptHeaderValue
84
- ? acceptHeaderValue.split(';')[1]
85
- : undefined;
86
- return isUndefined(acceptHeaderVersionParameter)
89
+ const acceptHeaderValue = req.headers?.[MEDIA_TYPE_HEADER] ||
90
+ req.headers?.[MEDIA_TYPE_HEADER.toLowerCase()];
91
+ const headerVersion = getMediaTypeVersion(acceptHeaderValue, this.versioningOptions.key);
92
+ return isUndefined(headerVersion)
87
93
  ? VERSION_NEUTRAL // No version was supplied
88
- : acceptHeaderVersionParameter.split(this.versioningOptions.key)[1];
94
+ : headerVersion;
89
95
  }
90
96
  // Header Versioning Handler
91
97
  else if (this.versioningOptions?.type === VersioningType.HEADER) {
@@ -282,7 +288,7 @@ export class FastifyAdapter extends AbstractHttpAdapter {
282
288
  }
283
289
  const responseContentType = fastifyReply.getHeader('Content-Type');
284
290
  if (typeof responseContentType === 'string' &&
285
- !responseContentType.startsWith('application/json') &&
291
+ !isJsonContentType(responseContentType) &&
286
292
  body?.statusCode >= HttpStatus.BAD_REQUEST) {
287
293
  Logger.warn("Content-Type doesn't match Reply body, you might need a custom ExceptionFilter for non-JSON responses", FastifyAdapter.name);
288
294
  fastifyReply.header('Content-Type', 'application/json');
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Returns the version carried by an `Accept` header for media type versioning,
3
+ * e.g. `2` for `application/json;v=2` with the `v=` key.
4
+ *
5
+ * The version parameter may follow other parameters and may belong to any
6
+ * media range of a list (`text/html, application/json;v=2`); the first match
7
+ * wins. Returns `undefined` when no parameter starts with the key.
8
+ *
9
+ * Duplicated in each platform package so that a platform package never
10
+ * depends on a newer `@nestjs/core` than the one installed.
11
+ */
12
+ export declare function getMediaTypeVersion(acceptHeader: string | string[] | undefined, key: string): string | undefined;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Returns the version carried by an `Accept` header for media type versioning,
3
+ * e.g. `2` for `application/json;v=2` with the `v=` key.
4
+ *
5
+ * The version parameter may follow other parameters and may belong to any
6
+ * media range of a list (`text/html, application/json;v=2`); the first match
7
+ * wins. Returns `undefined` when no parameter starts with the key.
8
+ *
9
+ * Duplicated in each platform package so that a platform package never
10
+ * depends on a newer `@nestjs/core` than the one installed.
11
+ */
12
+ export function getMediaTypeVersion(acceptHeader, key) {
13
+ const mediaRanges = []
14
+ .concat(acceptHeader ?? [])
15
+ .flatMap(value => value.split(','));
16
+ for (const mediaRange of mediaRanges) {
17
+ const [, ...parameters] = mediaRange.split(';');
18
+ for (const parameter of parameters) {
19
+ const trimmedParameter = parameter.trim();
20
+ if (trimmedParameter.startsWith(key)) {
21
+ return trimmedParameter.slice(key.length);
22
+ }
23
+ }
24
+ }
25
+ return undefined;
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/platform-fastify",
3
- "version": "12.1.1",
3
+ "version": "12.1.2",
4
4
  "description": "Nest - modern, fast, powerful node.js web framework (@platform-fastify)",
5
5
  "author": "Kamil Mysliwiec",
6
6
  "license": "MIT",
@@ -54,5 +54,5 @@
54
54
  "optional": true
55
55
  }
56
56
  },
57
- "gitHead": "9feedffde8ef8c86f0cd521153740575dc579d88"
57
+ "gitHead": "8ab60aa1b2927fbe0e23135ffc65d610c623236a"
58
58
  }