Skip to content

Commit c46b254

Browse files
committed
refactor: move config normalization to defineConfig method
1 parent 901060f commit c46b254

File tree

7 files changed

+104
-47
lines changed

7 files changed

+104
-47
lines changed

src/define_config.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@
88
*/
99

1010
import proxyAddr from 'proxy-addr'
11-
import type { RequestConfig } from './types/request.js'
12-
import type { ResponseConfig } from './types/response.js'
11+
import string from '@poppinss/utils/string'
12+
import type { ServerConfig } from './types/server.js'
1313

1414
/**
1515
* Define configuration for the HTTP server
1616
*/
17-
export function defineConfig(
18-
config: Partial<RequestConfig & ResponseConfig>
19-
): RequestConfig & ResponseConfig {
20-
return {
17+
export function defineConfig(config: Partial<ServerConfig>): ServerConfig {
18+
const normalizedConfig = {
2119
allowMethodSpoofing: false,
2220
trustProxy: proxyAddr.compile('loopback'),
2321
subdomainOffset: 2,
@@ -34,4 +32,10 @@ export function defineConfig(
3432
},
3533
...config,
3634
}
35+
36+
if (normalizedConfig.cookie.maxAge) {
37+
normalizedConfig.cookie.maxAge = string.seconds.parse(normalizedConfig.cookie.maxAge)
38+
}
39+
40+
return normalizedConfig
3741
}

src/request.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ import type { HttpContext } from './http_context/main.js'
3737
* using `request.request` property.
3838
*/
3939
export class Request extends Macroable {
40+
/**
41+
* Encryption module to verify signed URLs and unsign/decrypt
42+
* cookies
43+
*/
44+
#encryption: Encryption
45+
46+
/**
47+
* Request config
48+
*/
49+
#config: RequestConfig
50+
4051
/**
4152
* Request body set using `setBody` method
4253
*/
@@ -90,11 +101,13 @@ export class Request extends Macroable {
90101
constructor(
91102
public request: IncomingMessage,
92103
public response: ServerResponse,
93-
private encryption: Encryption,
94-
private config: RequestConfig
104+
encryption: Encryption,
105+
config: RequestConfig
95106
) {
96107
super()
97108

109+
this.#config = config
110+
this.#encryption = encryption
98111
this.parsedUrl = parse(this.request.url!, false)
99112
this.#parseQueryString()
100113
}
@@ -114,7 +127,7 @@ export class Request extends Macroable {
114127
*/
115128
#initiateCookieParser() {
116129
if (!this.#cookieParser) {
117-
this.#cookieParser = new CookieParser(this.header('cookie')!, this.encryption)
130+
this.#cookieParser = new CookieParser(this.header('cookie')!, this.#encryption)
118131
}
119132
}
120133

@@ -133,7 +146,7 @@ export class Request extends Macroable {
133146
*/
134147
id(): string | undefined {
135148
let requestId = this.header('x-request-id')
136-
if (!requestId && this.config.generateRequestId) {
149+
if (!requestId && this.#config.generateRequestId) {
137150
requestId = cuid()
138151
this.request.headers['x-request-id'] = requestId
139152
}
@@ -320,7 +333,7 @@ export class Request extends Macroable {
320333
* ```
321334
*/
322335
method(): string {
323-
if (this.config.allowMethodSpoofing && this.intended() === 'POST') {
336+
if (this.#config.allowMethodSpoofing && this.intended() === 'POST') {
324337
return this.input('_method', this.intended()).toUpperCase()
325338
}
326339
return this.intended()
@@ -382,12 +395,12 @@ export class Request extends Macroable {
382395
* The value of trustProxy is passed directly to [proxy-addr](https://www.npmjs.com/package/proxy-addr)
383396
*/
384397
ip(): string {
385-
const ipFn = this.config.getIp
398+
const ipFn = this.#config.getIp
386399
if (typeof ipFn === 'function') {
387400
return ipFn(this)
388401
}
389402

390-
return proxyaddr(this.request, this.config.trustProxy)
403+
return proxyaddr(this.request, this.#config.trustProxy)
391404
}
392405

393406
/**
@@ -409,7 +422,7 @@ export class Request extends Macroable {
409422
* The value of trustProxy is passed directly to [proxy-addr](https://www.npmjs.com/package/proxy-addr)
410423
*/
411424
ips(): string[] {
412-
return proxyaddr.all(this.request, this.config.trustProxy)
425+
return proxyaddr.all(this.request, this.#config.trustProxy)
413426
}
414427

415428
/**
@@ -437,7 +450,7 @@ export class Request extends Macroable {
437450
return 'https'
438451
}
439452

440-
if (!trustProxy(this.request.socket.remoteAddress!, this.config.trustProxy)) {
453+
if (!trustProxy(this.request.socket.remoteAddress!, this.#config.trustProxy)) {
441454
return this.parsedUrl.protocol || 'http'
442455
}
443456

@@ -478,7 +491,7 @@ export class Request extends Macroable {
478491
* Use X-Fowarded-Host when we trust the proxy header and it
479492
* exists
480493
*/
481-
if (trustProxy(this.request.socket.remoteAddress!, this.config.trustProxy)) {
494+
if (trustProxy(this.request.socket.remoteAddress!, this.#config.trustProxy)) {
482495
host = this.header('X-Forwarded-Host') || host
483496
}
484497

@@ -540,7 +553,7 @@ export class Request extends Macroable {
540553
return []
541554
}
542555

543-
const offset = this.config.subdomainOffset
556+
const offset = this.#config.subdomainOffset
544557
const subdomains = hostname.split('.').reverse().slice(offset)
545558

546559
/*
@@ -907,7 +920,7 @@ export class Request extends Macroable {
907920
/*
908921
* Return false when signature fails
909922
*/
910-
const signedUrl = this.encryption.verifier.unsign(signature, purpose)
923+
const signedUrl = this.#encryption.verifier.unsign(signature, purpose)
911924
if (!signedUrl) {
912925
return false
913926
}

src/response.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export class Response extends Macroable {
6464
#router: Router
6565

6666
/**
67-
* Response defaults
67+
* Response config
6868
*/
6969
#config: ResponseConfig
7070

src/server/main.ts

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
* file that was distributed with this source code.
88
*/
99

10-
import string from '@poppinss/utils/string'
1110
import Middleware from '@poppinss/middleware'
1211
import { RuntimeException } from '@poppinss/utils'
1312
import type Encryption from '@adonisjs/encryption'
@@ -17,10 +16,8 @@ import type { Server as HttpsServer } from 'node:https'
1716
import type { ServerResponse, IncomingMessage, Server as HttpServer } from 'node:http'
1817

1918
import type { LazyImport } from '../types/base.js'
20-
import type { RequestConfig } from '../types/request.js'
21-
import type { ResponseConfig } from '../types/response.js'
22-
import type { ErrorHandlerAsAClass, ServerErrorHandler } from '../types/server.js'
2319
import type { MiddlewareAsClass, ParsedGlobalMiddleware } from '../types/middleware.js'
20+
import type { ErrorHandlerAsAClass, ServerConfig, ServerErrorHandler } from '../types/server.js'
2421

2522
import debug from '../debug.js'
2623
import { Request } from '../request.js'
@@ -67,7 +64,7 @@ export class Server<NamedMiddleware extends Record<string, LazyImport<Middleware
6764
/**
6865
* Server config
6966
*/
70-
#config: RequestConfig & ResponseConfig
67+
#config: ServerConfig
7168

7269
/**
7370
* Server middleware stack runs on every incoming HTTP request
@@ -91,29 +88,15 @@ export class Server<NamedMiddleware extends Record<string, LazyImport<Middleware
9188
return asyncLocalStorage.isEnabled
9289
}
9390

94-
constructor(app: Application, encryption: Encryption, config: RequestConfig & ResponseConfig) {
91+
constructor(app: Application, encryption: Encryption, config: ServerConfig) {
9592
this.#app = app
9693
this.#encryption = encryption
9794
this.#config = config
98-
this.#preProcessCookieMaxAge()
9995
this.#createAsyncLocalStore()
10096

10197
debug('server config: %O', this.#config)
10298
}
10399

104-
/**
105-
* Pre-processing cookie maxAge property to avoid re-parsing on
106-
* every request
107-
*/
108-
#preProcessCookieMaxAge() {
109-
/*
110-
* Pre process config to convert max age string to seconds.
111-
*/
112-
if (this.#config.cookie.maxAge && typeof this.#config.cookie.maxAge === 'string') {
113-
this.#config.cookie.maxAge = string.seconds.parse(this.#config.cookie.maxAge)
114-
}
115-
}
116-
117100
/**
118101
* Create async local storage store when enabled
119102
*/

src/types/request.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,4 @@ export type RequestConfig = {
4747
* the `proxy-addr` package to compute this value.
4848
*/
4949
trustProxy: (address: string, distance: number) => boolean
50-
51-
/**
52-
* Whether or not to create an async local storage store for
53-
* the HTTP context.
54-
*
55-
* Defaults to false
56-
*/
57-
useAsyncLocalStorage?: boolean
5850
}

src/types/server.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
*/
99

1010
import type { Constructor } from './base.js'
11+
import type { RequestConfig } from './request.js'
12+
import type { ResponseConfig } from './response.js'
1113
import type { HttpContext } from '../http_context/main.js'
1214

1315
/**
@@ -21,3 +23,17 @@ export type ServerErrorHandler = {
2123
* Error handler represented as a class
2224
*/
2325
export type ErrorHandlerAsAClass = Constructor<ServerErrorHandler>
26+
27+
/**
28+
* Config accepted by the HTTP server
29+
*/
30+
export type ServerConfig = RequestConfig &
31+
ResponseConfig & {
32+
/**
33+
* Whether or not to create an async local storage store for
34+
* the HTTP context.
35+
*
36+
* Defaults to false
37+
*/
38+
useAsyncLocalStorage?: boolean
39+
}

tests/define_config.spec.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* @adonisjs/http-server
3+
*
4+
* (c) AdonisJS
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
import { test } from '@japa/runner'
11+
import { defineConfig } from '../index.js'
12+
13+
test.group('Define config', () => {
14+
test('define server config', ({ assert }) => {
15+
assert.containsSubset(defineConfig({}), {
16+
allowMethodSpoofing: false,
17+
etag: false,
18+
cookie: {
19+
httpOnly: true,
20+
path: '/',
21+
maxAge: 7200,
22+
sameSite: false,
23+
secure: false,
24+
},
25+
generateRequestId: false,
26+
jsonpCallbackName: 'callback',
27+
subdomainOffset: 2,
28+
useAsyncLocalStorage: false,
29+
})
30+
})
31+
32+
test('give preference to defined config', ({ assert }) => {
33+
assert.containsSubset(defineConfig({ allowMethodSpoofing: true }), {
34+
allowMethodSpoofing: true,
35+
etag: false,
36+
cookie: {
37+
httpOnly: true,
38+
path: '/',
39+
maxAge: 7200,
40+
sameSite: false,
41+
secure: false,
42+
},
43+
generateRequestId: false,
44+
jsonpCallbackName: 'callback',
45+
subdomainOffset: 2,
46+
useAsyncLocalStorage: false,
47+
})
48+
})
49+
})

0 commit comments

Comments
 (0)