Get into the habit of writing together! This is the sixth day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event
In the previous article , Using Api Proxy in Angular , we dealt with the problem of the local joint debugging interface and used the proxy.
Our interfaces are written and processed separately. In actual development projects, there are many interfaces, some of which require login credentials and some do not. If one interface is not handled properly, can we consider intercepting and encapsulating the request?
This article implements it.
Differentiate the environment
We need to intercept services in different environments. When using angular-cli
to generate a project, it has automatically distinguished the environment, in the app/enviroments
directory:
environments
├── environment.prod.ts // 生产环境使用的配置
└── environment.ts // 开发环境使用的配置
复制代码
We modify the development environment as follows:
// enviroment.ts
export const environment = {
baseUrl: '',
production: false
};
复制代码
baseUrl
It is a field added to the front of the request when you make a request, and it points to the address you want to request. I didn't add anything, in fact, it was equivalent to adding http://localhost:4200
the content of .
Of course, the content you add here should be adjusted to match the content added on your agent, and readers can think and verify by themselves
add interceptor
We generate a service http-interceptor.service.ts
interceptor service, and we want every request to go through this service.
// http-interceptor.service.ts
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpHandler,
HttpInterceptor, // 拦截器
HttpRequest, // 请求
} 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) => {
// 处理响应的数据
console.log(response)
},
(error: any) => {
// 处理错误的数据
console.log(error)
}
)
)
}
}
复制代码
For the interceptor to take effect, we have app.module.ts
to inject it on :
// app.module.ts
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
// 拦截器服务
import { HttpInterceptorService } from './services/http-interceptor.service';
providers: [
// 依赖注入
{
provide: HTTP_INTERCEPTORS,
useClass: HttpInterceptorService,
multi: true,
}
],
复制代码
verify
So far, we have successfully implemented the interceptor. If you run npm run dev
, you will see the following message on the console:
To verify that content credentials are required to access the content, here I tried using [post] https://jimmyarea.com/api/private/leave/message
the interface of , and got the following error:
The backend has already processed this interface and requires credentials to operate, so an error is reported directly 401
.
Well, here comes the question. After we log in, how do we need to bring our credentials?
As follows, we modify the content of the interceptor:
let secureReq: HttpRequest<any> = req;
// ...
// 使用 localhost 存储用户凭证,在请求头带上
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 localstorage
the reset value, otherwise an error will be reported all the localstorage
time.
【End】✅