title: Stream video from AWS onto webpage using node.js and react
body: <p>I am in the process of trying to stream an mp4 video from my AWS S3 bucket onto a webpage using react.js for the client and node.js as the server.  I am quite a bit new to both of these however.  On the front-end, within one of my react components I have the following within a render, (some code in the return is omitted for relevance):</p>
  
  <pre><code>render() {
    const { classes } = this.props;
    return(
      &lt;video id = "video" width = "1280" height = "720" controls&gt;
      Your browser does not support the video tag.
        &lt;source src={this.state.videoNow} type='video/mp4' /&gt;
      &lt;/video&gt; 
    );
  }
  </code></pre>
  
  <p>Within the same class I have a componentDidMount() function:</p>
  
  <pre><code>componentDidMount() {
     fetch("/api/annotate", {
       headers: {'Authorization': 'Bearer ' + localStorage.getItem('token')}
     })
       .then(res =&gt; {
         this.setState({
           videoNow: res
          });
        ,(error) =&gt; {
            console.log(error)
        })
  }
  </code></pre>
  
  <p>Within my server.js file I have the following:</p>
  
  <pre><code>app.get('/api/annotate',
    (req, res) =&gt; {
      var s3 = new AWS.S3();
      const mimetype = 'video/mp4';
      const file = '&lt;video source in bucket&gt;';
      const cache = 0;
      console.log('const mimetype, file, and cache declared');
      s3.listObjectsV2({Bucket: &lt;name of bucket&gt;, MaxKeys: 1, Prefix: file}, function(err, data) {
        if (err) {
          return res.sendStatus(404);
        }
        console.log('made request to s3 to list objects');
  
        if ((req != null) &amp;&amp; (req.headers.range != null)) {
          var range = req.headers.range;
          var bytes = range.replace(/bytes=/, '').split('-');
          var start = parseInt(bytes[0], 10);
          var total = data.Contents[0].Size;
          var end = bytes[1] ? parseInt(bytes[1], 10) : total - 1;
          var chunksize = (end - start) + 1;
          console.log('declared range, bytes, start, total, end, chunksize vars');
  
          res.writeHead(206, {
             'Content-Range'  : 'bytes ' + start + '-' + end + '/' + total,
             'Accept-Ranges'  : 'bytes',
             'Content-Length' : chunksize,
             'Last-Modified'  : data.Contents[0].LastModified,
             'Content-Type'   : mimetype
          });
          console.log('wrote header');
          s3.getObject({Bucket: &lt;name of bucket&gt;, Key: file, Range: range}).createReadStream().pipe(res);
          console.log('got object from s3 and created readstream');
        }
        else
        {
          res.writeHead(200,
          {
              'Cache-Control' : 'max-age=' + cache + ', private',
              'Content-Length': data.Contents[0].Size,
              'Last-Modified' : data.Contents[0].LastModified,
              'Content-Type'  : mimetype
          });
          s3.getObject({Bucket: &lt;name of bucket&gt;, Key: file}).createReadStream().pipe(res);
          console.log('fell into else statement, wrote header');
        }
  
  
      });
    });
  </code></pre>
  
  <p>When I run this code, I notice that the else statement in my server.js file is always run once, and then nothing else happens.  The video doesn't load and the console states that the video could not be found.  If I change the video source within my react component to src='/api/annotate' the video loads perfectly.  The problem is that I am trying to add authentication, and this only works if I have a componentDidMount.  I've been searching for days on how to solve this issue and couldn't find much.  Once again, I am quite new to all of this.  Any advice would be very much appreciated!!!</p>