Torchserve Managment API not working with s3 presigned URI

ironstark: <h2>
<a name="context-1" class="anchor" href="#context-1"></a>Context</h2>
<p>I am trying to use the management API with a S3 presigned URL to download and register a new model. This is the code snippet:</p>
<pre><code class="lang-auto">   def create_presigned_url(self, bucket_name, object_name, expiration=3600):
        """Generate a presigned URL to share an S3 object

        :param bucket_name: string
        :param object_name: string
        :param expiration: Time in seconds for the presigned URL to remain valid
        :return: Presigned URL as string. If error, returns None.
        """

        # Generate a presigned URL for the S3 object
        s3_client = boto3.client('s3')
        try:
            response = s3_client.generate_presigned_url('get_object',
                                                        Params={'Bucket': bucket_name,
                                                                'Key': object_name},
                                                        ExpiresIn=expiration)
        except ClientError as e:
            logging.error(e)
            return None

        # The response contains the presigned URL
        return response
presigned_uri = self.create_presigned_url(bucket_name, object_name)
response = requests.post("http://127.0.0.1:8081/models?url={}".format(presigned_uri))
</code></pre>
<p>Doing a normal GET on the presigned URI works but it doesn’t work when used with the model management API. I tried all the workarounds mentioned in <span class="hashtag">#669</span> but those are not giving any results as well. Can you please recommend what to do to make it work. Listing the errors I get in various situations:</p>
<p>Using the raw presigned URI:</p>
<pre><code class="lang-auto">{
  "code": 400,
  "type": "DownloadArchiveException",
  "message": "Failed to download archive from: https://log-analyzer-torchserve-mar.s3.amazonaws.com/test_service/stage/uw1/21_10_22_23_25/anomaly_detection_1634945079.8530345.mar?AWSAccessKeyId=****"
}
</code></pre>
<p>Replacing &amp; with %26:</p>
<pre><code class="lang-auto">{
  "code": 400,
  "type": "DownloadArchiveException",
  "message": "Failed to download archive from: https://log-analyzer-torchserve-mar.s3.amazonaws.com/test_service/stage/uw1/21_10_26_00_23/anomaly_detection_1635207765.7685282.mar?AWSAccessKeyId=****&amp;Signature=****=&amp;x-amz-security-token=****&amp;Expires=1635283752"
}
</code></pre>
<p>Using the torchserve 0.4.2-cpu docker image.</p>
<h2>
<a name="your-environment-2" class="anchor" href="#your-environment-2"></a>Your Environment</h2>

<ul>
<li>Installed using source? [yes/no]: no</li>
<li>Are you planning to deploy it using docker container? [yes/no]: yes</li>
<li>Is it a CPU or GPU environment?: CPU</li>
<li>Using a default/custom handler? [If possible upload/share custom handler/model]: custom but unrelated to the issue.</li>
<li>What kind of model is it e.g. vision, text, audio?: text</li>
<li>Are you planning to use local models from model-store or public url being used e.g. from S3 bucket etc.?<br>
[If public url then provide link.]: S3 bucket</li>
</ul>
<h2>
<a name="expected-behavior-3" class="anchor" href="#expected-behavior-3"></a>Expected Behavior</h2>
<p>It should be able to download the model from S3 and register it.</p>
<h2>
<a name="current-behavior-4" class="anchor" href="#current-behavior-4"></a>Current Behavior</h2>
<p>Returning a 400</p>
<h2>
<a name="steps-to-reproduce-5" class="anchor" href="#steps-to-reproduce-5"></a>Steps to Reproduce</h2>


<ol>
<li>Just upload a mar file to a s3 bucket</li>
<li>Create the presigned uri using the given code and then call the managment API to try to register the model.<br>
…</li>
</ol>
<p>Reference Issue on torchserve:</p>
<aside class="onebox githubissue" data-onebox-src="https://github.com/pytorch/serve/issues/669">
  <header class="source">

      <a href="https://github.com/pytorch/serve/issues/669" target="_blank" rel="noopener nofollow ugc">github.com/pytorch/serve</a>
  </header>

  <article class="onebox-body">
    <div class="github-row">
  <div class="github-icon-container" title="Issue">
	  <svg width="60" height="60" class="github-icon" viewbox="0 0 14 16" aria-hidden="true"><path d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg>
  </div>

  <div class="github-info-container">
    <h4>
      <a href="https://github.com/pytorch/serve/issues/669" target="_blank" rel="noopener nofollow ugc">Failed to download and register model using s3 presigned v4 url</a>
    </h4>

    <div class="github-info">
      <div class="date">
        opened <span class="discourse-local-date" data-format="ll" data-date="2020-09-08" data-time="11:48:20" data-timezone="UTC">11:48AM - 08 Sep 20 UTC</span>
      </div>

        <div class="date">
          closed <span class="discourse-local-date" data-format="ll" data-date="2020-09-09" data-time="11:56:44" data-timezone="UTC">11:56AM - 09 Sep 20 UTC</span>
        </div>

      <div class="user">
        <a href="https://github.com/vishal-wiai" target="_blank" rel="noopener nofollow ugc">
          <img alt="vishal-wiai" src="https://avatars.githubusercontent.com/u/51786215?v=4" class="onebox-avatar-inline" width="20" height="20">
          vishal-wiai
        </a>
      </div>
    </div>

    <div class="labels">
        <span style="display:inline-block;margin-top:2px;background-color: #B8B8B8;padding: 2px;border-radius: 4px;color: #fff;margin-left: 3px;">
          triaged_wait
        </span>
    </div>
  </div>
</div>

  <div class="github-row">
    <p class="github-body-container">I'm using management API to register a model with a HTTPs URL. It is a s3 presig<span class="show-more-container"><a href="" rel="noopener" class="show-more">…</a></span><span class="excerpt hidden">ned url. Torchserve successfully downloads and registers models from s3 v2 signature URLs but fails to download for v4 signature types. Is there any bug to it?

I checked this behaviour with 3 of the models and also verified URL permissions. Using `requests.get()` I'm able to download but not on TorchServe.</span></p>
  </div>

  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>
<aside class="onebox githubissue" data-onebox-src="https://github.com/pytorch/serve/issues/1293">
  <header class="source">

      <a href="https://github.com/pytorch/serve/issues/1293" target="_blank" rel="noopener nofollow ugc">github.com/pytorch/serve</a>
  </header>

  <article class="onebox-body">
    <div class="github-row">
  <div class="github-icon-container" title="Issue">
	  <svg width="60" height="60" class="github-icon" viewbox="0 0 14 16" aria-hidden="true"><path d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg>
  </div>

  <div class="github-info-container">
    <h4>
      <a href="https://github.com/pytorch/serve/issues/1293" target="_blank" rel="noopener nofollow ugc">Model Management API doesn't work with S3 presigned URL</a>
    </h4>

    <div class="github-info">
      <div class="date">
        opened <span class="discourse-local-date" data-format="ll" data-date="2021-10-26" data-time="20:36:32" data-timezone="UTC">08:36PM - 26 Oct 21 UTC</span>
      </div>


      <div class="user">
        <a href="https://github.com/Iron-Stark" target="_blank" rel="noopener nofollow ugc">
          <img alt="Iron-Stark" src="https://avatars.githubusercontent.com/u/22685710?v=4" class="onebox-avatar-inline" width="20" height="20">
          Iron-Stark
        </a>
      </div>
    </div>

    <div class="labels">
    </div>
  </div>
</div>

  <div class="github-row">
    <p class="github-body-container">## Context
I am trying to use the management API with a S3 presigned URL to dow<span class="show-more-container"><a href="" rel="noopener" class="show-more">…</a></span><span class="excerpt hidden">nload and register a new model. This is the code snippet:

```
   def create_presigned_url(self, bucket_name, object_name, expiration=3600):
        """Generate a presigned URL to share an S3 object

        :param bucket_name: string
        :param object_name: string
        :param expiration: Time in seconds for the presigned URL to remain valid
        :return: Presigned URL as string. If error, returns None.
        """

        # Generate a presigned URL for the S3 object
        s3_client = boto3.client('s3')
        try:
            response = s3_client.generate_presigned_url('get_object',
                                                        Params={'Bucket': bucket_name,
                                                                'Key': object_name},
                                                        ExpiresIn=expiration)
        except ClientError as e:
            logging.error(e)
            return None

        # The response contains the presigned URL
        return response
presigned_uri = self.create_presigned_url(bucket_name, object_name)
response = requests.post("http://127.0.0.1:8081/models?url={}".format(presigned_uri))
```

Doing a normal GET on the presigned URI works but it doesn't work when used with the model management API. I tried all the workarounds mentioned in #669 but those are not giving any results as well. Can you please recommend what to do to make it work. Listing the errors I get in various situations:

Using the raw presigned URI:

```
{
  "code": 400,
  "type": "DownloadArchiveException",
  "message": "Failed to download archive from: https://log-analyzer-torchserve-mar.s3.amazonaws.com/test_service/stage/uw1/21_10_22_23_25/anomaly_detection_1634945079.8530345.mar?AWSAccessKeyId=****"
}
```

Replacing &amp; with %26:

```
{
  "code": 400,
  "type": "DownloadArchiveException",
  "message": "Failed to download archive from: https://log-analyzer-torchserve-mar.s3.amazonaws.com/test_service/stage/uw1/21_10_26_00_23/anomaly_detection_1635207765.7685282.mar?AWSAccessKeyId=****&amp;Signature=****=&amp;x-amz-security-token=****&amp;Expires=1635283752"
}
```

Using the torchserve 0.4.2-cpu docker image.

## Your Environment

* Installed using source? [yes/no]: no
* Are you planning to deploy it using docker container? [yes/no]: yes
* Is it a CPU or GPU environment?: CPU
* Using a default/custom handler? [If possible upload/share custom handler/model]: custom but unrelated to the issue.
* What kind of model is it e.g. vision, text, audio?: text
* Are you planning to use local models from model-store or public url being used e.g. from S3 bucket etc.?
  [If public url then provide link.]: S3 bucket

## Expected Behavior
It should be able to download the model from S3 and register it.

## Current Behavior
Returning a 400

## Steps to Reproduce


1.  Just upload a mar file to a s3 bucket
2. Create the presigned uri using the given code and then call the managment API to try to register the model.
...</span></p>
  </div>

  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>