Skip to content

Commit 6515bdf

Browse files
authored
Merge pull request #1 from ukitgroup/http-client
feat(http client): http client module based on got lib
2 parents dd74a25 + ffaf37f commit 6515bdf

35 files changed

+15694
-5
lines changed

.eslintrc.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
module.exports = {
2+
parser: "@typescript-eslint/parser",
3+
extends: [
4+
"eslint-config-airbnb-base",
5+
"plugin:@typescript-eslint/recommended",
6+
"prettier/@typescript-eslint",
7+
"plugin:prettier/recommended",
8+
"plugin:import/typescript"
9+
],
10+
parserOptions: {
11+
ecmaVersion: 2018,
12+
sourceType: "module"
13+
},
14+
rules: {
15+
"@typescript-eslint/no-parameter-properties": [
16+
"error",
17+
{
18+
allows: ["private readonly"]
19+
}
20+
],
21+
"@typescript-eslint/explicit-function-return-type": "off",
22+
"@typescript-eslint/interface-name-prefix": "off",
23+
"@typescript-eslint/no-unused-vars": "error",
24+
"import/prefer-default-export": "off",
25+
"no-useless-constructor": "off",
26+
"no-empty-function": "off",
27+
"class-methods-use-this": "off",
28+
"new-cap": "off",
29+
"@typescript-eslint/camelcase": "off",
30+
"no-underscore-dangle": "off",
31+
"import/extensions": [
32+
"error",
33+
"ignorePackages",
34+
{
35+
js: "never",
36+
jsx: "never",
37+
ts: "never",
38+
tsx: "never",
39+
mjs: "never"
40+
}
41+
]
42+
},
43+
overrides: [
44+
{
45+
files: ["*.test.{ts,js}", "*.spec.{ts,js}", "test/**/*.{ts,js}"],
46+
env: {
47+
jest: true
48+
},
49+
rules: {
50+
"no-console": "off",
51+
"import/no-extraneous-dependencies": "off",
52+
"@typescript-eslint/no-var-requires": "off",
53+
"no-underscore-dangle": "off",
54+
"no-restricted-syntax": "off",
55+
"no-await-in-loop": "off",
56+
"max-classes-per-file": "off"
57+
}
58+
}
59+
]
60+
};

.prettierrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"singleQuote": true,
3+
"trailingComma": "all"
4+
}

.travis.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
language: node_js
2+
3+
cache:
4+
directories:
5+
- node_modules
6+
7+
notifications:
8+
email:
9+
recipients:
10+
11+
12+
on_success: never
13+
on_failure: always
14+
15+
stages:
16+
- lints
17+
- test
18+
- name: release
19+
if: branch = master
20+
jobs:
21+
include:
22+
- stage: lints
23+
name: 'linting and type checking'
24+
node_js:
25+
- '12'
26+
before_script:
27+
- npm prune
28+
script:
29+
- npm run lint
30+
- npm run build
31+
- stage: test
32+
node_js:
33+
- '12'
34+
before_script:
35+
- npm prune
36+
script:
37+
- npm run test:cov
38+
- npm run test:e2e
39+
after_success:
40+
- npm run report-coverage
41+
- stage: release
42+
node_js: '12'
43+
before_script:
44+
- npm prune
45+
script:
46+
- npm run build
47+
- npm run semantic-release

README.md

Lines changed: 221 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,226 @@
11
# nestjs-http
22

3-
### Rich featured HttpClient for `nestjs` applications
3+
![Travis](https://img.shields.io/travis/ukitgroup/nestjs-http/master.svg?style=flat-square)
4+
![Coverage Status](https://coveralls.io/repos/github/ukitgroup/nestjs-http/badge.svg?branch=master)
5+
![node](https://img.shields.io/node/v/@ukitgroup/nestjs-http.svg?style=flat-square)
6+
![npm](https://img.shields.io/npm/v/@ukitgroup/nestjs-http.svg?style=flat-square)
47

5-
It implements wrapper around [Got](https://www.npmjs.com/package/got) lib instead of native nest HttpModule
8+
![GitHub top language](https://img.shields.io/github/languages/top/ukitgroup/nestjs-http.svg?style=flat-square)
9+
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/ukitgroup/nestjs-http.svg?style=flat-square)
10+
![David](https://img.shields.io/david/ukitgroup/nestjs-http.svg?style=flat-square)
11+
![David](https://img.shields.io/david/dev/ukitgroup/nestjs-http.svg?style=flat-square)
612

7-
It provides:
13+
![license](https://img.shields.io/github/license/ukitgroup/nestjs-http.svg?style=flat-square)
14+
![GitHub last commit](https://img.shields.io/github/last-commit/ukitgroup/nestjs-http.svg?style=flat-square)
15+
![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)
816

9-
1. [Got](https://www.npmjs.com/package/got) integration for [nestjs](https://nestjs.com/)
10-
2. Accept external Tracing Service for attaching specific http-headers across your microservice architecture
17+
## Description
18+
19+
### Rich featured HttpClient for [nestjs](https://nestjs.com/) applications
20+
21+
- [Got](https://www.npmjs.com/package/got) integration for `nestjs`;
22+
- Retries and all `Got` functions out of the box
23+
- Transparent `Got` usage (you will work with Got interface)
24+
- Accept external `Tracing Service` via DI for attaching specific http-headers across your microservice architecture;
25+
- Modularity - create instances for your modules with different configurations;
26+
- Default keep-alive http/https agent.
27+
28+
## Requirements
29+
30+
1. @nestjs/common ^7.2.0
31+
2. @nestjs/core ^7.2.0
32+
33+
## Installation
34+
35+
```bash
36+
npm install --save @ukitgroup/nestjs-http
37+
```
38+
39+
or
40+
41+
```bash
42+
yarn add @ukitgroup/nestjs-http
43+
```
44+
45+
## Short example
46+
47+
**cat.service.ts**
48+
49+
```typescript
50+
@Injectable()
51+
export class CatService {
52+
constructor(@Inject(HttpClientService) private readonly httpClient: Got) {}
53+
54+
meow(): string {
55+
// httpClient is an instance of Got
56+
// configuration from AppModule and CatModule
57+
// set built-in headers
58+
this.httpClient.post('/meow');
59+
return `meows..`;
60+
}
61+
}
62+
```
63+
64+
**cat.module.ts**
65+
66+
```typescript
67+
@Module({
68+
imports: [
69+
HttpClient.forInstance({
70+
imports: [YourConfigModule],
71+
providers: [
72+
{
73+
// override got configuration
74+
provide: HTTP_CLIENT_INSTANCE_GOT_OPTS,
75+
inject: [YourConfig],
76+
useFactory: config => {
77+
return {
78+
retry: config.retry,
79+
};
80+
},
81+
},
82+
],
83+
}),
84+
],
85+
providers: [CatService],
86+
})
87+
export class CatModule {}
88+
```
89+
90+
**app.module.ts**
91+
92+
```typescript
93+
@Module({
94+
imports: [HttpClient.forRoot({}), CatModule],
95+
})
96+
export class AppModule {}
97+
```
98+
99+
## API
100+
101+
Define root configuration for Got in AppModule with:
102+
103+
```
104+
HttpClient.forRoot(options: HttpClientForRootType)
105+
```
106+
107+
```
108+
HttpClientForRootType: {
109+
imports?: [],
110+
providers?: [],
111+
}
112+
```
113+
114+
Provide configuration with tokens:
115+
116+
- `HTTP_SERVICE_CONFIG` - ServiceConfigType for HttpClientService
117+
- `TRACE_DATA_SERVICE` - should implements TraceDataServiceInterface
118+
- `GOT_CONFIG` - got configuration
119+
120+
Provided configuration will be merged:
121+
defaultConfig -> forRoot() -> forInstance() -> execution
122+
123+
default config for httpService:
124+
125+
```typescript
126+
const defaultConfig = {
127+
enableTraceService: false,
128+
headersMap: {
129+
traceId: 'x-trace-id',
130+
ip: 'x-real-ip',
131+
userAgent: 'user-agent',
132+
referrer: 'referrer',
133+
},
134+
excludeHeaders: [],
135+
};
136+
```
137+
138+
default config for got extends default config from [got documentation](https://github.com/sindresorhus/got)
139+
140+
```typescript
141+
const defaultConfig = {
142+
agent: {
143+
http: new http.Agent({ keepAlive: true }),
144+
https: new https.Agent({ keepAlive: true }),
145+
},
146+
};
147+
```
148+
149+
Define instance configuration, trace service and http client service config in your module with:
150+
151+
```
152+
HttpClient.forInstance(options: HttpClientForRootType)
153+
```
154+
155+
# Trace service injection
156+
157+
Usually you pass some headers across your microservices such as: `trace-id`, `ip`, `user-agent` etc.
158+
To make it convenient you can inject traceService via `dependency injection` and `HTTPClient` will pass this data with headers
159+
160+
You just have to implement TraceServiceInterface:
161+
162+
```typescript
163+
export interface TraceDataServiceInterface {
164+
getRequestData(): TraceDataType;
165+
}
166+
167+
// and TraceDataType
168+
export type TraceDataType = {
169+
[key: string]: string;
170+
};
171+
```
172+
173+
Headers mapping to values:
174+
175+
```typescript
176+
const headersMap = {
177+
traceId: 'x-trace-id',
178+
ip: 'x-real-ip',
179+
userAgent: 'user-agent',
180+
referrer: 'referrer',
181+
};
182+
```
183+
184+
Sou you can just define your service which should return these fields. For example, you can use `cls-hooked` for retrieving request data
185+
186+
```typescript
187+
export class TraceService implements TraceDataServiceInterface {
188+
getRequestData() {
189+
return {
190+
traceId: 'unique-id',
191+
ip: '127.0.0.1',
192+
};
193+
}
194+
}
195+
```
196+
197+
And then just define configuration:
198+
199+
```typescript
200+
@Module({
201+
imports: [
202+
HttpClient.forInstance({
203+
providers: [
204+
{
205+
provide: HTTP_SERVICE_CONFIG,
206+
useValue: {
207+
enableTraceService: true,
208+
},
209+
},
210+
{ provide: TRACE_DATA_SERVICE, useClass: TraceService },
211+
],
212+
}),
213+
],
214+
})
215+
class AwesomeModule {}
216+
```
217+
218+
### TODO
219+
220+
- Injection of `MetricService` for exports requests metrics such as: statuses, errors, retries, timing
221+
- Client balancing for servers with several `ip`s or endpoints in different AZ which don't support server's LB.
222+
- ... Feature/Pull requests are welcome!😅
223+
224+
## License
225+
226+
@ukitgroup/nestjs-http is [MIT licensed](LICENSE).

commitlint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = { extends: ['@commitlint/config-conventional'] };

0 commit comments

Comments
 (0)