title: Adding a new header to a Request, while preserving the body
body: <p>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.</p>
  
  <p>This method that I am using works as expected when posting a <code>form</code> or <code>json</code> but I would like a cleaner or friendlier method as I don't trust that the <code>text</code> fallback will suffice.</p>
  
  <p>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 <a href="https://firebase.google.com/docs/auth/web/service-worker-sessions?authuser=0" rel="nofollow noreferrer">Firebase Service Worker setup</a>. And there was nothing to get and re-add the post data to the new request thus effectively dropping the entire POST body.</p>
  
  <p>This is the code I ended up with.</p>
  
  <pre><code>self.addEventListener( 'fetch', ( event ) =&gt; {
      const requestProcessor = async ( idToken ) =&gt; {
  
          let req = event.request;
  
          // For same origin https requests, append idToken to header.
          if ( self.location.origin == getOriginFromUrl( event.request.url ) &amp;&amp;
              ( self.location.protocol == 'https:' ||
                  self.location.hostname == 'localhost' ) &amp;&amp;
              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 ) );
  } );
  </code></pre>
  
  <p>So in summary my question is... <strong>Is the <code>text()</code> fallback that I add when a POST's contentType is neither <code>JSON</code> or <code>FormData</code> going to cover all angles or should I consider a new method of transferring the POST body</strong>.</p>