[英]How to generate the proper RestTemplate usage from curl?
我有一個可用的 curl 命令,如下所示:
curl -v -H "Content-Type:application/octet-stream" \
-H "x-amz-server-side-encryption:aws:kms" \
-H "x-amz-server-side-encryption-aws-kms-key-id:abcdef81-abcd-4c85-b1d8-ee540d0a5f5d" \
--upload-file /Users/fd/Downloads/video.mp4 \
'https://video-uploads-prod.s3-accelerate.amazonaws.com/ABCDEAQGZHEhM55fvvA/ads-aws_userUploadedVideo?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20200106T165718Z&X-Amz-SignedHeaders=content-type%3Bhost%3Bx-amz-server-side-encryption%3Bx-amz-server-side-encryption-aws-kms-key-id&X-Amz-Expires=86400&X-Amz-Credential=ABCDEFHLWTCWZ2MUPPBQ%2F20200106%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=037949abcd1234b063c75d3d505dd9120dd3fa9250c1ababa152e91fee123ca0'
卷曲工作正常:
* We are completely uploaded and fine
< HTTP/1.1 200 OK
但是,當我嘗試使用 RestTemplate(我使用的是 spring boot 1.5.6)時,我無法讓它工作。 我使用的代碼是:
byte[] media = //video in mp4//;
String uploadUrl = "https://video-uploads-prod.s3-accelerate.amazonaws.com/ABCDEAQGZHEhM55fvvA/ads-aws_userUploadedVideo?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20200106T165718Z&X-Amz-SignedHeaders=content-type%3Bhost%3Bx-amz-server-side-encryption%3Bx-amz-server-side-encryption-aws-kms-key-id&X-Amz-Expires=86400&X-Amz-Credential=ABCDEFHLWTCWZ2MUPPBQ%2F20200106%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=037949abcd1234b063c75d3d505dd9120dd3fa9250c1ababa152e91fee123ca0";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.set("x-amz-server-side-encryption", encryption);
headers.set("x-amz-server-side-encryption-aws-kms-key-id", awsKmsKeyId);
HttpEntity entity = new HttpEntity<>(media, headers);
ResponseEntity<String> respEntity = restTemplate.exchange(uploadUrl, HttpMethod.POST, entity, String.class);
我從 AWS 得到的錯誤是:
<Error>
<Code>AuthorizationQueryParametersError</Code>
<Message>Error parsing the X-Amz-Credential parameter; the Credential is mal-formed; expecting "<YOUR-AKID>/YYYYMMDD/REGION/SERVICE/aws4_request".</Message>
<RequestId>51FF099744C43804</RequestId>
<HostId>FOlLws+txYMP0hKEg7aDjQeeARdn7bJN+lw7q/aGA48hRnr1YEsJrVmRi6oEz+mkpHlTIax5MkI=</HostId>
</Error>
我懷疑 RestTemplate 正在更改 URL 的編碼。 無論如何,是否可以使用 RestTemplate 復制與 curl 完全相同的內容?
我還沒有測試以下方法,但是如果您將擴展的 url 傳遞給 restTemplate 實例怎么辦?
String uploadUrl = "...{your_params_in_placeholders}";
URI expanded = new UriTemplate(url).expand(uploadUrl, <param_values>);
url = URLDecoder.decode(expanded.toString(), "UTF-8");
restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
如果它不起作用,您可以嘗試注意 URL 中的編碼值(我的意思是“%2F”等)
在為此苦苦掙扎之后,我可以讓它發揮作用。 該代碼非常丑陋,但使技巧起作用。 發布給其他人以備不時之需。 無論如何,這並沒有回答我的問題,我想從 curl 命令中獲取確切的 RestTemplate 配置。
我必須使用URLDecoder.decode
手動解碼每個查詢參數,然后使用UriComponentsBuilder.fromHttpUrl
構建 URI 並添加先前解碼的參數
byte[] media = //video in mp4//;
String uploadUrl = "https://video-uploads-prod.s3-accelerate.amazonaws.com/ABCDEAQGZHEhM55fvvA/ads-aws_userUploadedVideo?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20200106T165718Z&X-Amz-SignedHeaders=content-type%3Bhost%3Bx-amz-server-side-encryption%3Bx-amz-server-side-encryption-aws-kms-key-id&X-Amz-Expires=86400&X-Amz-Credential=ABCDEFHLWTCWZ2MUPPBQ%2F20200106%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=037949abcd1234b063c75d3d505dd9120dd3fa9250c1ababa152e91fee123ca0";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.set("x-amz-server-side-encryption", encryption);
headers.set("x-amz-server-side-encryption-aws-kms-key-id", awsKmsKeyId);
HttpEntity entity = new HttpEntity<>(media, headers);
String url = uploadUrl.split("\\?")[0];
String[] urlParams = uploadUrl.split("\\?")[1].split("&");
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
for (String p : urlParams) {
String key = p.split("=")[0];
String value = URLDecoder.decode(p.split("=")[1], StandardCharsets.UTF_8.toString());
params.put(key, Collections.singletonList(value));
}
String uri = UriComponentsBuilder.fromHttpUrl(url)
.queryParams(params)
.build()
.toUriString();
ResponseEntity<String> respEntity = restTemplate.exchange(uri, HttpMethod.PUT, entity, String.class);
您可以在RestTemplate
傳遞URI
而不是String
,這應該可以消除您的錯誤。 在這里發生了同樣的事情。
URI uri = URI.create(urlAsString);
Map response = new RestTemplate().exchange(uri, GET, new HttpEntity(headers), Map.class).getBody();
使用 String 時似乎斜線被十六進制轉義,因此%2F
變為%252F
。 直接傳入 URI 可以避免這種情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.