【问题标题】:Adding a new header to a Request, while preserving the body向请求添加新标头,同时保留正文
【发布时间】:2019-02-11 16:11:46
【问题描述】:

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

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

我在 Google 的 workbox.js 服务工作者模块中寻找一个函数,看看我是否可以设置一个拦截,以便在向我的服务器发出请求时始终附加承载令牌,因为这将解决我最终的问题这里是第一位的。此代码基于Firebase Service Worker setup。并且没有任何东西可以获取并将发布数据重新添加到新请求中,从而有效地删除了整个 POST 正文。

这是我最终得到的代码。

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 既不是 JSONFormData 覆盖所有角度时,我添加的 text() 后备是什么,还是我应该考虑一种新的方法传输 POST 正文

【问题讨论】:

    标签: javascript firebase-authentication service-worker progressive-web-apps workbox


    【解决方案1】:

    如果要修改Request,保留body,但使用新的或更新的headers,最简单的方法是将原始请求作为第一个参数传递给Request构造函数,即RequestInfo 类型;它可以是字符串 URL,也可以是现有的 Request 对象。您在第二个参数中指定的任何字段(类型为 RequestInit)都将覆盖原始响应中的字段。

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

    这里有一些代码可以说明这一点:

    // 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() 时)。如果出于某种原因,您确实需要同时阅读bodys,那么请先在原始请求上调用clone(),例如

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-22
      • 2012-01-30
      • 2016-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-28
      • 1970-01-01
      相关资源
      最近更新 更多