在保留正文的同时,向请求添加新的标头 [英] Adding a new header to a Request, while preserving the body

查看:48
本文介绍了在保留正文的同时,向请求添加新的标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的公司设置房屋使用PWA.我应该使用哪种方法将承载令牌附加到来自dom或网络工作者的所有请求.

I am setting up a PWA for my company in house usage. What method should I use to attach a bearer token to all of the requests from dom or web-worker.

我使用的这种方法在发布 form json 时可以按预期工作,但是我想使用一种更清洁或更友好的方法,因为我不相信 text 后备就足够了.

This method that I am using works as expected when posting a form or json but I would like a cleaner or friendlier method as I don't trust that the text fallback will suffice.

我一直在Google的workbox.js服务工作程序模块中寻找一个函数,以查看是否可以将拦截器设置为在向服务器发送请求时始终附加Bearer令牌,因为这样可以解决为什么我最终会遇到的问题在这里放在首位.该代码基于 Firebase Service Worker设置.而且没有任何东西可以获取,也不需要将帖子数据重新添加到新请求中,从而有效地删除了整个POST正文.

I was looking for a function in Google's workbox.js service worker module to see if I could set up a intercept to always append the Bearer token when a request gets made to my server as that would solve the problem why I end up here in first place. This code is based on the Firebase Service Worker setup. And there was nothing to get and re-add the post data to the new request thus effectively dropping the entire POST body.

这是我最终得到的代码.

This is the code I ended up with.

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时添加的 text()后备会涵盖所有角度,或者我应该考虑转移POST正文的新方法.

So in summary my question is... Is the text() fallback that I add when a POST's contentType is neither JSON or FormData going to cover all angles or should I consider a new method of transferring the POST body.

推荐答案

如果要修改 Request ,则保留 body ,但使用新的或更新的标头,最简单的方法是将原始请求作为第一个参数传递给 RequestInit ,将覆盖原始响应中的字段.

If you want to modify a Request, preserving the body but with new or updated headers, the easiest approach is to pass in the original request as the first parameter to the Request constructor, which is of type 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, will override the fields in the original response.

如果您想添加一个附加的标头值,同时保留所有原始请求的标头,则会有些棘手,因为默认情况下,如果仅在 headers 中提供新值,则将覆盖所有原始标头.因此,您需要确保将 headers 设置为原始标题和新标题的组合.

It gets a little trickier if you want to add in an additional header value while keeping all the headers from the original request, since by default, if you only provide the new values in headers, that will overwrite all of the original headers. So you need to make sure that you set headers to a combination of the original headers plus your new header.

以下代码说明了这一点:

Here's some code that illustrates this:

// 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 最终会被读取(当您将其传递给 fetch()时).如果由于某种原因确实需要读取两个 body ,然后首先在原始请求上调用 clone(),例如

One thing to note is that with this approach, the body of the original request will end up being used when you construct the modified request. This shouldn't matter in your use case, since only the body of the modified request will end up being read (when you pass it to fetch()). If, for some reason, you do need to read both bodys, then call clone() on the original request first, like

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

这篇关于在保留正文的同时,向请求添加新的标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆