如何防止Akka Http重定向请求中URI的百分比解码?

时间:2020-10-16 04:54:41

标签: scala akka urlencode akka-http

我正在使用Akka Http处理存储在GCS(Google云存储)中的文本资源的签名url重定向。基本上,我在GCS中有一些文件,希望在请求时随API一起提供。不幸的是,该资源的路径中有一个带有=字符的子目录,类似于:https://storage.googleapis.com/path_start/more_path/format=avro/still_more_path/filename.avro

Google存储空间的signUrl方法将已签名的网址中的=字符编码为%3D。我已验证使用此签名的url可以访问GCS中的文件(点击即可开始下载)。问题是,当Akka Http根据请求重定向此签名的url时,它将其解码回等号。这会导致来自GCS的SignatureDoesNotMatch错误:


    <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>

我尝试生成签名的URL,并在以下代码段中将其重定向:

          val signedUrl = cloudStorageService.getSignedUrl(bucketId, filePath)
          logger.info(s"signedUrl: $signedUrl")
          redirect(signedUrl, TemporaryRedirect)

和我的cloudStorageService.getSignedUrl方法在此处分别定义:

      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
      }

第一个代码段中的日志记录语句告诉我,已签名的URL是使用%3D生成的,但是重定向的URL已被百分比解码回=,从而导致SignatureDoesNotMatch错误。

此行为是Akka Http的标准行为。根据{{​​3}}(针对Uri类),所有成员均代表百分比解码元素。可以使用原始查询字符串构造uri,但在我的情况下,编码字符出现在uri路径本身中,而不是查询中。

所以我的问题是,有什么方法可以使Akka Http重定向此签名的url,而无需对路径进行百分比解码?还是我弄错了,还有另一种方法可以解决这个问题?

1 个答案:

答案 0 :(得分:1)

您可能想要“手动”创建重定向响应,而不是使用“ redirect”指令。指令实现为:

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)
      }

您可以引入自己的headers.Location(uri)来代替RawHeader来构建Location标头。您可以在方案中将实体留空。

(相关文档:https://doc.akka.io//docs/akka-http/current/routing-dsl/directives/route-directives/redirect.html

相关问题