简体   繁体   English

如何从 curl 生成正确的 RestTemplate 用法?

[英]How to generate the proper RestTemplate usage from curl?

I have a working curl command that is below:我有一个可用的 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'

The curl is working properly:卷曲工作正常:

* We are completely uploaded and fine
< HTTP/1.1 200 OK

However, when I try to use RestTemplate (i'm using spring boot 1.5.6) I'm not able to make it work.但是,当我尝试使用 RestTemplate(我使用的是 spring boot 1.5.6)时,我无法让它工作。 The code I use is:我使用的代码是:

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

The error I get from AWS is:我从 AWS 得到的错误是:

<Error>
   <Code>AuthorizationQueryParametersError</Code>
   <Message>Error parsing the X-Amz-Credential parameter; the Credential is mal-formed; expecting "&lt;YOUR-AKID&gt;/YYYYMMDD/REGION/SERVICE/aws4_request".</Message>
   <RequestId>51FF099744C43804</RequestId>
   <HostId>FOlLws+txYMP0hKEg7aDjQeeARdn7bJN+lw7q/aGA48hRnr1YEsJrVmRi6oEz+mkpHlTIax5MkI=</HostId>
</Error>

My suspicion is that RestTemplate is changing the encoding of the URL.我怀疑 RestTemplate 正在更改 URL 的编码。 Is there anyway to replicate exactly the same as curl with RestTemplate?无论如何,是否可以使用 RestTemplate 复制与 curl 完全相同的内容?

I haven't test the following approach but what if you pass an expanded url to a restTemplate instance?我还没有测试以下方法,但是如果您将扩展的 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);

If it doesn't work you can try to pay some attention to the encoded values in your URL(I mean "%2F" and so on)如果它不起作用,您可以尝试注意 URL 中的编码值(我的意思是“%2F”等)

I could make it work after struggling a lot with this.在为此苦苦挣扎之后,我可以让它发挥作用。 The code is pretty ugly but made the trick to work.该代码非常丑陋,但使技巧起作用。 Post for others in case you need it.发布给其他人以备不时之需。 Anyway, this is not answering my question I want get the exact RestTemplate configuration out of a curl command .无论如何,这并没有回答我的问题,我想从 curl 命令中获取确切的 RestTemplate 配置

I had to manually decode each query param with URLDecoder.decode and then built the URI with UriComponentsBuilder.fromHttpUrl and added the previously decoded params我必须使用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);

You can pass a URI as opposed to a String in your RestTemplate and that should get rid of your error.您可以在RestTemplate传递URI而不是String ,这应该可以消除您的错误。 Had the same thing happening here.在这里发生了同样的事情。

URI uri = URI.create(urlAsString);
Map response = new RestTemplate().exchange(uri, GET, new HttpEntity(headers), Map.class).getBody();

It seems like slashes are being hex-escaped when using a String so %2F becomes %252F .使用 String 时似乎斜线被十六进制转义,因此%2F变为%252F Passing in a URI directly avoids that.直接传入 URI 可以避免这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM