Spring MVC can not decode query parameter value from restTemplate - resttemplate

I have an Spring boot application. For one endpoint,
I use a swagger to call it. What I input is: "FGluxxdw==", then swagger will auto encode as "FGluxxdw%3D%3D", but the endpoint would auto decode the value back as "FGluxxdw==", following is the whole swagger request sample:
curl -X GET "http://localhost:8080/order/scroll?size=1&orderItemNumber=XX1468&scrollId=FGluxxdw%3D%3D"
-H "accept: application/hal+json"
-H "Authorization: Bearer SOME_VALUE"
-H "api-key: ABC-123"
However, if I use restemplate,
this.restTemplate.exchange(uri, GET, httpEntity, PRODUCT.class))
And the uri value is
http://localhost:8080/order/scroll?size=1&orderItemNumber=XX1468&scrollId=FGluxxdw%3D%3D
However, spring boot endpoint can not decode the scrollId this time.

This question was asked a couple of months ago. Leaving this here to help others. Try:
Use UriComponentsBuilder.
Set charset to UTF_8.
Build Uri not UriString.
UriComponentsBuilder uriBuilder = UriComponentsBuilder
.fromHttpUrl("http://localhost:8080/order/scroll")
.encode(StandardCharsets.UTF_8)
.queryParam("size", 1)
.queryParam("orderItemNumber", "XX1468")
.queryParam("scrollId", "FGluxxdw==");
URI uri = uriBuilder.build().toUri();

Related

Problems with redirecting to signed cloud storage URL (cURL?)

I am creating a Firebase HTTP function that uploads a file to Cloud Storage, creates a signed URL to the file, and then redirects the client to that URL. Using Postman with automatic redirect following turned on, the file is retrieved correctly. However, if I try to turn on redirects while using cURL (curl -L -H "Content-Type: application/json" "https://us-central1-example.cloudfunctions.net/exampleFunction" -d '{"example": true}'), the following error is returned by Cloud Storage:
<?xml version='1.0' encoding='UTF-8'?>
<Error>
<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>
<StringToSign>GET
application/json
1602245678
/example.appspot.com/exampleBucket/exampleFile.txt</StringToSign>
</Error>
If I make the request with form encoded data instead, it works in cURL as well: curl -L "https://us-central1-example.cloudfunctions.net/exampleFunction" -d "example=true"
If I try to manually make a GET request to the URL in Postman, I get an equivalent error:
<?xml version='1.0' encoding='UTF-8'?>
<Error>
<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>
<StringToSign>GET
1602246219
/www.google.com/example.appspot.com/exampleBucket/exampleFile.txt</StringToSign>
</Error>
If I paste the URL into a browser or use cURL to download the signed URL, the file is also downloaded correctly.
I am using the following function to get the signed url:
async getSignedUrl(file: File, expireAt: number): Promise<string> {
const [url] = await file
.getSignedUrl({
action: "read",
expires: expireAt
});
return url
}
which returns a signed URL in the following format:
https://storage.googleapis.com/example.appspot.com/exampleBucket/exampleFile.txt?GoogleAccessId=[Access ID]&Expires=1602246219&Signature=[Signature] (I've noted that the value of "Expires" is the same value returned in the tag).
My suspicion is that Postman and cURL adds something to the request which results in a different signature, but I am not sure exactly what is going on.
What is happening when letting cURL follow the redirect or when creating a GET request in Postman, that leads to this difference in signature?
If I understood correctly, the issue arises in two scenarios
When hitting your CF through curl with
curl -L -H "Content-Type: application/json" "https://us-central1-example.cloudfunctions.net/exampleFunction" -d '{"example": true}')
According to the example in github in the docs Signed URL v4, 'Content-Type: application/octet-stream' should be used:
curl -X PUT -H 'Content-Type: application/octet-stream' --upload-file my-file '${url}'
I tried with the following with successfully result:
curl -X PUT -H 'Content-Type: application/octet-stream' -d '{"example": true}' 'https://storage.googleapis.com/...'
If I try with the content-type you shared with failed results.
2.
If I try to manually make a GET request to the URL in Postman, I get an equivalent error:
I tried a simple GET in postman using a Signed URL and it worked just fine
Command used in gsutil to get the signed URL:
gsutil signurl -d 10m key.json gs://BUCKET/aa.png
Then I tried a GET on postman and worked just fine.
I also tried with a Signed URL to upload a File in Postman and worked just fine.
My thoughts are that, according to Common MIME types
application/octet-stream is the default value for all other cases (not textual files).
When you set the content type as application/json you specify a JSON format, but not an object or file. That's why it works with the following, since you are not specifying the header content-type, the default is taken application/octet-stream
curl -L "https://us-central1-example.cloudfunctions.net/exampleFunction" -d "example=true"
Joss Barons answer helped me in the right direction, but it is not true that the Content-Type has to be application/octet-stream. That is only used for creating a signed url that can be used for uploading a file. In my case, when creating the signed url using the Cloud Storage SDK for node, I didn't specify a Content-Type, so when sending a GET request to the signed url, it must not contain a Content-Type header.

How to use invoke http to perform GET request in nifi?

I need to perform a get request from nifi to couchbase. The curl command is:
curl http://HOST:PORT/query/service -d "statement=select item.Date from bucket unnest bucket as item" -u USER:PASSWORD
I tried using InvokeHttp and ExecuteStreamCommand but it keeps returning errors(status code 400). The full error message is:
{ "requestID": "bff62c0b-36fd-401d-bca0-0959e0944323", "errors":
[{"code":1050,"msg":"No statement or prepared value"}], "status":
"fatal", "metrics": {"elapsedTime": "113.31µs","executionTime":
"74.321µs","resultCount": 0,"resultSize": 0,"errorCount": 1
It's important to say that I prefer that the http request will be triggered by an incoming flowfile. I tried using the processors in various of ways but non of them worked.
When I run the command from the nifi server it works fine.
Thanks for the help
the -d parameter of the curl utility forces HTTP POST command
and application/x-www-form-urlencoded mime-type.
so, in the nifi InvokeHTTP select the following parameters
HTTP Method = POST
Remote URL = <your url here>
Basic Authentication Username = <username>
Basic Authentication Password = <password>
Content-Type = application/x-www-form-urlencoded
and the body of the flow file should be
statement=select item.Date from bucket unnest bucket as item
I don't know nifi, but based on the error message, the "statement=" part of the request isn't being included, or you are not sending the request as a POST command.

Use httr to create POST call for Bearer token

I am using R.
I am new to API's and trying to figure out how to put the post call together to get the required bearer token.
I am using the Experian Sandbox.
Once I have the bearer token i'm good but getting the Post call put together is proving to be very difficult for me.
+below was clipped from the developer portal.
The call to get the Oauth2 token is a POST request with a Content-Type
which needs to be specified as JSON; the response will also be in JSON
format:
Request example:
curl -X POST
-d '{"username": "youremail#email.com", "password": "YOURPASSWORD"}'
-H "Client_id: xxxxxxxxxxxxxxxxxxxxxxxx"
-H "Client_secret: xxxxxxxxx"
-H "Cache-Control: no-cache"
-H "Content-Type: application/json"
"https://sandbox-us-api.experian.com/oauth2/v1/token"
The following solution took care of my issue should anyone else need it for future reference. Thank you to R Community on helping to get me up to date on how this call is performed.
post_req <- httr::POST(
"https://sandbox-us-api.experian.com/oauth2/v1/token",
add_headers(
"Content-Type" = "application/json",
"Cache-Control"="no-cache",
"Client_secret"="xxxxxxxxxx",
"Client_id"="xxxxxxxxxxxxxxxxx"),
body = '{"username": "youremail#email.com", "password": "YOURPASSWORD"}',
verbose()
)

Using JSON in Header in Python Requests library

I want to make a request to an API which expects a JSON to be sent in the Header field. I'm unable to do it in Python Request library.
I'm able to do it in cURL.
cURL code:
curl -v -X POST https://content.dropboxapi.com/2/files/download
--header "Authorization: Bearer abcdefgh12343567"
--header "Dropbox-API-Arg: {\"path\": \"/folder/file.mp4\"}" -o file.mp4
Python code:
import requests
import simplejson
r = requests.post(
'https://content.dropboxapi.com/2/files/download',
headers={
'Authorization':'Bearer abcdefgh12343567',
'Dropbox-API-arg': simplejson.dumps({'path': '/folder/file.mp4'})
})
Here the Header contains a JSON string.
I'm trying to use Dropbox's files/download API documented here.
Even though the request is sent, the JSON value seems to be wrong.
The above code seems to work correctly now. I'm not sure about what happened - I was receiving HTTP 409 error earlier.
I was doubtful about how Python Requests Library would handle JSON string inside the header. So, I created an API to see how the server would read the headers made by both cURL and Python Requests. Both headers are identical.

Microsoft cognitive API token doesn't work

I'm trying to use the Microsoft cognitive API for text analysis using the recommended curl method from their documentation:
curl -v -X POST "https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment" -H "Content-Type: application/jscp-Apim-Subscription-Key: {bc94cba9b84748ebb2f2b79a28ee3450}" --data-ascii "{I had a wonderful experience! The rooms were wonderful and the staff were helpful.}"
But I get back:
{ "statusCode": 401, "message": "Access denied due to invalid subscription key. Make sure to provide a valid key for an active subscription." }
I also tried removing the {} surrounding token and text to be analyzed. What am I doing wrong here?
Note: yes I realize the security issue with showing key but I have re-generated thanks.
There are three issues with your request:
Content-Type header should be application/json. This is likely a copy-paste error.
Ocp-Apim-Subscription-Key header value must be the API without the curly braces. This is the cause for your 401 error.
The body must be JSON of a particular format. You can find the schema here.
Here's the rewritten request:
curl -v "https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: $OXFORD_TEXT_KEY" --data-ascii '{"documents":[{"language":"en","id":"1234","text":"I had a wonderful experience! The rooms were wonderful and the staff were helpful."}]}'
Which should result in:
{"documents":[{"score":0.9750894,"id":"1234"}],"errors":[]}

Resources