Suele ocurrir que un front-end consume más de un backend diferente, con diferentes URLs, que eventualmente podrían utilizar diferentes tokens o necesitar cada uno de una manipulación diferente de la request por parte del interceptor.
Manipulando múltiples tipos de solicitudes
Es posible crear un contexto para los interceptores para indicar si queremos que X endpoint sea interceptado o no.
1. Importando clases necesarias
Para esto, importando HttpContextToken y HttpContext desde @angular/common/http vamos a crear una función para validar si el endpoint necesita o no la inyección de un token.
Creamos la constante ADD_TOKEN que indicará si el endpoint necesita de un token o no. Por defecto, todos los endpoints necesitan un token. La función addToken() hará que no se inyecte el token cuando no se requiere.
También puedes utilizar la lógica inversa, que ningún endpoint por defecto utilice el token y solo habilitar manualmente los que si lo requieren.
2. Creando el contexto para las solicitudes
En la lógica del interceptor, colocamos un IF para validar si la petición necesita o no del token.
Agregamos como argumento context a las opciones de la solicitud. El endpoint de Login no suele necesitar de un token para funcionar, es el único que excluimos del uso del interceptor.
¡Con esto creo que puedo modificar mis propios proyectos y adaptarlos a mis necesidades, buenísimo!
El tema del contexto y los interceptores is crazy!
Justo necesitaba interceptores, las ultimas 2 clases maravillosas
Como así, me confunde el profesor en el minuto 2:59. En la clase anterior se supone que el interceptor va a estar a la escucha de cualquier petición sino se le agrega un contexto pero en ese minuto de esta clase dice todo lo contrario, que al no enviar ningún contexto no todas van a estar siendo evaluadas por el interceptor. No se supone que al poner contexto en una petición es para que el interceptor este al pendiente de solo esa petición y no de todas las demás peticiones?.....O entendí mal?. No se si alguien me pueda explicar esta parte
se refería a que en ese momento antes de integrar el interceptor no hay contexto y que se evaluarían todas, para evitar eso se implementa el contexto
Una analogía que se me ocurre para entenderlo, y espero no estar equivocado es la siguiente: podemos ver CHECK_TIME como una bandera que va a controlar si el interceptor evaluará una petición o no, usando un condicional. Y podemos ver a checkTime() como la función o herramienta para cambiar el valor de dicha bandera. Como su valor por defecto es False, ninguna petición será interceptada. Cuando se usa checkTime(), el valor cambia a True y la petición será interceptada.
En ese instante, el profesor dice que "todas las peticiones no van a ser evaluadas (interceptadas) por el interceptor de tiempo, a menos de que empecemos a enviarle ese contexto". Esto lo dice porque al momento de crear el contexto en time.interceptor, lo hicimos de la siguiente forma:
Al ser false el valor por defecto, estamos codificando el interceptor de forma tal que no se ejecute en ninguna petición, excepto en aquellas que peticiones que envíen el contexto (o cambien este valor a true). Esto se hace en la siguiente linea:
Esto hace que el siguiente condicional permita interceptar la petición solo cuando se use checkTime() como contexto:
if(request.context.get(CHECK_TIME))
Espero haberme dejado entender
y si tengo mas de un interceptor y quiero mandar mas de un contexto, ¿se puede?
Por ahora, según la API puedes tener múltiples interceptores, pero solo un contexto por cada request, podrías tener contextos más genéricos que corran en multiples interceptores.
Tenia conocimiento de los interceptors, pero estas ultimas 2 clases me volaron la cabeza.
Sin duda la mejor forma de aprender es aprendiendo a desaprender.
Cual es la la mejor practica; con un header o por contexto?
Vale siguiendo, la misma fórmula de interceptores para aquellas rutas que deban agregar un token de autenticación, por ejemplo, el endpoint donde solicitamos el profile del usuario logueado, he realizado lo siguiente, para no estar metiendo el token en todas las peticiones:
import{Injectable}from'@angular/core';import{HttpClient,HttpHeaders}from'@angular/common/http';import{ switchMap, tap }from'rxjs/operators';import{Auth}from'../models/auth.model';import{User}from'../models/user.model';import{TokenService}from'./token.service';import{ addTokenHeader }from'../interceptors/add-token.interceptor';@Injectable({providedIn:'root'})exportclassAuthService{private apiUrl ='https://young-sands-07814.herokuapp.com';constructor(privatehttp:HttpClient,privatetokenService:TokenService){}login(email: string,password: string){returnthis.http.post<Auth>(`${this.apiUrl}/api/auth/login`,{email, password}).pipe(tap(response=>this.tokenService.saveToken(response.access_token)));}getProfile(){// el interceptor se encarga de añadir el tokenreturnthis.http.get<User>(`${this.apiUrl}/api/auth/profile`,{context:addTokenHeader()});}loginAndGetProfile(email: string,password: string){returnthis.login(email, password).pipe(switchMap(()=>this.getProfile()))}}
Ahora la petición '...api/auth/profile' tiene el contexto '{context: addTokenHeader()}', que resuelve poner el 'AUTH_TOKEN' a true para que en el if del interceptor 'if(request.context.get(AUTH_TOKEN)) {' solucione adherir el
'headers: request.headers.set('Authorization', Bearer ${token})' y con ello pasar la lógica del servidor para endpoints con autorización y sólo para aquellos endpoints donde se necesite.
Entiendo como contexto de un interceptor como un paramento de headers para pasar y no pasar por los interceptors?
El contexto de un interceptor sirve para ignorar ciertas rutas que no quieres que sean interceptadas para no agregar un header.
Es opcional, tal vez tu app no lo necesite y todos los endpoints que consumes necesitan un token.
Saludos
Gracias
Por que no me deja importar HttpContext, me sale Cannot find name 'HttpContexToken', tengo la version 10 de angular.
Revisa los imports del modulo de app, puede ser de ayuda. Ahí deberías importar el Http module
Vuelvo a leer lo que escribiste, lento. Te haz comido una letra "t" en HttpContextToken