1 | ### RxFeign (Request en Sevidor y Cliente)
|
2 | #### IMPORTANTE
|
3 | Este primer release solo tiene unas cuantas funcionalidades basicas,
|
4 | si necesitas hacer request con mucha mas configuracion mejor busca otra libreria.
|
5 | #### Motivacion
|
6 | realizar peticiones por medio de anotaciones
|
7 | #### Instalacion
|
8 | ```sh
|
9 | $ yarn add axios rxjs rxfeign
|
10 |
|
11 | or
|
12 |
|
13 | $ npm install --save axios rxjs rxfeign
|
14 | ```
|
15 |
|
16 | ```typescript
|
17 | import { Get , Client,PathParam, Query, HttpObservable } from 'rxfeign';
|
18 | ```
|
19 |
|
20 | #### Anotaciones
|
21 | - *@Client*
|
22 | recibe dos tipos de parametro, un string o un objeto
|
23 | * string : url base (http://domain/)
|
24 | * objecto : este objeto por el momento solo tiene dos atributos, la url base y los headers
|
25 | globales para todos los request que se hacen dentro de esa clase.
|
26 | Si no se define el header __Content-Type__ por defecto es __application/json__.
|
27 |
|
28 | ```typescript
|
29 | @Client({
|
30 | url: 'https://jsonplaceholder.typicode.com/posts/',
|
31 | headers:{} // opcional
|
32 | })
|
33 | export class Post{}
|
34 |
|
35 | o
|
36 |
|
37 | @Client('https://jsonplaceholder.typicode.com/posts/')
|
38 | export class Post{}
|
39 | ```
|
40 |
|
41 | - *@Get/@Post/@Put/@Patch/@Delete*
|
42 | recibe por parametro la url que ira junto con la url base y el segundo parametro sera
|
43 | la clase en la que se encuentra.
|
44 |
|
45 | ```typescript
|
46 | @Client('https://jsonplaceholder.typicode.com/posts/')
|
47 | export class Post {
|
48 |
|
49 | constructor(){}
|
50 |
|
51 | @Get('{id}')
|
52 | public findById(
|
53 | @PathParam('id') id: number,
|
54 | ): HttpObservable<PostModel> {}
|
55 | }
|
56 | ```
|
57 | - *@PathParam*
|
58 | recibe por parametro el string que contiene el id que coincide con la expresion en la url como se ve en el ejemplo anterior. Este parametro es opcional, si no se define entonces se agregara al final de la url.
|
59 |
|
60 | - *@Query*
|
61 | recibe por parametro un string con el nombre que ira el query en la url.
|
62 | el resultado del siguiente ejemplo seria :
|
63 | __/1?attr=holaa__
|
64 |
|
65 | ```typescript
|
66 | @Get('{id}')
|
67 | public findById(
|
68 | @PathParam('id') id: number, // 1
|
69 | @Query('attr') value: number|string // holaa
|
70 | ): HttpObservable<PostModel> {}
|
71 | ```
|
72 | si el parametro que se pasa es un objeto, se mapeara cada atributo valor en la url
|
73 | y no se define el string que se pasa por parametro.
|
74 | la salida del siguiente ejemplo seria la siguiente:
|
75 | __/1?attr=holaa&name=lord&id=99__
|
76 |
|
77 | ```typescript
|
78 |
|
79 | class PostModel{
|
80 | constructor(
|
81 | public name: string,
|
82 | public id: string
|
83 | ){}
|
84 | }
|
85 |
|
86 | @Get('{id}')
|
87 | public findById(
|
88 | @PathParam('id') id: number, // 1
|
89 | @Query('attr') value: number|string // holaa
|
90 | @Query() value: PostModel // new PostModel('lord',99)
|
91 | ): HttpObservable<PostModel> {}
|
92 | ```
|
93 |
|
94 | - *@Body*
|
95 | Esta anotacion no recibe parametros, el objeto que se reciba por parametro en el metodo
|
96 | sera el body de la peticion.
|
97 |
|
98 | Ademas de eso, tambien esta la anotacion *@PathParamProperty* la cual permite
|
99 | definir el parametro que ira en la url atra vez del objecto que ira en el body.
|
100 | La salida del siguiente ejemplo sera la siguiente:
|
101 | __url/88__
|
102 | ```json
|
103 | {
|
104 | "id": 88,
|
105 | "name": "Bodyy"
|
106 | }
|
107 | ```
|
108 |
|
109 | ```typescript
|
110 |
|
111 | class PostModel{
|
112 |
|
113 | @PathParamProperty()
|
114 | public id: string
|
115 |
|
116 | public name: string
|
117 |
|
118 | constructor(id, name){
|
119 | this.name = name
|
120 | this.id = id
|
121 | }
|
122 | }
|
123 |
|
124 | @Post('{id}')
|
125 | public create(
|
126 | @Body object: PostModel // new PostModel(88,"Bodyy")
|
127 | ): HttpObservable<PostModel> {}
|
128 | ```
|
129 |
|
130 | - *@Mapper*:
|
131 | Es el map de rxjs. Lo que retorne esta funcion, sera lo que retorna el metodo con la anotacion.
|
132 |
|
133 | ```typescript
|
134 | export class Class {
|
135 | public static map(body): number{
|
136 | return body.id as number
|
137 | }
|
138 |
|
139 | @Mapper(Class.map)
|
140 | @Post('{id}')
|
141 | public create(
|
142 | @Body object: PostModel // new PostModel(88,"Bodyy")
|
143 | ): HttpObservable<number> {}
|
144 | }
|
145 | ```
|
146 |
|
147 | - *@Before*:
|
148 | Este metodo permite interceptar el request antes de enviar la peticion y hacer lo que se quiera.
|
149 | se llamara antes que los interceptores (ya veremos los interceptores).
|
150 | el metodo que se pasa por parametro recibe un objeto de tipo Request que esta definido de la siguiente manera:
|
151 |
|
152 | ```typescript
|
153 | export interface Request_ {
|
154 | readonly method: string,
|
155 | body: any,
|
156 | readonly headers: HeadersHttp,
|
157 | readonly url: string
|
158 | }
|
159 | ```
|
160 | ```typescript
|
161 | export class Class {
|
162 | public static before(req: Request_): Request_{
|
163 | req.headers.set("otro","header")
|
164 | req.body = {
|
165 | ...body,
|
166 | otro:"atributo en el body"
|
167 | }
|
168 | return req
|
169 | }
|
170 |
|
171 | @Before(Class.before)
|
172 | @Post('{id}')
|
173 | public create(
|
174 | @Body object: PostModel // new PostModel(88,"Bodyy")
|
175 | ): HttpObservable<number> {}
|
176 | }
|
177 | ```
|
178 |
|
179 | - *@Headers*
|
180 | Permite establecer headers especificos para ese request. recibe un objeto.
|
181 | ```typescript
|
182 | @Headers({
|
183 | "ApiKey":"anwb0ted4132"
|
184 | })
|
185 | @Post('{id}')
|
186 | public create(
|
187 | @Body object: PostModel // new PostModel(88,"Bodyy")
|
188 | ): HttpObservable<number> {}
|
189 | ```
|
190 |
|
191 | - *@HandlerError*
|
192 | Este metodo que se pasa por parametro recibe una instancia de tipo *__AxiosError__* y debe retornar la instancia que sera lanzada como excepcion.
|
193 | se espera que el usuario tenga establecido un manejador de excepciones global.
|
194 | se puede lanzar una excepcion custom heredando de __HttpRequestException__
|
195 | si no se define esta anotacion y hay un error entonces se lanzara una excepcion de tipo __HttpRequestException__
|
196 | el cual esta definido de la siguiente manera:
|
197 |
|
198 | ```typescript
|
199 | export class HttpRequestException {
|
200 | constructor(
|
201 | public error: string,
|
202 | public statusCode: number,
|
203 | public message: string,
|
204 | ) {}
|
205 | }
|
206 | ```
|
207 |
|
208 |
|
209 | ```typescript
|
210 | export class Class {
|
211 |
|
212 | public static error<MyClass extends HttpRequestException>(error: AxiosError): MyClase {
|
213 | if(error.response.status === 404){
|
214 | return new NotFoundHttp(...)
|
215 | }else{
|
216 | return new MyClass(...)
|
217 | }
|
218 | }
|
219 |
|
220 | @HandlerError(Class.error)
|
221 | @Post('{id}')
|
222 | public create(
|
223 | @Body object: PostModel // new PostModel(88,"Bodyy")
|
224 | ): HttpObservable<number> {}
|
225 | }
|
226 | ```
|
227 |
|
228 | - *addInterceptor*
|
229 | Este es un array el cual admite callbacks que reciben por parametro una clase que implemente la interfaz __HttpInterceptor__.
|
230 | Los interceptors se deben agregar en el main de la aplicacion.
|
231 | Estos interceptores se llaman en todos los request que se realicen y despues de la anotacion *@Before* que este definida en los metodos. Es similar a la anotacion @Before solo que esta forma es global, todos los request pasaran por ahi.
|
232 |
|
233 | ```typescript
|
234 |
|
235 |
|
236 | export class Main implements HttpInterceptor {
|
237 |
|
238 | public start(): void{
|
239 | addInterceptors(Main)
|
240 | }
|
241 |
|
242 | public intercep(req: Request_): Request_{
|
243 | console.log(req.url)
|
244 | return req
|
245 | }
|
246 | }
|
247 | ```
|