You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 19中如何禁用HTTP_INTERCEPTORS以正常请求Youtube API

问题背景与现象

应用环境与功能

基于Angular 19和.NET后端开发,需从Youtube获取视频数据,同时具备登录注册功能并使用HTTP_INTERCEPTORS。

问题描述

启用main.ts中的HTTP_INTERCEPTORS后,Youtube API请求失效;注释该拦截器配置后,请求恢复正常。

main.ts中的HTTP_INTERCEPTORS配置:

{
  provide: HTTP_INTERCEPTORS,
  useClass: JwtInterceptor,
  multi: true,
},

Youtube请求返回的错误信息:

{
    "headers": {
        "normalizedNames": {},
        "lazyUpdate": null
    },
    "status": 401,
    "statusText": "OK",
    "url": "https://www.googleapis.com/youtube/v3/playlistItems?key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&part=snippet&maxResults=12&playlistId=PLPvjlyTckx7OhGYE9JZw9Q1MYP_n-u-8V",
    "ok": false,
    "name": "HttpErrorResponse",
    "message": "Http failure response for https://www.googleapis.com/youtube/v3/playlistItems?key=xxxxxxxxxxxxxxxxxxxxxxxx&part=snippet&maxResults=12&playlistId=PLPvjlyTckx7OhGYE9JZw9Q1MYP_n-u-8V: 401 OK",
    "error": {
        "error": {
            "code": 401,
            "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
            "errors": [
                {
                    "message": "Invalid Credentials",
                    "domain": "global",
                    "reason": "authError",
                    "location": "Authorization",
                    "locationType": "header"
                }
            ],
            "status": "UNAUTHENTICATED"
        }
    }
}

JwtInterceptor代码:

export class JwtInterceptor implements HttpInterceptor {
  private accountService = inject(AccountService);

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    this.accountService.user$.pipe(take(1)).subscribe({
      next: user => {
        if (user) {
          // Clone from the coming request and add Authorization header to that
          request = request.clone({
            setHeaders: {
              Authorization: `Bearer ${user.jwt}`
            }
          });
        }
      }
    })
    return next.handle(request);
  }
}

疑问

如何在请求Youtube数据时禁用该HTTP_INTERCEPTORS?


解决方案

方法1:修改拦截器,排除Youtube域名请求

直接在JwtInterceptor中判断请求URL是否属于Youtube API域名,匹配则跳过Authorization头的添加:

export class JwtInterceptor implements HttpInterceptor {
  private accountService = inject(AccountService);

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    // 过滤Youtube API请求
    const isYoutubeRequest = request.url.includes('googleapis.com/youtube');
    if (isYoutubeRequest) {
      return next.handle(request);
    }

    // 修复原拦截器异步订阅导致的请求提前发送问题
    return this.accountService.user$.pipe(
      take(1),
      switchMap(user => {
        let modifiedRequest = request;
        if (user) {
          modifiedRequest = request.clone({
            setHeaders: {
              Authorization: `Bearer ${user.jwt}`
            }
          });
        }
        return next.handle(modifiedRequest);
      })
    );
  }
}

方法2:为Youtube请求添加自定义标记,拦截器识别后跳过

  1. 发送Youtube请求时添加自定义标记头:
// 发送Youtube请求的代码示例
this.httpClient.get('https://www.googleapis.com/youtube/v3/playlistItems', {
  params: { /* 你的请求参数 */ },
  headers: new HttpHeaders({ 'Skip-Jwt-Interceptor': 'true' })
});
  1. 修改拦截器识别并跳过标记请求:
export class JwtInterceptor implements HttpInterceptor {
  private accountService = inject(AccountService);

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    // 检查是否存在跳过拦截器的标记
    const skipInterceptor = request.headers.get('Skip-Jwt-Interceptor') === 'true';
    if (skipInterceptor) {
      // 移除自定义标记,避免传递给第三方API
      const cleanedRequest = request.clone({
        headers: request.headers.delete('Skip-Jwt-Interceptor')
      });
      return next.handle(cleanedRequest);
    }

    return this.accountService.user$.pipe(
      take(1),
      switchMap(user => {
        let modifiedRequest = request;
        if (user) {
          modifiedRequest = request.clone({
            setHeaders: {
              Authorization: `Bearer ${user.jwt}`
            }
          });
        }
        return next.handle(modifiedRequest);
      })
    );
  }
}

方法3:创建独立的HttpClient实例用于Youtube请求

创建不依赖全局拦截器的HttpClient实例,专门用于Youtube API请求:

  1. 定义独立的HttpClient提供者:
import { InjectionToken, Provider, HttpClient, HttpXhrBackend } from '@angular/common/http';

export const YOUTUBE_HTTP_CLIENT = new InjectionToken<HttpClient>('YoutubeHttpClient');

export const provideYoutubeHttpClient = (): Provider => ({
  provide: YOUTUBE_HTTP_CLIENT,
  useFactory: () => {
    // 直接使用HttpXhrBackend,不经过全局拦截器链
    const backend = new HttpXhrBackend({ build: () => new XMLHttpRequest() });
    return new HttpClient(backend);
  }
});
  1. 在模块中注册该提供者:
@NgModule({
  providers: [
    provideYoutubeHttpClient()
  ]
})
export class AppModule {}
  1. 在组件/服务中注入使用:
import { Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { YOUTUBE_HTTP_CLIENT } from './youtube-http-client.provider';

constructor(@Inject(YOUTUBE_HTTP_CLIENT) private youtubeHttpClient: HttpClient) {}

getYoutubePlaylistItems() {
  return this.youtubeHttpClient.get('https://www.googleapis.com/youtube/v3/playlistItems', {
    params: { /* 你的请求参数 */ }
  });
}

内容的提问来源于stack exchange,提问作者D052057

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:39:55