Search code examples
expressamazon-s3reverse-proxy

Serve Entire React CRA from AWS S3 bucket using Express


I am basically trying to use express as a sort of reverse proxy. My end goal is to serve up different react CRA bundles to different users. Right now though I am just working on a Proof of Concept to see if it is even possible to do this.

TLDR Goal:

  • use express to point to a specific CRA bundle stored in a s3 bucket and serve it

This is the code I am using in express:

app.get('/*', function (req, res) {
  const bucketParams = {
    Bucket: 'some-dumb-bucket',
    Key: 'cra/index.html'
  };

  s3.getObject(bucketParams)
  .on('httpHeaders', function (statusCode, headers) {
    res.set('Content-Length', headers['content-length']);
    res.set('Content-Type', headers['content-type']);
    res.set('Last-Modified', headers['last-modified']);
    this.response.httpResponse.createUnbufferedStream()
      .pipe(res);
    })
    .send();
})

The problem I am encountering is that all of my content is coming back with wrong headers. When I go into s3 and view the metadata it has the right headers so why is it fetching all the headers as "text/html"?

enter image description here


Solution

  • I figured out what I was doing wrong! It was looping through and grabbing the same index.html headers. Fix:

    app.get('/*', function (req, res) {
      const bucketParams = {
        Bucket: 'some-dumb-bucket',
        Key: 'auth/index.html'
      };
    
      if (req.url && req.url !== '/') {
        bucketParams.Key = `auth${req.url}`;
      } else
       bucketParams.Key = `auth/index.html`;
    
      // send the assets over from s3
      s3.getObject(bucketParams)
        .on('httpHeaders', function (statusCode, headers) {
          res.set('Content-Length', headers['content-length']);
          res.set('Content-Type', headers['content-type']);
          res.set('Last-Modified', headers['last-modified']);
          res.set('ETag', headers['etag']);
          this.response.httpResponse.createUnbufferedStream()
            .pipe(res);
        })
        .send();
    });
    

    Code could be a tiny bit cleaner but PoC working.