简体   繁体   English

Angular的Service Worker阻止调用API

[英]Angular's Service Worker prevents API to be called

I got an Angular app which uses API endpoints of a NestJS app. 我有一个Angular应用程序,它使用NestJS应用程序的API端点。

In order to deploy the whole application to Heroku, I build Angular app and I put the content of /dist folder inside my NestJS app. 为了将整个应用程序部署到Heroku,我构建了Angular应用程序,并将/ dist文件夹的内容放在我的NestJS应用程序中。

I use a Google authentication system. 我使用的是Google身份验证系统。 Basically, Angular calls an API endpoint which redirects user to Google's login screen and once done, it calls back my API which redirects back to a front URL like shown on this image: 基本上,Angular调用一个API端点,将用户重定向到Google的登录屏幕,一旦完成,它就会回调我的API,重定向回前面的URL,如下图所示: 身份验证过程

My issue with this is : when I have a service worker running in my Angular app, every time I click on the "Login with Google" link, I get the following error message: 我的问题是 :当我在Angular应用程序中运行服务工作者时,每次单击“使用Google登录”链接时,都会收到以下错误消息:

ERROR Error: Uncaught (in promise): Error: Cannot match any routes. 错误错误:未捕获(承诺):错误:无法匹配任何路由。 URL Segment: 'api/auth/google' Error: Cannot match any routes. 网址细分:'api / auth / google'错误:无法匹配任何路由。 URL Segment: 'api/auth/google' 网址细分:'api / auth / google'

After this, when I try to call an API endpoint directly through my browser, like https://myapp.herokuapp.com/api/albums , I get the same error message. 在此之后,当我尝试通过我的浏览器直接调用API端点时,例如https://myapp.herokuapp.com/api/albums ,我收到相同的错误消息。 But not with Postman for example. 但不是以Postman为例。

So I decided to remove the service worker from the Angular part and everything works well now. 所以我决定从Angular部分删除服务工作者,现在一切正常 So the service worker prevents me from calling API endpoints. 因此,服务工作者阻止我调用API端点。

How to configure it correctly to avoid this kind of problem ? 如何正确配置以避免这种问题?

In case you need some more information, see below: 如果您需要更多信息,请参阅以下内容:

Here is my main.ts : 这是我的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'));
}

My AllExceptionsFilter : 我的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'));
    }
  }
}

My LoginComponent (Angular): 我的LoginComponent (Angular):

<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;
}

@Flobesst, posted as an answer :) @Flobesst,贴出来作为答案:)

Take a look at this post: Angular 5 and Service Worker: How to exclude a particular path from ngsw-config.json 看一下这篇文章: Angular 5和Service Worker:如何从ngsw-config.json中排除特定路径

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM