首页 > 解决方案 > Angular 的 Service Worker 阻止调用 API

问题描述

我有一个使用 NestJS 应用程序的 API 端点的 Angular 应用程序。

为了将整个应用程序部署到 Heroku,我构建了 Angular 应用程序并将 /dist 文件夹的内容放在我的 NestJS 应用程序中。

我使用谷歌认证系统。基本上,Angular 会调用一个 API 端点,将用户重定向到 Google 的登录屏幕,一旦完成,它就会回调我的 API,该 API 会重定向回前面的 URL,如下图所示: 认证过程

我的问题是:当我在 Angular 应用程序中运行服务工作者时,每次单击“使用 Google 登录”链接时,都会收到以下错误消息:

ERROR 错误:未捕获(在承诺中):错误:无法匹配任何路由。URL 段:'api/auth/google' 错误:无法匹配任何路由。网址段:'api/auth/google'

之后,当我尝试通过浏览器直接调用 API 端点时,例如https://myapp.herokuapp.com/api/albums,我收到相同的错误消息。但不是以邮递员为例。

所以我决定从 Angular 部分移除 service worker,现在一切正常。所以服务人员阻止我调用 API 端点。

如何正确配置以避免此类问题?

如果您需要更多信息,请参见下文:

这是我的main.ts

async function bootstrap() {
  const configService = new ConfigService(CONFIG_SERVICE_PATH);
  const app = await NestFactory.create(AppModule);
  const httpRef = app.get(HTTP_SERVER_REF);

  app.enableCors();

  console.log('***** NODE ENV IS: ' + process.env.NODE_ENV); // <-- returns 'production' 
  console.log('***** IS PRODUCTION ? ' + configService.get('PRODUCTION')); // <-- returns 'true'

  if (configService.get('PRODUCTION') === 'true') {
    app.useStaticAssets(join(__dirname, '../front')); // <-- Angular folder
    app.useGlobalFilters(new AllExceptionsFilter(httpRef));
  } else {
    app.useStaticAssets(join(__dirname, '..', 'public'));
  }

  await app.listen(process.env.PORT || configService.get('PORT'));
}

我的AllExceptionsFilter

@Catch(NotFoundException)
export class AllExceptionsFilter extends BaseExceptionFilter {
  constructor(@Inject(HTTP_SERVER_REF) applicationRef: HttpServer) {
    super(applicationRef);
  }

  /**
   * This filter will serve the correct response for a request to the API or a request to the front part.
   */
  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const req = ctx.getRequest();

    if (req.path && req.path.startsWith('/api')) {
      super.catch(exception, host);
    } else {
      response.sendFile(resolve(__dirname, '../../front/index.html'));
    }
  }
}

我的LoginComponent(角度):

<a href="{{ loginUrl }}" class="google-button">
  <span class="google-button__text">Sign in with Google</span>

get loginUrl(): string {
  const url = environment.backendUrl + '/auth/google';
  console.log('Login url: ' + url); // <-- logs 'https://myapp.heroku.com/api/auth/google'
  return url;
}

标签: angularherokuservice-workerprogressive-web-appsnestjs

解决方案


@Flobestst,作为答案发布:)

看看这篇文章:Angular 5 and Service Worker: How to exclude a specific path from ngsw-config.json


推荐阅读