In the previous article, using Api proxy in Angular, we dealt with the problem of local joint debugging interface and used proxy.
Our interfaces are written and processed separately. In actual development projects, there are many interfaces, some of which require login credentials, and some of which do not. If each interface is not handled properly, can we consider intercepting and encapsulating the request? [Recommended related tutorials: "Angular Tutorial"]
This article will be implemented.
To distinguish between environments
, we need to intercept services in different environments. When using angular-cli
to generate a project, it has automatically distinguished the environments. In the app/enviroments
directory:
environments ├── environment.prod.ts // Configuration used in the production environment └── environment.ts // Configuration used in the development environment
Let’s modify the development environment:
// enviroment.ts export const environment = { baseUrl: '', production: false };
baseUrl
is a field added in front of the request when you make the request. It points to the address you want to request. I didn't add anything. In fact, it was equivalent to adding the content of http://localhost:4200
.
Of course, the content you add here must be adjusted to match the content added on your proxy. Readers can think and verify by themselves.
Add an interceptor.
We generate the service http-interceptor.service.ts
interceptor service. We hope that every request will go through this service.
// http-interceptor.service.ts import { Injectable } from '@angular/core'; import { HttpEvent, HttpHandler, HttpInterceptor, // Interceptor HttpRequest, // Request} from '@angular/common/http'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; import { environment } from 'src/environments/environment'; @Injectable({ providedIn: 'root' }) export class HttpInterceptorService implements HttpInterceptor { constructor() { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { let secureReq: HttpRequest<any> = req; secureReq = secureReq.clone({ url: environment.baseUrl + req.url }); return next.handle(secureReq).pipe( tap( (response: any) => { // Process the response data console.log(response) }, (error: any) => { // Handle error data console.log(error) } ) ) } }
For the interceptor to take effect, we have to inject it on app.module.ts
:
// app.module.ts import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; //Interceptor service import { HttpInterceptorService } from './services/http-interceptor.service'; providers: [ // Dependency injection { provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorService, multi: true, } ],
Verification
at this point, we have successfully implemented the interceptor. If you run npm run dev
, you will see the following message on the console:
To verify whether content credentials are required to access the content, here I used the [post] https://jimmyarea.com/api/private/leave/message
interface to try and got the following error:
The backend has already processed that this interface requires credentials to operate, so an error 401
is reported directly.
So, here comes the problem. After we log in, how do we need to bring our credentials?
As follows, we modify the interceptor content:
let secureReq: HttpRequest<any> = req; // ... // Use localhost to store user credentials in the request header if (window.localStorage.getItem('ut')) { let token = window.localStorage.getItem('ut') || '' secureReq = secureReq.clone({ headers: req.headers.set('token', token) }); } // ...
The validity period of this certificate requires readers to judge whether the validity period is valid when entering the system, and then consider resetting the value of localstorage
, otherwise errors will always be reported. This is also very simple. The relevant encapsulation of localstorage
is convenient for operation. Yes~
[End]