diff --git a/content/controllers.md b/content/controllers.md
index 0bc1cec08a..8ac6cc6add 100644
--- a/content/controllers.md
+++ b/content/controllers.md
@@ -102,7 +102,7 @@ export class CatsController {
> info **Hint** To take advantage of `express` typings (like in the `request: Request` parameter example above), make sure to install the `@types/express` package.
-The request object represents the HTTP request and contains properties for the query string, parameters, HTTP headers, and body (read more [here](https://expressjs.com/en/api.html#req)). In most cases, you don't need to manually access these properties. Instead, you can use dedicated decorators like `@Body()` or `@Query()`, which are available out of the box. Below is a list of the provided decorators and the corresponding platform-specific objects they represent.
+The request object represents the HTTP request and contains properties for the query string, parameters, HTTP headers, and body (read more [here](https://expressjs.com/en/api.html#req)). In most cases, you don't need to manually access these properties. Instead, you can use dedicated decorators like `@Body()` or `@QueryString()`, which are available out of the box. Below is a list of the provided **parameter** decorators and the corresponding platform-specific objects they represent.
@@ -130,7 +130,7 @@ The request object represents the HTTP request and contains properties for the q
req.body / req.body[key]
-
@Query(key?: string)
+
@QueryString(key?: string)
req.query / req.query[key]
@@ -189,7 +189,18 @@ export class CatsController {
}
```
-It's that simple. Nest provides decorators for all of the standard HTTP methods: `@Get()`, `@Post()`, `@Put()`, `@Delete()`, `@Patch()`, `@Options()`, and `@Head()`. In addition, `@All()` defines an endpoint that handles all of them.
+It's that simple. Nest provides decorators for all of the standard HTTP methods: `@Get()`, `@Post()`, `@Put()`, `@Delete()`, `@Patch()`, `@Options()`, and `@Head()`. Nest also provides `@Query()` and `@Search()` for the corresponding HTTP methods. In addition, `@All()` defines an endpoint that handles all of them.
+
+```typescript
+@Query('search')
+find(@Body() filters: SearchDto) {
+ return this.service.search(filters);
+}
+```
+
+> info **Hint** The HTTP `QUERY` method is safe and idempotent and carries a request body; use `@Body()` for the payload (not `@QueryString()`). Runtime support depends on Node.js including `QUERY` in `http.METHODS` (typically `>=20.19.3 <21` or `>=22.2.0`). Express 5 (the default via `@nestjs/platform-express`) exposes `app.query` when Node includes `QUERY`; the Fastify adapter registers the verb via `query(...)`. Client and proxy support may vary.
+
+> warning **Warning** Do not confuse the `@Query()` **method** decorator (HTTP `QUERY` routes) with `@QueryString()`, the **parameter** decorator that extracts URL query string values from `req.query`.
#### Route wildcards
@@ -256,7 +267,7 @@ Returned values will override any arguments passed to the `@Redirect()` decorato
```typescript
@Get('docs')
@Redirect('https://docs.nestjs.com', 302)
-getDocs(@Query('version') version) {
+getDocs(@QueryString('version') version) {
if (version && version === '5') {
return { url: 'https://docs.nestjs.com/v5/' };
}
@@ -408,19 +419,21 @@ async create(createCatDto) {
#### Query parameters
-When handling query parameters in your routes, you can use the `@Query()` decorator to extract them from incoming requests. Let's see how this works in practice.
+When handling query parameters in your routes, you can use the `@QueryString()` decorator to extract them from incoming requests. Let's see how this works in practice.
+
+> warning **Warning** Previously this was `@Query()`. That name is now reserved for the HTTP `QUERY` **method** decorator. Use `@QueryString()` to read `req.query`.
Consider a route where we want to filter a list of cats based on query parameters like `age` and `breed`. First, define the query parameters in the `CatsController`:
```typescript
@@filename(cats.controller)
@Get()
-async findAll(@Query('age') age: number, @Query('breed') breed: string) {
+async findAll(@QueryString('age') age: number, @QueryString('breed') breed: string) {
return `This action returns all cats filtered by age: ${age} and breed: ${breed}`;
}
```
-In this example, the `@Query()` decorator is used to extract the values of `age` and `breed` from the query string. For example, a request to:
+In this example, the `@QueryString()` decorator is used to extract the values of `age` and `breed` from the query string. For example, a request to:
```plaintext
GET /cats?age=2&breed=Persian
@@ -465,7 +478,7 @@ Below is an example that demonstrates the use of several available decorators to
```typescript
@@filename(cats.controller)
-import { Controller, Get, Query, Post, Body, Put, Param, Delete } from '@nestjs/common';
+import { Controller, Get, QueryString, Post, Body, Put, Param, Delete } from '@nestjs/common';
import { CreateCatDto, UpdateCatDto, ListAllEntities } from './dto';
@Controller('cats')
@@ -476,7 +489,7 @@ export class CatsController {
}
@Get()
- findAll(@Query() query: ListAllEntities) {
+ findAll(@QueryString() query: ListAllEntities) {
return `This action returns all cats (limit: ${query.limit} items)`;
}
@@ -496,7 +509,7 @@ export class CatsController {
}
}
@@switch
-import { Controller, Get, Query, Post, Body, Put, Param, Delete, Bind } from '@nestjs/common';
+import { Controller, Get, QueryString, Post, Body, Put, Param, Delete, Bind } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@@ -507,7 +520,7 @@ export class CatsController {
}
@Get()
- @Bind(Query())
+ @Bind(QueryString())
findAll(query) {
console.log(query);
return `This action returns all cats (limit: ${query.limit} items)`;
diff --git a/content/custom-decorators.md b/content/custom-decorators.md
index 31bec3fdf5..4ae034b6ad 100644
--- a/content/custom-decorators.md
+++ b/content/custom-decorators.md
@@ -39,7 +39,7 @@ Nest provides a set of useful **param decorators** that you can use together wit
req.body / req.body[param]
-
@Query(param?: string)
+
@QueryString(param?: string)
req.query / req.query[param]
@@ -156,7 +156,7 @@ You can use this same decorator with different keys to access different properti
#### Working with pipes
-Nest treats custom param decorators in the same fashion as the built-in ones (`@Body()`, `@Param()` and `@Query()`). This means that pipes are executed for the custom annotated parameters as well (in our examples, the `user` argument). Moreover, you can apply the pipe directly to the custom decorator:
+Nest treats custom param decorators in the same fashion as the built-in ones (`@Body()`, `@Param()` and `@QueryString()`). This means that pipes are executed for the custom annotated parameters as well (in our examples, the `user` argument). Moreover, you can apply the pipe directly to the custom decorator:
```typescript
@@filename()
diff --git a/content/faq/request-lifecycle.md b/content/faq/request-lifecycle.md
index 3e80edeff0..5bfa661e9b 100644
--- a/content/faq/request-lifecycle.md
+++ b/content/faq/request-lifecycle.md
@@ -47,7 +47,7 @@ export class CatsController {
updateCat(
@Body() body: UpdateCatDTO,
@Param() params: UpdateCatParams,
- @Query() query: UpdateCatQuery,
+ @QueryString() query: UpdateCatQuery,
) {
return this.catsService.updateCat(body, params, query);
}
diff --git a/content/migration.md b/content/migration.md
index 2930a62354..57dab4729b 100644
--- a/content/migration.md
+++ b/content/migration.md
@@ -352,3 +352,28 @@ $ mau deploy
```
You can learn more about Mau [in this chapter](/deployment#easy-deployment-with-mau).
+
+#### `@Query()` and `@QueryString()`
+
+> warning **BREAKING CHANGE** (NestJS release that introduces HTTP `QUERY` support; see [nestjs/nest#17397](https://github.com/nestjs/nest/pull/17397))
+>
+> - Rename: `@Query()` parameter decorator → `@QueryString()`
+> - New: `@Query()` method decorator routes HTTP `QUERY` requests
+
+The former `@Query()` **parameter** decorator (which extracted URL query string values from `req.query`) has been renamed to `@QueryString()`. The `@Query()` name is now the **method** decorator for the HTTP `QUERY` verb (same pattern as `@Get()`, `@Post()`, `@Search()`, and so on). Handlers for HTTP `QUERY` should read the payload with `@Body()`.
+
+```typescript
+// before
+@Get()
+find(@Query('page') page: string) {}
+
+// after
+@Get()
+find(@QueryString('page') page: string) {}
+
+// new HTTP QUERY route
+@Query('items')
+search(@Body() body: FiltersDto) {}
+```
+
+> info **Hint** Runtime support for the HTTP `QUERY` method depends on Node.js including `QUERY` in `http.METHODS` (typically `>=20.19.3 <21` or `>=22.2.0`). See [Controllers](/controllers#resources) for more details.
diff --git a/content/openapi/types-and-parameters.md b/content/openapi/types-and-parameters.md
index 5c881e003b..1f443f5aef 100644
--- a/content/openapi/types-and-parameters.md
+++ b/content/openapi/types-and-parameters.md
@@ -1,6 +1,6 @@
### Types and parameters
-The `SwaggerModule` searches for all `@Body()`, `@Query()`, and `@Param()` decorators in route handlers to generate the API document. It also creates corresponding model definitions by taking advantage of reflection. Consider the following code:
+The `SwaggerModule` searches for all `@Body()`, `@QueryString()`, and `@Param()` decorators in route handlers to generate the API document. It also creates corresponding model definitions by taking advantage of reflection. Consider the following code:
```typescript
@Post()
@@ -120,11 +120,11 @@ export enum UserRole {
}
```
-You can then use the enum directly with the `@Query()` parameter decorator in combination with the `@ApiQuery()` decorator.
+You can then use the enum directly with the `@QueryString()` parameter decorator in combination with the `@ApiQuery()` decorator.
```typescript
@ApiQuery({ name: 'role', enum: UserRole })
-async filterByRole(@Query('role') role: UserRole = UserRole.User) {}
+async filterByRole(@QueryString('role') role: UserRole = UserRole.User) {}
```
diff --git a/content/pipes.md b/content/pipes.md
index fc6a9094cf..a6097f5ced 100644
--- a/content/pipes.md
+++ b/content/pipes.md
@@ -85,7 +85,7 @@ For example with a query string parameter:
```typescript
@Get()
-async findOne(@Query('id', ParseIntPipe) id: number) {
+async findOne(@QueryString('id', ParseIntPipe) id: number) {
return this.catsService.findOne(id);
}
```
@@ -165,7 +165,7 @@ These properties describe the currently processed argument.
Indicates whether the argument is a body
@Body(), query
- @Query(), param
+ @QueryString(), param
@Param(), or a custom parameter (read more
here).
@@ -549,14 +549,14 @@ We leave the implementation of this pipe to the reader, but note that like all o
#### Providing defaults
-`Parse*` pipes expect a parameter's value to be defined. They throw an exception upon receiving `null` or `undefined` values. To allow an endpoint to handle missing querystring parameter values, we have to provide a default value to be injected before the `Parse*` pipes operate on these values. The `DefaultValuePipe` serves that purpose. Simply instantiate a `DefaultValuePipe` in the `@Query()` decorator before the relevant `Parse*` pipe, as shown below:
+`Parse*` pipes expect a parameter's value to be defined. They throw an exception upon receiving `null` or `undefined` values. To allow an endpoint to handle missing querystring parameter values, we have to provide a default value to be injected before the `Parse*` pipes operate on these values. The `DefaultValuePipe` serves that purpose. Simply instantiate a `DefaultValuePipe` in the `@QueryString()` decorator before the relevant `Parse*` pipe, as shown below:
```typescript
@@filename()
@Get()
async findAll(
- @Query('activeOnly', new DefaultValuePipe(false), ParseBoolPipe) activeOnly: boolean,
- @Query('page', new DefaultValuePipe(0), ParseIntPipe) page: number,
+ @QueryString('activeOnly', new DefaultValuePipe(false), ParseBoolPipe) activeOnly: boolean,
+ @QueryString('page', new DefaultValuePipe(0), ParseIntPipe) page: number,
) {
return this.catsService.findAll({ activeOnly, page });
}
diff --git a/content/techniques/serialization.md b/content/techniques/serialization.md
index f225a1dbaa..6830458090 100644
--- a/content/techniques/serialization.md
+++ b/content/techniques/serialization.md
@@ -108,7 +108,7 @@ In the example below, despite returning plain JavaScript objects in both conditi
@UseInterceptors(ClassSerializerInterceptor)
@SerializeOptions({ type: UserEntity })
@Get()
-findOne(@Query() { id }: { id: number }): UserEntity {
+findOne(@QueryString() { id }: { id: number }): UserEntity {
if (id === 1) {
return {
id: 1,
diff --git a/content/techniques/validation.md b/content/techniques/validation.md
index ab9d28cdab..bfe1c02556 100644
--- a/content/techniques/validation.md
+++ b/content/techniques/validation.md
@@ -286,7 +286,7 @@ Alternatively (with auto-transformation disabled), you can explicitly cast value
@Get(':id')
findOne(
@Param('id', ParseIntPipe) id: number,
- @Query('sort', ParseBoolPipe) sort: boolean,
+ @QueryString('sort', ParseBoolPipe) sort: boolean,
) {
console.log(typeof id === 'number'); // true
console.log(typeof sort === 'boolean'); // true
@@ -420,7 +420,7 @@ In addition, the `ParseArrayPipe` may come in handy when parsing query parameter
```typescript
@Get()
findByIds(
- @Query('ids', new ParseArrayPipe({ items: Number, separator: ',' }))
+ @QueryString('ids', new ParseArrayPipe({ items: Number, separator: ',' }))
ids: number[],
) {
return 'This action returns users by ids';