title: Is there a way to get location (public url) of S3 object using AWS CLI?
body: <p>&lt; premise><br>
  I'm new cloud computing in general, <code>AWS</code> specifically, and REST API, and am trying to cobble together a "big-picture" understanding.</p>
  
  <p>I am working with <code>LocalStack</code> - which, by my understanding, simulates the real <code>AWS</code> by responding identically to (a subset of) the <code>AWS</code> API if you specify the endpoint address/port that <code>LocalStack</code> listens at.</p>
  
  <p>Lastly, I've been working from this tutorial: <a href="https://dev.to/goodidea/how-to-fake-aws-locally-with-localstack-27me" rel="nofollow noreferrer">https://dev.to/goodidea/how-to-fake-aws-locally-with-localstack-27me</a><br>
  &lt; /premise></p>
  
  <p>Using the noted tutorial, and per its guidance, I successfully creating a <code>S3</code> bucket using the <code>AWS</code> CLI.<br>
  To demonstrate uploading a local file to the <code>S3</code> bucket, though, the tutorial switches to <code>node.js</code>, which I think demonstrates the <code>AWS</code> <code>node.js</code> SDK:</p>
  
  <pre><code># aws.js
  # This code segment comes from https://dev.to/goodidea/how-to-fake-aws-locally-with-localstack-27me
  #
  
  const AWS = require('aws-sdk')
  require('dotenv').config()
  
  const credentials = {
     accessKeyId: process.env.AWS_ACCESS_KEY_ID,
     secretAccessKey: process.env.AWS_SECRET_KEY,
  }
  
  const useLocal = process.env.NODE_ENV !== 'production'
  
  const bucketName = process.env.AWS_BUCKET_NAME
  
  const s3client = new AWS.S3({
     credentials,
     /**
      * When working locally, we'll use the Localstack endpoints. This is the one for S3.
      * A full list of endpoints for each service can be found in the Localstack docs.
      */
     endpoint: useLocal ? 'http://localhost:4572' : undefined,
     /**
       * Including this option gets localstack to more closely match the defaults for
       * live S3. If you omit this, you will need to add the bucketName to the `Key`
       * property in the upload function below.
       *
       * see: https://github.com/localstack/localstack/issues/1180
       */
     s3ForcePathStyle: true,
  })
  
  
  const uploadFile = async (data, fileName) =&gt;
     new Promise((resolve) =&gt; {
        s3client.upload(
           {
              Bucket: bucketName,
              Key: fileName,
              Body: data,
           },
           (err, response) =&gt; {
              if (err) throw err
              resolve(response)
           },
        )
     })
  
  module.exports = uploadFile
  </code></pre>
  
  <p>.</p>
  
  <pre><code># test-upload.js
  # This code segment comes from https://dev.to/goodidea/how-to-fake-aws-locally-with-localstack-27me
  #
  
  const fs = require('fs')
  const path = require('path')
  const uploadFile = require('./aws')
  
  const testUpload = () =&gt; {
     const filePath = path.resolve(__dirname, 'test-image.jpg')
     const fileStream = fs.createReadStream(filePath)
     const now = new Date()
     const fileName = `test-image-${now.toISOString()}.jpg`
     uploadFile(fileStream, fileName).then((response) =&gt; {
        console.log(":)")
        console.log(response)
     }).catch((err) =&gt; {
        console.log(":|")
        console.log(err)
     })
  }
  
  testUpload()
  </code></pre>
  
  <p>Invocation :</p>
  
  <pre><code>$ node test-upload.js
  :)
  { ETag: '"c6b9e5b1863cd01d3962c9385a9281d"',
    Location: 'http://demo-bucket.localhost:4572/demo-bucket/test-image-2019-03-11T21%3A22%3A43.511Z.jpg',
    key: 'demo-bucket/test-image-2019-03-11T21:22:43.511Z.jpg',
    Key: 'demo-bucket/test-image-2019-03-11T21:22:43.511Z.jpg',
    Bucket: 'demo-bucket' }
  </code></pre>
  
  <p>I do not have prior experience with node.js, but my understanding of the above code is that it uses the <code>AWS.S3.upload()</code> <code>AWS</code> <code>node.js</code> SDK method to copy a local file to a <code>S3</code> bucket, and prints the <code>HTTP</code> response (is that correct?).</p>
  
  <p><strong>Question</strong>: I observe that the <code>HTTP</code> response includes a "Location" key whose value looks like a URL I can copy/paste into a browser to view the image directly from the <code>S3</code> bucket; is there a way to get this location using the <code>AWS</code> CLI?</p>
  
  <p>Am I correct to assume that <code>AWS</code> CLI commands are analogues of the <code>AWS</code> SDK?</p>
  
  <p>I tried uploading a file to my S3 bucket using the <code>aws s3 cp</code> CLI command, which I thought would be analogous to the <code>AWS.S3.upload()</code> method above, but it didn't generate any output, and I'm not sure what I should have done - or should do - to get a Location the way the HTTP response to the <code>AWS.S3.upload()</code> AWS node SDK method did.</p>
  
  <pre><code>$ aws --endpoint-url=http://localhost:4572 s3 cp ./myFile.json s3://myBucket/myFile.json
  upload: ./myFile.json to s3://myBucket/myFile.json
  </code></pre>
  
  <hr>
  
  <p><strong>Update</strong>: continued study makes me now wonder whether it is <em>implicit</em> that a file uploaded to a <code>S3</code> bucket by any means - whether by CLI command <code>aws s3 cp</code> or node.js SDK method <code>AWS.S3.upload()</code>, etc. - can be accessed at <code>http://&lt;bucket_name&gt;.&lt;endpoint_without_http_prefix&gt;/&lt;bucket_name&gt;/&lt;key&gt;</code> ? E.g. <code>http://myBucket.localhost:4572/myBucket/myFile.json</code>?<br>
  If this is <em>implicit</em>, I suppose you could argue it's unnecessary to ever be given the "Location" as in that example <code>node.js</code> HTTP response.<br>
  Grateful for guidance - I hope it's obvious how painfully under-educated I am on all the involved technologies.  </p>
  
  <hr>
  
  <p><strong>Update 2</strong>: It looks like the correct url is <code>&lt;endpoint&gt;/&lt;bucket_name&gt;/&lt;key&gt;</code>, e.g. <code>http://localhost:4572/myBucket/myFile.json</code>.</p>