如何将自定义http标头添加到角度模块联合remoteEntry.js加载调用?

问题描述 投票:0回答:3

我有一个主机应用程序和一些微前端应用程序都是 Angular 15。我使用过

"@angular-architects/module-federation": "^15.0.3"
。一切正常,除了我无法拦截加载 mfe 应用程序的 remoteEntry.js 文件的 http 调用。

所有 mfe 应用程序都部署在服务器中,服务器要完成请求,我必须将授权令牌添加到请求中。我尝试了多种方法,但无法拦截调用并将令牌添加到其中。

  1. Angulat http 拦截器不会拦截此调用。
  2. 模块联盟没有提供任何添加http请求的选项。

如有任何建议,我们将不胜感激。

下面是我的路由,我在其中加载mfe

{
        path: 'config',
        loadChildren: () =>
          loadRemoteModule({
            remoteEntry: environment.configREmoteEntryURL,
            type: "module",
            exposedModule: './Module'
          })
            .then(m => m.AppModule)
},
angular webpack webpack-dev-server angular-module-federation
3个回答
3
投票

您可以使用 Service Worker 来拦截和操作所有针对 MFE CDN 的请求。

service-worer.js

let authToken = '';

// This event listeners listens to the requests towards the login
// endpoint and stores that authToken at the corresponding variable.
self.addEventListener('fetch', function (event) {
  if (event.request.url === 'https://auth-endpoint/login') {
    event.respondWith(
      fetch(event.request)
        .then(function (response) {
          var responseClone = response.clone();

          responseClone.json().then(function (data) {
            authToken = data.token;
          });

          return response;
        })
    );
  }
});

// This requests listens to the requests towards the MFEs' endpoint
// and adds the custom headers needed fot the authorization
self.addEventListener('fetch', function (event) {
  if (event.request.url.startsWith('https://remotes-endpoint/')) {
    let url = new URL(event.request.url);

    let headers = new Headers(event.request.headers);

    headers.set('Content-Type', 'application/javascript');
    headers.set('Authorization', authToken);

    let newRequest = new Request(url, {
      method: event.request.method,
      headers,
      mode: 'cors',
      credentials: 'same-origin',
      redirect: event.request.redirect
    });

    event.respondWith(fetch(newRequest));
  }
});

您需要在 bootstrap.js 中注册您的 Service Worker

...
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function () {
    navigator.serviceWorker.register('/service-worker.js')
      .then(function (registration) {
        console.log('Service Worker registration successful with scope: ', registration.scope);
      }, function (err) {
        console.log('Service Worker registration failed: ', err);
      });
  });
}

在您的 webpack 配置中添加 CopyPlugin

const CopyPlugin = require('copy-webpack-plugin');

const config = {
  ...
  plugins: [
    ...
    new CopyPlugin({
      patterns: [
        // adjust 'service-worker.js' if your file is somewhere else
        { from: 'service-worker.js', to: '' }, 
      ],
    }),
  ]
}

module.exports = config;

您很可能还需要从模块联合配置中删除遥控器,只要在用户登录之前消费者应用程序的挂载上不存在 authToken。因此,遥控器的请求将在挂载时失败。要解决此问题,您需要使用动态远程容器加载遥控器。此repo中完整实现了此方法。


0
投票

恐怕目前这是不可能的。

您的用例是什么?


0
投票

这个解决方案很聪明,但它对我来说不起作用,我会改变一些东西。

  1. 请求参数:

mode:'cors',凭据:'same-origin',-这意味着服务器正在对remoteEntry文件使用某种授权+它应该支持cors请求。因此,这样编写会在启动真正的请求之前创建一个选项请求,这在您的服务器上可能是不允许的。实际上,常见的 GET 请求(没有自定义标头)不应该要求打开 CORS。因此,只需省略凭据,并将模式更改为:

mode: "no-cors"

  1. 发送的缓存控制标头对我来说不起作用,但您可以做一个简单的增强: 让 url = 新 URL(event.request.url);

    网址=

    ${url}?${Date.now()}
    ;

第二步将保证您获得文件的新副本,在每个请求上添加此随机散列,这将防止 proweser 缓存它。

© www.soinside.com 2019 - 2024. All rights reserved.