向请求添加新的 header,同时保留 body

Adding a new header to a Request, while preserving the body

我正在为我的公司内部使用设置 PWA。我应该使用什么方法将不记名令牌附加到来自 dom 或 web-worker.

的所有请求

我使用的这种方法在 posting formjson 时按预期工作,但我想要一种更清洁或更友好的方法,因为我不相信text 回退就足够了。

我在 Google 的 workbox.js service worker 模块中寻找一个函数,看看我是否可以设置一个拦截器,以便在向我的服务器发出请求时始终附加 Bearer 令牌因为这将解决我为什么首先来到这里的问题。此代码基于 Firebase Service Worker setup。并且没有任何东西可以获取并且 re-add post 数据到新请求因此有效地丢弃了整个 POST body.

这是我最终得到的代码。

self.addEventListener( 'fetch', ( event ) => {
    const requestProcessor = async ( idToken ) => {

        let req = event.request;

        // For same origin https requests, append idToken to header.
        if ( self.location.origin == getOriginFromUrl( event.request.url ) &&
            ( self.location.protocol == 'https:' ||
                self.location.hostname == 'localhost' ) &&
            idToken ) {


            let contentType = req.headers.get( "Content-Type" );

            // Clone headers as request headers are immutable.
            const headers = new Headers();
            for ( let entry of req.headers.entries() ) {
                headers.append( entry[ 0 ], entry[ 1 ] );
            }
            // Add ID token to header.
            headers.append( 'Authorization', 'Bearer ' + idToken );
            try {

                let tmpReq = req.clone();
                let body = "";

                if ( req.body ) {
                    body = req.body;

                } else if ( req.method === "POST" ) {
                    // get the post data if its json
                    if ( contentType === "application/json" ) {
                        // get JSON data
                        let json = await tmpReq.json();
                        body = JSON.stringify( json );

                    // Get the post data if its a submitted form
                    } else if ( contentType === "application/x-www-form-urlencoded" ) {
                        // get Form-Data
                        body = await tmpReq.formData();

                    // Get the post data as plain text as a fallback
                    } else {
                        body = await tmpReq.text();
                    }

                    console.log( "Content", content );
                }

                // create a new request with the Bearer Token and post body
                req = new Request( req.url, {
                    method: req.method,
                    headers: headers,
                    mode: 'same-origin',
                    credentials: req.credentials,
                    cache: req.cache,
                    redirect: req.redirect,
                    referrer: req.referrer,
                    body: body,
                    bodyUsed: req.bodyUsed,
                    context: req.context
                } );

            } catch ( e ) {
                // This will fail for CORS requests. We just continue with the
                // fetch caching logic below and do not pass the ID token.
            }

        }
        return fetch( req );
    };
    // Fetch the resource after checking for the ID token.
    // This can also be integrated with existing logic to serve cached files
    // in offline mode.
    event.respondWith( getIdToken().then( requestProcessor, requestProcessor ) );
} );

所以总而言之,我的问题是... 当 POST 的 contentType 既不是 JSON 也不是 FormData 将涵盖所有角度,或者我应该考虑一种新的传输方法 POST body.

如果你想修改一个Request,保留body但有新的或更新的headers,最简单的方法是将原始请求作为第一个参数传递给RequestInfo; it can be either a string URL, or an existing Request object. Any fields that you specify in the second parameter, which is of type RequestInit 类型的 Request 构造函数将覆盖原始响应中的字段。

如果您想在保留原始请求中的所有 header 的同时添加额外的 header 值,这会变得有点棘手,因为默认情况下,如果您只提供新值在 headers 中,这将覆盖所有原始的 header。因此,您需要确保将 headers 设置为原始 header 加上新的 header.

的组合

下面是一些说明这一点的代码:

// This request might be created implicitly by the web app,
// but let's just create it manually as an example:
const originalRequest = new Request('https://example.com', {
  body: 'shared body',
  method: 'POST',
  headers: {
    'x-header': 'my header value'
  },
});

// Start with the original headers as a baseline:
const modifiedHeaders = new Headers(originalRequest.headers);
// Make any changes you want:
modifiedHeaders.set('Authorization', 'Bearer 12345');

// Create a new request based on the original,
// with the modified headers:
const modifiedRequest = new Request(originalRequest, {
  headers: modifiedHeaders,
});

// Everything else in modifiedRequest should be as-is,
// but the headers will be updated.
// Do whatever you want with modifiedRequest at this point.

需要注意的一点是,使用这种方法,原始请求的 body 最终将在您构造修改后的请求时使用。这在您的用例中应该无关紧要,因为只有修改后的请求的 body 最终会被读取(当您将其传递给 fetch() 时)。如果出于某种原因,您确实需要阅读两个 body,请先对原始请求调用 clone(),例如

const modifiedRequest = new Request(originalRequest.clone(), {...});
// The two requests now have independent bodies.