Skip to content

Commit 74aa97c

Browse files
authored
Feat/len add interceptors terminators (#19)
* feat: add controller and request mappers decorators * refactor: remove route array from Http class * refactor: create handler to hook preHandler * feat: implement fastify handler class and set error handler method * style: add more keywords in package.json * feat: add interceptors and terminators middleware to project * feat: add interceptors/terminators middlewares and controller method to router * fix: change ports for each test * feat: add url methods to request and change node ci version
1 parent 4e62858 commit 74aa97c

35 files changed

+748
-108
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818

1919
- uses: actions/setup-node@v1
2020
with:
21-
node-version: '14.x'
21+
node-version: '16.x'
2222
registry-url: 'https://registry.npmjs.org'
2323

2424
- name: Download dependencies

README.md

+61-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ The intention behind this repository is to always maintain a `Http` package to a
2929
> it keeps as dev dependency because one day `@secjs/core` will install everything once.
3030
3131
```bash
32-
npm install @secjs/ioc @secjs/utils @secjs/exceptions
32+
npm install @secjs/ioc @secjs/env @secjs/utils @secjs/exceptions
3333
```
3434

3535
> Then you can install the package using:
@@ -140,6 +140,66 @@ Route.register()
140140
http.listen()
141141
```
142142

143+
### Creating a Middleware
144+
145+
> With Http you can define three different execution times for one middleware
146+
147+
```ts
148+
import {
149+
Router,
150+
MiddlewareContract,
151+
HandleContextContract,
152+
InterceptContextContract,
153+
TerminateContextContract
154+
} from '@secjs/http'
155+
156+
export class Middleware implements MiddlewareContract {
157+
// Handle method will be executed before the controller method handler
158+
// This is the normal middleware
159+
async handle(ctx: HandleContextContract) {
160+
ctx.data.userId = '1'
161+
162+
ctx.next()
163+
}
164+
165+
// Intercept method will be executed before the response goes to client
166+
async intercept(ctx: InterceptContextContract) {
167+
// You can use intercept to rewrite or add some information to the response
168+
ctx.body.intercepted = true
169+
ctx.response.status(304)
170+
171+
ctx.next()
172+
}
173+
174+
// Terminate method will be executed after the response goes to client
175+
async terminate(ctx: TerminateContextContract) {
176+
// You can use terminate to save metrics of the request in an Elastic for example
177+
console.log('Terminate middleware executed!')
178+
179+
ctx.next()
180+
}
181+
}
182+
```
183+
184+
> Now we can use Router to set the middleware in some route
185+
186+
```ts
187+
Container.singleton(
188+
{
189+
'middleware': new Middleware(),
190+
},
191+
'Middlewares',
192+
)
193+
194+
// If you use named middlewares in Router, he will register all the three methods of Middleware class.
195+
Route.get('middlewares', 'TestController.index').middleware('middleware')
196+
197+
//
198+
Route
199+
.get('middlewares', 'TestController.index')
200+
.middleware(new Middleware().handle)
201+
```
202+
143203
---
144204

145205
## License

index.ts

+11
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,16 @@ export * from './src/Contracts/MiddlewareContract'
55

66
export * from './src/Contracts/Context/ContextContract'
77
export * from './src/Contracts/Context/HandlerContract'
8+
89
export * from './src/Contracts/Context/RequestContract'
910
export * from './src/Contracts/Context/ResponseContract'
11+
12+
export * from './src/Contracts/Context/Error/ErrorContextContract'
13+
export * from './src/Contracts/Context/Error/ErrorHandlerContract'
14+
15+
export * from './src/Contracts/Context/Middlewares/Handle/HandleContextContract'
16+
export * from './src/Contracts/Context/Middlewares/Handle/HandleHandlerContract'
17+
export * from './src/Contracts/Context/Middlewares/Intercept/InterceptContextContract'
18+
export * from './src/Contracts/Context/Middlewares/Intercept/InterceptHandlerContract'
19+
export * from './src/Contracts/Context/Middlewares/Terminate/TerminateContextContract'
20+
export * from './src/Contracts/Context/Middlewares/Terminate/TerminateHandlerContract'

package-lock.json

+43-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@
2323
"nodejs"
2424
],
2525
"devDependencies": {
26+
"@secjs/env": "1.2.8",
2627
"@secjs/exceptions": "1.0.4",
2728
"@secjs/ioc": "1.0.8",
28-
"@secjs/utils": "1.6.3",
29+
"@secjs/utils": "1.6.5",
2930
"@types/jest": "27.0.1",
3031
"@types/node": "14.14.37",
3132
"@types/supertest": "^2.0.11",

src/Context/Request.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
* file that was distributed with this source code.
88
*/
99

10+
import { Env } from '@secjs/env'
11+
import { Is } from '@secjs/utils'
1012
import { FastifyRequest } from 'fastify'
13+
import { removeSlash } from '../Utils/removeSlash'
1114
import { RequestContract } from '../Contracts/Context/RequestContract'
1215

1316
export class Request implements RequestContract {
@@ -25,14 +28,24 @@ export class Request implements RequestContract {
2528
return this.request.method
2629
}
2730

28-
get fullUrl(): string {
29-
return this.request.url
31+
get hostUrl(): string {
32+
const url = this.request.url
33+
const port = Env('PORT', '1335')
34+
let host = Env('APP_DOMAIN', `http://localhost:${port}`)
35+
36+
if (!Is.Ip(host)) host = host.replace(`:${port}`, '')
37+
38+
return removeSlash(`${host}${url}`) as string
3039
}
3140

3241
get baseUrl(): string {
3342
return this.request.url.split('?')[0]
3443
}
3544

45+
get originalUrl(): string {
46+
return this.request.url
47+
}
48+
3649
get body(): Record<string, any> {
3750
return this.request.body
3851
}

src/Contracts/Context/ContextContract.ts

-3
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 { NextContract } from './NextContract'
1110
import { RequestContract } from './RequestContract'
1211
import { ResponseContract } from './ResponseContract'
1312

@@ -16,7 +15,5 @@ export interface ContextContract {
1615
response: ResponseContract
1716
params: Record<string, string>
1817
queries: Record<string, string>
19-
next?: NextContract
2018
data?: Record<string, any>
21-
error?: any
2219
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* @secjs/http
3+
*
4+
* (c) João Lenon <lenon@secjs.com.br>
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 { RequestContract } from '../RequestContract'
11+
import { ResponseContract } from '../ResponseContract'
12+
13+
export interface ErrorContextContract {
14+
request: RequestContract
15+
response: ResponseContract
16+
params: Record<string, string>
17+
queries: Record<string, string>
18+
data?: Record<string, any>
19+
error: any
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* @secjs/http
3+
*
4+
* (c) João Lenon <lenon@secjs.com.br>
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 { ErrorContextContract } from './ErrorContextContract'
11+
12+
export interface ErrorHandlerContract {
13+
(ctx?: ErrorContextContract): Promise<any> | any
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @secjs/http
3+
*
4+
* (c) João Lenon <lenon@secjs.com.br>
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 { NextContract } from '../../NextContract'
11+
import { RequestContract } from '../../RequestContract'
12+
import { ResponseContract } from '../../ResponseContract'
13+
14+
export interface HandleContextContract {
15+
request: RequestContract
16+
response: ResponseContract
17+
params: Record<string, string>
18+
queries: Record<string, string>
19+
data?: Record<string, any>
20+
next: NextContract
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* @secjs/http
3+
*
4+
* (c) João Lenon <lenon@secjs.com.br>
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 { HandleContextContract } from './HandleContextContract'
11+
12+
export interface HandleHandlerContract {
13+
(ctx?: HandleContextContract): Promise<any> | any
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* @secjs/http
3+
*
4+
* (c) João Lenon <lenon@secjs.com.br>
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 { NextContract } from '../../NextContract'
11+
import { RequestContract } from '../../RequestContract'
12+
import { ResponseContract } from '../../ResponseContract'
13+
14+
export interface InterceptContextContract {
15+
request: RequestContract
16+
response: ResponseContract
17+
params: Record<string, string>
18+
queries: Record<string, string>
19+
body: Record<string, any>
20+
data?: Record<string, any>
21+
next: NextContract
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* @secjs/http
3+
*
4+
* (c) João Lenon <lenon@secjs.com.br>
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 { InterceptContextContract } from './InterceptContextContract'
11+
12+
export interface InterceptHandlerContract {
13+
(ctx?: InterceptContextContract): Promise<any> | any
14+
}

0 commit comments

Comments
 (0)