title: How to prevent percent decoding of URIs in Akka Http redirect requests?
body: <p>I am using Akka Http to handle the redirection of a signed url for a text resource stored in GCS (Google Cloud Storage). Basically I have some files in GCS that I want to deliver with my API when requested. Unfortunately, the path to this resource has a subdirectory with a <code>=</code> character in it, something like: <code>https://storage.googleapis.com/path_start/more_path/format=avro/still_more_path/filename.avro</code>.</p>
  <p>Google storage's <code>signUrl</code> method percent encodes this <code>=</code> character as <code>%3D</code> in the signed url. I have verified that using this signed url allows access to the files in GCS (hitting it starts a download). The problem is when Akka Http redirects this signed url on request, it decodes it back to the equals sign. This results in a <code>SignatureDoesNotMatch</code> error from GCS:</p>
  <pre><code>
      &lt;Code&gt;SignatureDoesNotMatch&lt;/Code&gt;
      &lt;Message&gt;The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.&lt;/Message&gt;
  </code></pre>
  <p>I attempt to generate the signed url and redirect it in the following code snippet:</p>
  <pre><code>          val signedUrl = cloudStorageService.getSignedUrl(bucketId, filePath)
            logger.info(s&quot;signedUrl: $signedUrl&quot;)
            redirect(signedUrl, TemporaryRedirect)
  </code></pre>
  <p>and my <code>cloudStorageService.getSignedUrl</code> method is defined separately here:</p>
  <pre><code>      def getSignedUrl(bucket: String, path: String, expiration: Option[Int] = None): String = {
          val maxLifetime = 60 * 60 * 24 * 7
          val lifetime = expiration.getOrElse(maxLifetime)
          val cappedExpiration = Math.min(lifetime, maxLifetime)
      
          val blobInfo = BlobInfo.newBuilder(BlobId.of(bucket, path)).build
          storage.signUrl(blobInfo, cappedExpiration, TimeUnit.SECONDS, Storage.SignUrlOption.withV4Signature).toString
        }
  </code></pre>
  <p>The logging statement in the first snippet shows me that the signed URL is generated with the <code>%3D</code>, but the redirected URL has been percent decoded back to <code>=</code>, resulting in the <code>SignatureDoesNotMatch</code> error.</p>
  <p>This behavior is standard for Akka Http. According to <a href="https://doc.akka.io/api/akka-http/current/akka/http/scaladsl/model/Uri.html" rel="nofollow noreferrer">the documentation</a> for Uri class, all members represent percent decoded elements. There is an option to construct the uri with a raw query string, but in my case the encoded character happens in the uri path itself, not the query.</p>
  <p>So my question is, is there any way to get Akka Http to redirect this signed url without percent decoding the path? Or am I mistaken, and there's another way to approach this problem?</p>