@adatechnology/http-client 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +596 -0
- package/dist/http.interface.js +27 -0
- package/dist/http.module.js +37 -0
- package/dist/http.provider.js +137 -0
- package/dist/http.token.js +6 -0
- package/dist/implementations/axios/axios.http.module.js +41 -0
- package/dist/implementations/axios/axios.http.provider.js +424 -0
- package/dist/implementations/axios/axios.http.token.js +4 -0
- package/dist/implementations/http.implementation.module.js +20 -0
- package/dist/index.js +11 -0
- package/dist/types/http.interface.d.ts +175 -0
- package/dist/types/http.module.d.ts +9 -0
- package/dist/types/http.provider.d.ts +43 -0
- package/dist/types/http.token.d.ts +3 -0
- package/dist/types/implementations/axios/axios.http.module.d.ts +5 -0
- package/dist/types/implementations/axios/axios.http.provider.d.ts +226 -0
- package/dist/types/implementations/axios/axios.http.token.d.ts +1 -0
- package/dist/types/implementations/http.implementation.module.d.ts +2 -0
- package/dist/types/index.d.ts +4 -0
- package/package.json +19 -0
- package/src/http.interface.ts +259 -0
- package/src/http.module.ts +27 -0
- package/src/http.provider.ts +219 -0
- package/src/http.token.ts +3 -0
- package/src/implementations/axios/axios.http.module.ts +33 -0
- package/src/implementations/axios/axios.http.provider.ts +603 -0
- package/src/implementations/axios/axios.http.token.ts +1 -0
- package/src/implementations/http.implementation.module.ts +9 -0
- package/src/index.ts +8 -0
- package/tsconfig.json +16 -0
- package/tsconfig.tsbuildinfo +1 -0
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
# HTTP Provider
|
|
2
|
+
|
|
3
|
+
Este módulo fornece uma interface HTTP completa e flexível para fazer requisições HTTP em aplicações NestJS. Suporta tanto APIs Promise quanto Observable (RxJS), oferecendo máxima flexibilidade para diferentes casos de uso.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
1. Instale as dependências necessárias no monorepo (axios + rxjs):
|
|
8
|
+
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
1. Instale as dependências necessárias no monorepo (axios + rxjs):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add -w axios rxjs
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
2. Configure o módulo no seu AppModule usando `forRoot` para fornecer uma instância Axios configurada (baseURL, timeout, headers etc.). O pacote publica o namespace `@adatechnology/http-client`.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { Module } from "@nestjs/common";
|
|
21
|
+
import { HttpModule } from "@adatechnology/http-client";
|
|
22
|
+
|
|
23
|
+
@Module({
|
|
24
|
+
imports: [
|
|
25
|
+
// conveniência: importa a implementação Axios internamente
|
|
26
|
+
HttpModule.forRoot({ baseURL: "https://api.example.com", timeout: 10000 }),
|
|
27
|
+
],
|
|
28
|
+
})
|
|
29
|
+
export class AppModule {}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Após isso, injete o provider padrão `HTTP_PROVIDER` no seu serviço:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
36
|
+
import {
|
|
37
|
+
HTTP_PROVIDER,
|
|
38
|
+
HttpProviderInterface,
|
|
39
|
+
} from "@adatechnology/http-client";
|
|
40
|
+
|
|
41
|
+
@Injectable()
|
|
42
|
+
export class MeuServico {
|
|
43
|
+
constructor(
|
|
44
|
+
@Inject(HTTP_PROVIDER) private readonly http: HttpProviderInterface,
|
|
45
|
+
) {}
|
|
46
|
+
|
|
47
|
+
async getUsers() {
|
|
48
|
+
const res = await this.http.get("/users");
|
|
49
|
+
return res.data;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
O pacote também exporta os tokens `HTTP_AXIOS_PROVIDER` e `HTTP_AXIOS_CONNECTION` caso precise da instância Axios original ou queira controlar a implementação diretamente.
|
|
55
|
+
O módulo também exporta os tokens `HTTP_AXIOS_PROVIDER` e `HTTP_AXIOS_CONNECTION` caso precise da instância Axios original ou queira criar instâncias adicionais.
|
|
56
|
+
|
|
57
|
+
## Implementation modules
|
|
58
|
+
|
|
59
|
+
A implementação específica (Axios) foi isolada em `implementations/axios`. Existem duas formas de usar o pacote:
|
|
60
|
+
|
|
61
|
+
1. Usar o shim de conveniência `HttpModule.forRoot(...)` — já importa a implementação Axios internamente e registra o `HTTP_PROVIDER`:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
// simples - importa a implementação Axios por baixo dos panos
|
|
65
|
+
imports: [HttpModule.forRoot({ baseURL: "https://api.example.com" })];
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
2. Importar explicitamente o módulo de implementação quando precisar de controle fino ou quiser trocar de driver:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { HttpImplementationAxiosModule } from "@adatechnology/http-client";
|
|
72
|
+
|
|
73
|
+
imports: [
|
|
74
|
+
// registra a conexão e o provider Axios
|
|
75
|
+
HttpImplementationAxiosModule.forRoot({ baseURL: "https://api.example.com" }),
|
|
76
|
+
// registra o provider genérico que usa a implementação registrada
|
|
77
|
+
HttpModule.forRoot(),
|
|
78
|
+
];
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Nesse modo explícito, `HttpImplementationAxiosModule.forRoot` registra os tokens `HTTP_AXIOS_CONNECTION` (a instância Axios) e `HTTP_AXIOS_PROVIDER` (o provider baseado em Axios). O `HttpModule` registra apenas o `HTTP_PROVIDER` que delega à implementação registrada.
|
|
82
|
+
|
|
83
|
+
Use a forma explícita se for adicionar múltiplos drivers (fetch, node-http) no futuro — cada driver teria seu próprio `implementations/*` com `forRoot`.
|
|
84
|
+
|
|
85
|
+
## Características
|
|
86
|
+
|
|
87
|
+
- ✅ Suporte completo a todos os métodos HTTP (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
|
|
88
|
+
- ✅ APIs duplas: Promise e Observable (RxJS)
|
|
89
|
+
- ✅ Cache automático com TTL configurável
|
|
90
|
+
- ✅ Invalidação de cache
|
|
91
|
+
- ✅ Interceptors para tratamento de erros
|
|
92
|
+
- ✅ Configuração de timeout, headers globais
|
|
93
|
+
- ✅ Instâncias múltiplas com configurações diferentes
|
|
94
|
+
- ✅ Tipagem TypeScript completa
|
|
95
|
+
- ✅ Baseado em Axios (robusto e bem testado)
|
|
96
|
+
|
|
97
|
+
## Instalação e Configuração
|
|
98
|
+
|
|
99
|
+
O provider HTTP já está integrado no sistema de providers do projeto. Para usar, basta injetar o `HTTP_PROVIDER` no seu serviço:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
103
|
+
import {
|
|
104
|
+
HTTP_PROVIDER,
|
|
105
|
+
HttpProviderInterface,
|
|
106
|
+
} from "@modules/shared/infrastructure/providers/http";
|
|
107
|
+
|
|
108
|
+
@Injectable()
|
|
109
|
+
export class MeuServico {
|
|
110
|
+
constructor(
|
|
111
|
+
@Inject(HTTP_PROVIDER)
|
|
112
|
+
private readonly httpProvider: HttpProviderInterface,
|
|
113
|
+
) {}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Exemplos de Uso
|
|
118
|
+
|
|
119
|
+
### Requisições Básicas
|
|
120
|
+
|
|
121
|
+
#### GET Request
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Promise API
|
|
125
|
+
const response = await this.httpProvider.get<User[]>("/api/users");
|
|
126
|
+
console.log(response.data); // Array de usuários
|
|
127
|
+
console.log(response.status); // 200
|
|
128
|
+
|
|
129
|
+
// Observable API
|
|
130
|
+
this.httpProvider.get$<User[]>("/api/users").subscribe({
|
|
131
|
+
next: (response) => console.log("Usuários:", response.data),
|
|
132
|
+
error: (error) => console.error("Erro:", error),
|
|
133
|
+
complete: () => console.log("Requisição completa"),
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### POST Request
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
const newUser = { name: "João", email: "joao@example.com" };
|
|
141
|
+
|
|
142
|
+
// Promise API
|
|
143
|
+
const response = await this.httpProvider.post<User>("/api/users", newUser);
|
|
144
|
+
console.log("Usuário criado:", response.data);
|
|
145
|
+
|
|
146
|
+
// Observable API
|
|
147
|
+
this.httpProvider.post$<User>("/api/users", newUser).subscribe({
|
|
148
|
+
next: (response) => console.log("Usuário criado:", response.data),
|
|
149
|
+
error: (error) => console.error("Erro ao criar usuário:", error),
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### PUT/PATCH Request
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
const updatedUser = { name: "João Silva", email: "joao.silva@example.com" };
|
|
157
|
+
|
|
158
|
+
// PUT - substitui completamente o recurso
|
|
159
|
+
const putResponse = await this.httpProvider.put<User>(
|
|
160
|
+
"/api/users/1",
|
|
161
|
+
updatedUser,
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
// PATCH - atualiza parcialmente o recurso
|
|
165
|
+
const patchResponse = await this.httpProvider.patch<User>("/api/users/1", {
|
|
166
|
+
name: "João Silva",
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### DELETE Request
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// Promise API
|
|
174
|
+
await this.httpProvider.delete("/api/users/1");
|
|
175
|
+
console.log("Usuário deletado");
|
|
176
|
+
|
|
177
|
+
// Observable API
|
|
178
|
+
this.httpProvider.delete$("/api/users/1").subscribe({
|
|
179
|
+
next: () => console.log("Usuário deletado"),
|
|
180
|
+
error: (error) => console.error("Erro ao deletar:", error),
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Cache
|
|
185
|
+
|
|
186
|
+
O provider inclui cache automático para requisições GET com limpeza automática de entradas expiradas. Por padrão, as respostas são cacheadas por 5 minutos e o cache é limpo automaticamente a cada 5 minutos.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Requisição com cache (padrão)
|
|
190
|
+
const response1 = await this.httpProvider.get("/api/users");
|
|
191
|
+
const response2 = await this.httpProvider.get("/api/users"); // Retorna do cache
|
|
192
|
+
|
|
193
|
+
// Desabilitar cache para uma requisição específica
|
|
194
|
+
const response = await this.httpProvider.get("/api/users", { cache: false });
|
|
195
|
+
|
|
196
|
+
// Cache customizado (30 segundos)
|
|
197
|
+
const response = await this.httpProvider.get("/api/users", {
|
|
198
|
+
cache: true,
|
|
199
|
+
cacheTtl: 30000,
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### Invalidação de Cache
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// Limpar cache específico
|
|
207
|
+
this.httpProvider.clearCache("/api/users");
|
|
208
|
+
|
|
209
|
+
// Limpar todo o cache
|
|
210
|
+
this.httpProvider.clearCache();
|
|
211
|
+
|
|
212
|
+
// Ver estatísticas do cache
|
|
213
|
+
const stats = this.httpProvider.getCacheStats();
|
|
214
|
+
console.log(`Cache tem ${stats.size} entradas`);
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Configuração de Headers e Autenticação
|
|
218
|
+
|
|
219
|
+
#### Headers Personalizados
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
// Definir headers para todas as requisições
|
|
223
|
+
this.httpProvider.setHeaders({
|
|
224
|
+
"X-API-Key": "your-api-key",
|
|
225
|
+
"X-Custom-Header": "custom-value",
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Ou definir headers por requisição
|
|
229
|
+
const response = await this.httpProvider.get("/api/data", {
|
|
230
|
+
headers: {
|
|
231
|
+
Authorization: "Bearer token",
|
|
232
|
+
"Content-Type": "application/json",
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### Autenticação Bearer Token
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
// Definir token de autenticação (Bearer por padrão)
|
|
241
|
+
this.httpProvider.setAuthToken("your-jwt-token");
|
|
242
|
+
|
|
243
|
+
// Ou especificar tipo de token
|
|
244
|
+
this.httpProvider.setAuthToken("your-token", "Basic");
|
|
245
|
+
|
|
246
|
+
// Limpar token
|
|
247
|
+
this.httpProvider.clearAuthToken();
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
// Definir token de autenticação
|
|
251
|
+
this.httpProvider.setAuthToken('your-jwt-token');
|
|
252
|
+
|
|
253
|
+
// Ou especificar o tipo de token
|
|
254
|
+
this.httpProvider.setAuthToken('your-token', 'Basic');
|
|
255
|
+
|
|
256
|
+
// Remover token
|
|
257
|
+
this.httpProvider.clearAuthToken();
|
|
258
|
+
|
|
259
|
+
````
|
|
260
|
+
|
|
261
|
+
### Timeout e Base URL
|
|
262
|
+
|
|
263
|
+
#### Configurar Timeout
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
// Definir timeout global (30 segundos)
|
|
267
|
+
this.httpProvider.setTimeout(30000);
|
|
268
|
+
|
|
269
|
+
// Ou por requisição
|
|
270
|
+
const response = await this.httpProvider.get('/api/slow-endpoint', {
|
|
271
|
+
timeout: 5000, // 5 segundos
|
|
272
|
+
});
|
|
273
|
+
````
|
|
274
|
+
|
|
275
|
+
#### Base URL
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// Definir base URL para todas as requisições
|
|
279
|
+
this.httpProvider.setBaseURL("https://api.example.com");
|
|
280
|
+
|
|
281
|
+
// Agora as requisições são relativas
|
|
282
|
+
const users = await this.httpProvider.get<User[]>("/users"); // https://api.example.com/users
|
|
283
|
+
const posts = await this.httpProvider.get<Post[]>("/posts"); // https://api.example.com/posts
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Interceptors
|
|
287
|
+
|
|
288
|
+
#### Request Interceptor
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
// Adicionar interceptor de request
|
|
292
|
+
const requestInterceptorId = this.httpProvider.addRequestInterceptor(
|
|
293
|
+
(config) => {
|
|
294
|
+
// Modificar config antes de enviar
|
|
295
|
+
config.headers["X-Request-ID"] = generateRequestId();
|
|
296
|
+
config.headers["X-Timestamp"] = Date.now().toString();
|
|
297
|
+
return config;
|
|
298
|
+
},
|
|
299
|
+
(error) => {
|
|
300
|
+
// Tratar erro na configuração da requisição
|
|
301
|
+
console.error("Erro no request interceptor:", error);
|
|
302
|
+
return Promise.reject(error);
|
|
303
|
+
},
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
// Remover interceptor
|
|
307
|
+
this.httpProvider.removeRequestInterceptor(requestInterceptorId);
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### Response Interceptor
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
// Adicionar interceptor de response
|
|
314
|
+
const responseInterceptorId = this.httpProvider.addResponseInterceptor(
|
|
315
|
+
(response) => {
|
|
316
|
+
// Processar resposta antes de retornar
|
|
317
|
+
console.log(
|
|
318
|
+
`Request to ${response.config.url} took ${Date.now() - response.config.timestamp}ms`,
|
|
319
|
+
);
|
|
320
|
+
return response;
|
|
321
|
+
},
|
|
322
|
+
(error) => {
|
|
323
|
+
// Tratar erros de resposta
|
|
324
|
+
if (error.response?.status === 401) {
|
|
325
|
+
// Token expirado - redirecionar para login
|
|
326
|
+
this.authService.logout();
|
|
327
|
+
}
|
|
328
|
+
return Promise.reject(error);
|
|
329
|
+
},
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
// Remover interceptor
|
|
333
|
+
this.httpProvider.removeResponseInterceptor(responseInterceptorId);
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Requisições Customizadas
|
|
337
|
+
|
|
338
|
+
#### Usando o método `request`
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
// Requisição customizada com Promise
|
|
342
|
+
const response = await this.httpProvider.request<User>({
|
|
343
|
+
method: "GET",
|
|
344
|
+
url: "/api/users",
|
|
345
|
+
params: { page: 1, limit: 10 },
|
|
346
|
+
headers: { "Custom-Header": "value" },
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// Com Observable
|
|
350
|
+
this.httpProvider
|
|
351
|
+
.request$<User>({
|
|
352
|
+
method: "POST",
|
|
353
|
+
url: "/api/users",
|
|
354
|
+
data: { name: "João", email: "joao@example.com" },
|
|
355
|
+
})
|
|
356
|
+
.subscribe((response) => console.log(response.data));
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Instâncias Múltiplas
|
|
360
|
+
|
|
361
|
+
#### Criar instância separada
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
// Criar instância com configuração específica
|
|
365
|
+
const apiClient = this.httpProvider.createInstance({
|
|
366
|
+
baseURL: "https://external-api.com",
|
|
367
|
+
timeout: 10000,
|
|
368
|
+
headers: {
|
|
369
|
+
Authorization: "Bearer external-token",
|
|
370
|
+
"X-API-Version": "v2",
|
|
371
|
+
},
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// Usar a instância específica
|
|
375
|
+
const externalData = await apiClient.get("/data");
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Tratamento de Erros
|
|
379
|
+
|
|
380
|
+
#### Com Promises
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
try {
|
|
384
|
+
const response = await this.httpProvider.get("/api/users");
|
|
385
|
+
console.log("Dados:", response.data);
|
|
386
|
+
} catch (error) {
|
|
387
|
+
if (error.response) {
|
|
388
|
+
// Erro da API (4xx, 5xx)
|
|
389
|
+
console.error("Erro da API:", error.response.status, error.response.data);
|
|
390
|
+
} else if (error.request) {
|
|
391
|
+
// Erro de rede
|
|
392
|
+
console.error("Erro de rede:", error.message);
|
|
393
|
+
} else {
|
|
394
|
+
// Outro erro
|
|
395
|
+
console.error("Erro:", error.message);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
#### Com Observables
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
this.httpProvider.get$<User[]>("/api/users").subscribe({
|
|
404
|
+
next: (response) => {
|
|
405
|
+
console.log("Usuários carregados:", response.data);
|
|
406
|
+
},
|
|
407
|
+
error: (error) => {
|
|
408
|
+
if (error.response) {
|
|
409
|
+
// Erro da API
|
|
410
|
+
this.notificationService.showError(
|
|
411
|
+
`Erro ${error.response.status}: ${error.response.data.message}`,
|
|
412
|
+
);
|
|
413
|
+
} else {
|
|
414
|
+
// Erro de rede
|
|
415
|
+
this.notificationService.showError("Erro de conexão");
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
complete: () => {
|
|
419
|
+
console.log("Requisição finalizada");
|
|
420
|
+
},
|
|
421
|
+
});
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Casos de Uso Avançados
|
|
425
|
+
|
|
426
|
+
#### Retry com Observable
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
import { retry, delay } from "rxjs/operators";
|
|
430
|
+
|
|
431
|
+
this.httpProvider
|
|
432
|
+
.get$<Data>("/api/unstable-endpoint")
|
|
433
|
+
.pipe(
|
|
434
|
+
retry({
|
|
435
|
+
count: 3,
|
|
436
|
+
delay: (error, retryCount) => {
|
|
437
|
+
console.log(`Tentativa ${retryCount} falhou, tentando novamente...`);
|
|
438
|
+
return timer(1000 * retryCount); // Delay crescente
|
|
439
|
+
},
|
|
440
|
+
}),
|
|
441
|
+
)
|
|
442
|
+
.subscribe({
|
|
443
|
+
next: (response) => console.log("Dados:", response.data),
|
|
444
|
+
error: (error) => console.error("Falhou após 3 tentativas:", error),
|
|
445
|
+
});
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
#### Cache com Interceptors
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
// Interceptor para cache simples
|
|
452
|
+
const cache = new Map();
|
|
453
|
+
|
|
454
|
+
this.httpProvider.addResponseInterceptor((response) => {
|
|
455
|
+
// Cache GET requests
|
|
456
|
+
if (response.config.method?.toLowerCase() === "get") {
|
|
457
|
+
cache.set(response.config.url, {
|
|
458
|
+
data: response.data,
|
|
459
|
+
timestamp: Date.now(),
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
return response;
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
this.httpProvider.addRequestInterceptor((config) => {
|
|
466
|
+
// Verificar cache para GET requests
|
|
467
|
+
if (config.method?.toLowerCase() === "get") {
|
|
468
|
+
const cached = cache.get(config.url);
|
|
469
|
+
if (cached && Date.now() - cached.timestamp < 300000) {
|
|
470
|
+
// 5 minutos
|
|
471
|
+
// Retornar dados do cache (isso cancelará a requisição real)
|
|
472
|
+
return Promise.reject({
|
|
473
|
+
__cached: true,
|
|
474
|
+
data: cached.data,
|
|
475
|
+
config,
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return config;
|
|
480
|
+
});
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
#### Upload de Arquivos
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
const formData = new FormData();
|
|
487
|
+
formData.append("file", file);
|
|
488
|
+
formData.append("metadata", JSON.stringify({ name: "document.pdf" }));
|
|
489
|
+
|
|
490
|
+
const response = await this.httpProvider.post<UploadResult>(
|
|
491
|
+
"/api/upload",
|
|
492
|
+
formData,
|
|
493
|
+
{
|
|
494
|
+
headers: {
|
|
495
|
+
"Content-Type": "multipart/form-data",
|
|
496
|
+
},
|
|
497
|
+
onUploadProgress: (progressEvent) => {
|
|
498
|
+
const percentCompleted = Math.round(
|
|
499
|
+
(progressEvent.loaded * 100) / progressEvent.total,
|
|
500
|
+
);
|
|
501
|
+
console.log(`Upload: ${percentCompleted}%`);
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
);
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## Interface Completa
|
|
508
|
+
|
|
509
|
+
```typescript
|
|
510
|
+
interface HttpProviderInterface {
|
|
511
|
+
// Métodos HTTP Promise-based
|
|
512
|
+
get<T>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
|
|
513
|
+
post<T>(
|
|
514
|
+
url: string,
|
|
515
|
+
data?: any,
|
|
516
|
+
config?: HttpRequestConfig,
|
|
517
|
+
): Promise<HttpResponse<T>>;
|
|
518
|
+
put<T>(
|
|
519
|
+
url: string,
|
|
520
|
+
data?: any,
|
|
521
|
+
config?: HttpRequestConfig,
|
|
522
|
+
): Promise<HttpResponse<T>>;
|
|
523
|
+
patch<T>(
|
|
524
|
+
url: string,
|
|
525
|
+
data?: any,
|
|
526
|
+
config?: HttpRequestConfig,
|
|
527
|
+
): Promise<HttpResponse<T>>;
|
|
528
|
+
delete<T>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
|
|
529
|
+
head<T>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
|
|
530
|
+
options<T>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
|
|
531
|
+
request<T>(config: HttpRequestConfig): Promise<HttpResponse<T>>;
|
|
532
|
+
|
|
533
|
+
// Métodos HTTP Observable-based
|
|
534
|
+
get$<T>(url: string, config?: HttpRequestConfig): Observable<HttpResponse<T>>;
|
|
535
|
+
post$<T>(
|
|
536
|
+
url: string,
|
|
537
|
+
data?: any,
|
|
538
|
+
config?: HttpRequestConfig,
|
|
539
|
+
): Observable<HttpResponse<T>>;
|
|
540
|
+
put$<T>(
|
|
541
|
+
url: string,
|
|
542
|
+
data?: any,
|
|
543
|
+
config?: HttpRequestConfig,
|
|
544
|
+
): Observable<HttpResponse<T>>;
|
|
545
|
+
patch$<T>(
|
|
546
|
+
url: string,
|
|
547
|
+
data?: any,
|
|
548
|
+
config?: HttpRequestConfig,
|
|
549
|
+
): Observable<HttpResponse<T>>;
|
|
550
|
+
delete$<T>(
|
|
551
|
+
url: string,
|
|
552
|
+
config?: HttpRequestConfig,
|
|
553
|
+
): Observable<HttpResponse<T>>;
|
|
554
|
+
head$<T>(
|
|
555
|
+
url: string,
|
|
556
|
+
config?: HttpRequestConfig,
|
|
557
|
+
): Observable<HttpResponse<T>>;
|
|
558
|
+
options$<T>(
|
|
559
|
+
url: string,
|
|
560
|
+
config?: HttpRequestConfig,
|
|
561
|
+
): Observable<HttpResponse<T>>;
|
|
562
|
+
request$<T>(config: HttpRequestConfig): Observable<HttpResponse<T>>;
|
|
563
|
+
|
|
564
|
+
// Interceptors
|
|
565
|
+
addRequestInterceptor(onFulfilled?, onRejected?): number;
|
|
566
|
+
addResponseInterceptor(onFulfilled?, onRejected?): number;
|
|
567
|
+
removeRequestInterceptor(interceptorId: number): void;
|
|
568
|
+
removeResponseInterceptor(interceptorId: number): void;
|
|
569
|
+
|
|
570
|
+
// Configuração
|
|
571
|
+
createInstance(config?: HttpClientConfig): HttpProviderInterface;
|
|
572
|
+
setBaseURL(baseURL: string): void;
|
|
573
|
+
setTimeout(timeout: number): void;
|
|
574
|
+
setHeaders(headers: Record<string, string>): void;
|
|
575
|
+
setAuthToken(token: string, type?: string): void;
|
|
576
|
+
clearAuthToken(): void;
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
## Boas Práticas
|
|
581
|
+
|
|
582
|
+
1. **Use Observables para operações complexas**: Quando precisar de retry, cancelamento, ou combinação com outras streams.
|
|
583
|
+
|
|
584
|
+
2. **Configure timeouts apropriados**: Defina timeouts realistas baseados na natureza da API.
|
|
585
|
+
|
|
586
|
+
3. **Centralize configuração**: Use interceptors para adicionar headers comuns, logging, etc.
|
|
587
|
+
|
|
588
|
+
4. **Trate erros adequadamente**: Implemente tratamento de erro específico para diferentes tipos de falha.
|
|
589
|
+
|
|
590
|
+
5. **Use instâncias separadas**: Para APIs externas com configurações diferentes.
|
|
591
|
+
|
|
592
|
+
6. **Documente suas APIs**: Use JSDoc nos métodos que consomem o HTTP provider.
|
|
593
|
+
|
|
594
|
+
7. **Considere cache**: Para dados que não mudam frequentemente, implemente cache com interceptors.
|
|
595
|
+
|
|
596
|
+
Este provider oferece uma base sólida e flexível para todas as suas necessidades de comunicação HTTP!
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentType = exports.HttpMethod = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* HTTP methods supported
|
|
6
|
+
*/
|
|
7
|
+
var HttpMethod;
|
|
8
|
+
(function (HttpMethod) {
|
|
9
|
+
HttpMethod["GET"] = "GET";
|
|
10
|
+
HttpMethod["POST"] = "POST";
|
|
11
|
+
HttpMethod["PUT"] = "PUT";
|
|
12
|
+
HttpMethod["PATCH"] = "PATCH";
|
|
13
|
+
HttpMethod["DELETE"] = "DELETE";
|
|
14
|
+
HttpMethod["HEAD"] = "HEAD";
|
|
15
|
+
HttpMethod["OPTIONS"] = "OPTIONS";
|
|
16
|
+
})(HttpMethod || (exports.HttpMethod = HttpMethod = {}));
|
|
17
|
+
/**
|
|
18
|
+
* Content types for HTTP requests
|
|
19
|
+
*/
|
|
20
|
+
var ContentType;
|
|
21
|
+
(function (ContentType) {
|
|
22
|
+
ContentType["JSON"] = "application/json";
|
|
23
|
+
ContentType["FORM_URLENCODED"] = "application/x-www-form-urlencoded";
|
|
24
|
+
ContentType["FORM_DATA"] = "multipart/form-data";
|
|
25
|
+
ContentType["TEXT"] = "text/plain";
|
|
26
|
+
ContentType["XML"] = "application/xml";
|
|
27
|
+
})(ContentType || (exports.ContentType = ContentType = {}));
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var HttpModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.HttpModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const http_provider_1 = require("./http.provider");
|
|
13
|
+
const http_token_1 = require("./http.token");
|
|
14
|
+
const axios_http_module_1 = require("./implementations/axios/axios.http.module");
|
|
15
|
+
let HttpModule = HttpModule_1 = class HttpModule {
|
|
16
|
+
/**
|
|
17
|
+
* Configure HttpModule with an Axios instance or AxiosRequestConfig.
|
|
18
|
+
* This will import the implementation-specific module (currently Axios).
|
|
19
|
+
*/
|
|
20
|
+
static forRoot(config) {
|
|
21
|
+
return {
|
|
22
|
+
module: HttpModule_1,
|
|
23
|
+
imports: [axios_http_module_1.HttpImplementationAxiosModule.forRoot(config)],
|
|
24
|
+
providers: [
|
|
25
|
+
{
|
|
26
|
+
provide: http_token_1.HTTP_PROVIDER,
|
|
27
|
+
useClass: http_provider_1.HttpProvider,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
exports: [http_token_1.HTTP_PROVIDER],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
exports.HttpModule = HttpModule;
|
|
35
|
+
exports.HttpModule = HttpModule = HttpModule_1 = __decorate([
|
|
36
|
+
(0, common_1.Module)({})
|
|
37
|
+
], HttpModule);
|