Reputation: 99
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 =
character in it, something like: https://storage.googleapis.com/path_start/more_path/format=avro/still_more_path/filename.avro
.
Google storage's signUrl
method percent encodes this =
character as %3D
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 SignatureDoesNotMatch
error from GCS:
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message>
I attempt to generate the signed url and redirect it in the following code snippet:
val signedUrl = cloudStorageService.getSignedUrl(bucketId, filePath)
logger.info(s"signedUrl: $signedUrl")
redirect(signedUrl, TemporaryRedirect)
and my cloudStorageService.getSignedUrl
method is defined separately here:
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
}
The logging statement in the first snippet shows me that the signed URL is generated with the %3D
, but the redirected URL has been percent decoded back to =
, resulting in the SignatureDoesNotMatch
error.
This behavior is standard for Akka Http. According to the documentation 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.
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?
Upvotes: 0
Views: 396
Reputation: 6897
You might want to create the redirect response 'manually' instead of using the 'redirect' directive. The directive implementation is:
HttpResponse(
status = redirectionType,
headers = headers.Location(uri) :: Nil,
entity = redirectionType.htmlTemplate match {
case "" => HttpEntity.Empty
case template => HttpEntity(ContentTypes.`text/html(UTF-8)`, template format uri)
}
Instead of headers.Location(uri)
you could introduce your own RawHeader
to build up a Location
header. You can probably leave the entity empty in your scenario.
(relevant documentation: https://doc.akka.io//docs/akka-http/current/routing-dsl/directives/route-directives/redirect.html)
Upvotes: 1