Skip to content

Commit 369858d

Browse files
authored
[Backport 4.x] refactor: change reply.redirect() signature (#5483) (#5484)
* feat: change `reply.redirect()` signature * feat: change `reply.redirect()` signature * docs * docs * update message * fix deprecation * update message
1 parent d2d6d9a commit 369858d

File tree

7 files changed

+62
-16
lines changed

7 files changed

+62
-16
lines changed

docs/Reference/Reply.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
- [.trailer(key, function)](#trailerkey-function)
1818
- [.hasTrailer(key)](#hastrailerkey)
1919
- [.removeTrailer(key)](#removetrailerkey)
20-
- [.redirect([code ,] dest)](#redirectcode--dest)
20+
- [.redirect(dest, [code ,])](#redirectdest--code)
2121
- [.callNotFound()](#callnotfound)
2222
- [.getResponseTime()](#getresponsetime)
2323
- [.type(contentType)](#typecontenttype)
@@ -62,8 +62,8 @@ since the request was received by Fastify.
6262
- `.hasTrailer(key)` - Determine if a trailer has been set.
6363
- `.removeTrailer(key)` - Remove the value of a previously set trailer.
6464
- `.type(value)` - Sets the header `Content-Type`.
65-
- `.redirect([code,] dest)` - Redirect to the specified URL, the status code is
66-
optional (default to `302`).
65+
- `.redirect(dest, [code,])` - Redirect to the specified URL, the status code is
66+
optional (defaults to `302`).
6767
- `.callNotFound()` - Invokes the custom not found handler.
6868
- `.serialize(payload)` - Serializes the specified payload using the default
6969
JSON serializer or using the custom serializer (if one is set) and returns the
@@ -299,7 +299,7 @@ reply.getTrailer('server-timing') // undefined
299299
```
300300

301301

302-
### .redirect([code ,] dest)
302+
### .redirect(dest, [code ,])
303303
<a id="redirect"></a>
304304

305305
Redirects a request to the specified URL, the status code is optional, default
@@ -320,7 +320,7 @@ reply.redirect('/home')
320320
Example (no `reply.code()` call) sets status code to `303` and redirects to
321321
`/home`
322322
```js
323-
reply.redirect(303, '/home')
323+
reply.redirect('/home', 303)
324324
```
325325

326326
Example (`reply.code()` call) sets status code to `303` and redirects to `/home`
@@ -330,7 +330,7 @@ reply.code(303).redirect('/home')
330330

331331
Example (`reply.code()` call) sets status code to `302` and redirects to `/home`
332332
```js
333-
reply.code(303).redirect(302, '/home')
333+
reply.code(303).redirect('/home', 302)
334334
```
335335

336336
### .callNotFound()

docs/Reference/Warnings.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
- [FSTDEP018](#FSTDEP018)
2525
- [FSTDEP019](#FSTDEP019)
2626
- [FSTDEP020](#FSTDEP020)
27+
- [FSTDEP021](#FSTDEP021)
2728

2829

2930
## Warnings
@@ -90,3 +91,4 @@ Deprecation codes are further supported by the Node.js CLI options:
9091
| <a id="FSTDEP018">FSTDEP018</a> | You are accessing the deprecated `request.routerMethod` property. | Use `request.routeOptions.method`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
9192
| <a id="FSTDEP019">FSTDEP019</a> | You are accessing the deprecated `reply.context` property. | Use `reply.routeOptions.config` or `reply.routeOptions.schema`. | [#5032](https://github.com/fastify/fastify/pull/5032) [#5084](https://github.com/fastify/fastify/pull/5084) |
9293
| <a id="FSTDEP020">FSTDEP020</a> | You are using the deprecated `reply.getReponseTime()` method. | Use the `reply.elapsedTime` property instead. | [#5263](https://github.com/fastify/fastify/pull/5263) |
94+
| <a id="FSTDEP021">FSTDEP021</a> | The `reply.redirect()` method has a new signature: `reply.redirect(url: string, code?: number)`. It will be enforced in `fastify@v5`'. | [#5483](https://github.com/fastify/fastify/pull/5483) |

lib/reply.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const {
5555
FST_ERR_MISSING_SERIALIZATION_FN,
5656
FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN
5757
} = require('./errors')
58-
const { FSTDEP010, FSTDEP013, FSTDEP019, FSTDEP020 } = require('./warnings')
58+
const { FSTDEP010, FSTDEP013, FSTDEP019, FSTDEP020, FSTDEP021 } = require('./warnings')
5959

6060
const toString = Object.prototype.toString
6161

@@ -457,9 +457,15 @@ Reply.prototype.type = function (type) {
457457
return this
458458
}
459459

460-
Reply.prototype.redirect = function (code, url) {
461-
if (typeof code === 'string') {
462-
url = code
460+
Reply.prototype.redirect = function (url, code) {
461+
if (typeof url === 'number') {
462+
FSTDEP021()
463+
const temp = code
464+
code = url
465+
url = temp
466+
}
467+
468+
if (!code) {
463469
code = this[kReplyHasStatusCode] ? this.raw.statusCode : 302
464470
}
465471

lib/warnings.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ const FSTDEP020 = createDeprecation({
8282
message: 'You are using the deprecated "reply.getResponseTime()" method. Use the "reply.elapsedTime" property instead. Method "reply.getResponseTime()" will be removed in `fastify@5`.'
8383
})
8484

85+
const FSTDEP021 = createDeprecation({
86+
code: 'FSTDEP021',
87+
message: 'The `reply.redirect()` method has a new signature: `reply.redirect(url: string, code?: number)`. It will be enforced in `fastify@v5`'
88+
})
89+
8590
const FSTWRN001 = createWarning({
8691
name: 'FastifyWarning',
8792
code: 'FSTWRN001',
@@ -113,6 +118,7 @@ module.exports = {
113118
FSTDEP018,
114119
FSTDEP019,
115120
FSTDEP020,
121+
FSTDEP021,
116122
FSTWRN001,
117123
FSTWRN002
118124
}

test/internals/reply.test.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const {
1919
} = require('../../lib/symbols')
2020
const fs = require('node:fs')
2121
const path = require('node:path')
22-
const { FSTDEP010, FSTDEP019, FSTDEP020 } = require('../../lib/warnings')
22+
const { FSTDEP010, FSTDEP019, FSTDEP020, FSTDEP021 } = require('../../lib/warnings')
2323

2424
const agent = new http.Agent({ keepAlive: false })
2525

@@ -250,15 +250,15 @@ test('within an instance', t => {
250250
})
251251

252252
fastify.get('/redirect-code', function (req, reply) {
253-
reply.redirect(301, '/')
253+
reply.redirect('/', 301)
254254
})
255255

256256
fastify.get('/redirect-code-before-call', function (req, reply) {
257257
reply.code(307).redirect('/')
258258
})
259259

260260
fastify.get('/redirect-code-before-call-overwrite', function (req, reply) {
261-
reply.code(307).redirect(302, '/')
261+
reply.code(307).redirect('/', 302)
262262
})
263263

264264
fastify.get('/custom-serializer', function (req, reply) {
@@ -2094,6 +2094,36 @@ test('redirect to an invalid URL should not crash the server', async t => {
20942094
await fastify.close()
20952095
})
20962096

2097+
test('redirect with deprecated signature should warn', t => {
2098+
t.plan(4)
2099+
2100+
process.removeAllListeners('warning')
2101+
process.on('warning', onWarning)
2102+
function onWarning (warning) {
2103+
t.equal(warning.name, 'DeprecationWarning')
2104+
t.equal(warning.code, FSTDEP021.code)
2105+
}
2106+
2107+
const fastify = Fastify()
2108+
2109+
fastify.get('/', (req, reply) => {
2110+
reply.redirect(302, '/new')
2111+
})
2112+
2113+
fastify.get('/new', (req, reply) => {
2114+
reply.send('new')
2115+
})
2116+
2117+
fastify.inject({ method: 'GET', url: '/' }, (err, res) => {
2118+
t.error(err)
2119+
t.pass()
2120+
2121+
process.removeListener('warning', onWarning)
2122+
})
2123+
2124+
FSTDEP021.emitted = false
2125+
})
2126+
20972127
test('invalid response headers should not crash the server', async t => {
20982128
const fastify = Fastify()
20992129
fastify.route({

test/types/reply.test-d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const getHandler: RouteHandlerMethod = function (_request, reply) {
2929
expectAssignable<() => { [key: string]: number | string | string[] | undefined }>(reply.getHeaders)
3030
expectAssignable<(key: string) => FastifyReply>(reply.removeHeader)
3131
expectAssignable<(key: string) => boolean>(reply.hasHeader)
32-
expectType<{(statusCode: number, url: string): FastifyReply; (url: string): FastifyReply }>(reply.redirect)
32+
expectType<{(statusCode: number, url: string): FastifyReply;(url: string, statusCode?: number): FastifyReply;}>(reply.redirect)
3333
expectType<() => FastifyReply>(reply.hijack)
3434
expectType<() => void>(reply.callNotFound)
3535
// Test reply.getResponseTime() deprecation

types/reply.d.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ export interface FastifyReply<
5757
getHeaders(): Record<HttpHeader, number | string | string[] | undefined>;
5858
removeHeader(key: HttpHeader): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
5959
hasHeader(key: HttpHeader): boolean;
60-
// Note: should consider refactoring the argument order for redirect. statusCode is optional so it should be after the required url param
60+
/**
61+
* @deprecated The `reply.redirect()` method has a new signature: `reply.reply.redirect(url: string, code?: number)`. It will be enforced in `fastify@v5`'.
62+
*/
6163
redirect(statusCode: number, url: string): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
62-
redirect(url: string): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
64+
redirect(url: string, statusCode?: number): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
6365
hijack(): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
6466
callNotFound(): void;
6567
/**

0 commit comments

Comments
 (0)