Angular 5 HttpClient无法捕获过期Token返回的401错误响应
Hey there! Let's figure out why you're not catching that expired token 401 error in Angular 5. I've run into similar issues before, so here are the most common fixes to get that error logged and handled properly:
1. Check Your HTTP Interceptor (Most Likely Culprit)
If you're using a custom HTTP interceptor to attach the OAuth token to requests, it's easy to accidentally "swallow" the error without re-throwing it. Angular's interceptors sit between your request and the server, so if you handle the error there but don't pass it along, your component's subscribe error callback will never see it.
Here's how to adjust your interceptor to log the error and re-throw it:
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpErrorResponse } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/catch'; @Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> { // Clone the request and add your token header const authRequest = req.clone({ headers: req.headers.set('Authorization', `Bearer ${yourTokenVariable}`) }); // Handle the request and catch errors return next.handle(authRequest).catch((error: HttpErrorResponse) => { // First, log the error details console.error('Interceptor caught 401 error:', error); console.error('Error message:', error.error); // This should show your backend's invalid token message // Critical: Re-throw the error so your component's subscribe can pick it up return Observable.throw(error); }); } }
Don't forget to register the interceptor in your app module's providers array:
@NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ] }) export class AppModule { }
2. Verify Spring Backend CORS Configuration
If your backend's CORS settings are misconfigured, browsers will block access to the 401 error details, even if the server sends them. Make sure your Spring setup allows:
- Your Angular app's origin
- Custom headers like
Authorization - Exposing error response headers (if needed)
Here's a basic Spring CORS configuration example:
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://your-angular-app-url:4200") // Replace with your app's URL .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .exposedHeaders("Authorization"); // Expose headers your app needs to access } }
If you're using Spring Security, add .cors() to your security chain to enable CORS handling:
@Override protected void configure(HttpSecurity http) throws Exception { http.cors() .and() // Rest of your security configuration... }
3. Confirm Error Response Format
Check your browser's Network tab (in DevTools) to see what the backend actually returns when the token is expired. If the response isn't valid JSON, Angular might struggle to parse it into an error object. Make sure your Spring backend sends a properly formatted JSON response with the error details, like:
{ "error": "invalid_token", "error_description": "Token has expired" }
4. Check for Global Error Handlers
If you have a custom ErrorHandler registered globally, it might be catching the error before your component's subscribe does. Ensure that your global handler re-throws the error (or at least logs it) so it propagates down:
import { ErrorHandler, Injectable } from '@angular/core'; @Injectable() export class GlobalErrorHandler implements ErrorHandler { handleError(error: any): void { console.error('Global error caught:', error); // Re-throw the error so component-level handlers can pick it up throw error; } }
Register it in your app module:
@NgModule({ providers: [{ provide: ErrorHandler, useClass: GlobalErrorHandler }] }) export class AppModule { }
Once you fix these issues, your component's subscribe error callback should finally catch the 401 error. From there, you can log the details and implement token refresh or redirect to the login page as needed!
内容的提问来源于stack exchange,提问作者Philipp Fock

