Encoded path is encoded again - karate

I have to make a request:
* url foo
* path bar
* path code
Code is retrieved from another request and I receive it url encoded.
The problem is when I put it in the path, karate encode it again.
Ex: I receive zxc1J%2BV%2FMnb and in path it becomes zxc1J%252BV%252FMnb.
%2Bis replaced by %252B.
When I decode received code and put it in path, it is not encoded.
My javascript function to decode is :
* def codeDecoded = decodeURIComponent(code)
and encoding function is * def codeEncoded = encodeURIComponent(codeDecoded)
Am I missing smth? What is wrong? How can I manage this? Thanks.
Edit:
#Peter Thomas I try my last chance, because I already showed the prb to someone from server and he didn't understand why karate encodes again smth already encoded and doesn't encode smth decoded.
So my first request is a POST request, which returns an encoded code in responseHeaders. Ex: GVkX1%2FKZEi%2FWQ.
In my second request I have to take this code and put it in the path ex: url/GVkX1%2FKZEi%2FWQ.
The problem is that karate transforms it to url/GVkX1%252FKZEi%252FWQ . And I don't need it. And if I decode url/GVkX1%2FKZEi%2FWQ before to put it in path, the url in karate is url/GVkX1/KZEi/WQ. When put in path, the decoded code is not encoded in karate. I hope it is more understandable.

Yes Karate will always encode the path you provide for your convenience. This is what 99% of users expect anyways.
There is nothing wrong with using a custom function to decode and ensure you pass un-encoded URL / path values to Karate, so by all means, please continue to do so !
Edit: quite likely the way you tried to decode may be wrong, try this:
* def encoded = 'zxc1J%2BV%2FMnb'
* def decoded = java.net.URLDecoder.decode(encoded, 'UTF-8')
* print decoded
Which prints:
[print] zxc1J+V/Mnb

Related

Karate / Post Request : Unable to pass random generator variable in json payload

I am trying to create Karate feature file for API Testing.
It is a post request and we have to pass random number for 1 field i.e. order in request payload every time.
Now, I am trying to use this function in the same feature file to pass that random generated value in json payload before sending post request.
Could someone please have a look at my feature file and help.
Thanks
Also, Is there a way if i want to pass this same random value for a json payload created as a separate request.json payload file
Your requestPayload is within double quotes, so it became a string.
Here's an example that should get you going. Just paste it into a new Scenario and run it and see what happens.
* def temp1 = 'bar'
* url 'https://httpbin.org/anything'
* def payload = { foo: '#(temp1)' }
* request payload
* method post
And please read the documentation and examples, it will save a you a lot of time.

Karate: How to send raw request and disable embedded expressions

How can I send a raw request wrapped in parentheses and prevent Karate from parsing it as "embedded expression"?
Example 1: Correctly sends the string '(1+2)' as payload (as expected).
Given request '(1+2)'
Example 2: The same string as multi-line is detected as "embedded expression" and converted by Karate to type number 3 (you can see it clearly in the logs and in the receiving API):
Given request
"""
(1+2)
"""
Why is that and how can I send real raw strings, no matter what's inside? In other words: How to disable embedded expressions?
My background is that I need to send multi-line raw strings as payload. Some sub-strings are wrapped in parentheses and this would then lead to errors in the receiving API (to simplify my question I reduced the examples to 1 line).
Use text: https://github.com/intuit/karate#text
* url 'https://httpbin.org'
* path 'anything'
* text body =
"""
(1+2)
"""
* request body
* method post
Refer to the docs for "type conversion" also. And another reference: https://stackoverflow.com/a/64328206/143475

How to pass a json file as a value for a key under request body of a feature file

enter image description hereI am creating a feature file using Karate framework and as per that i need to pass a json file as key value pair in the request body
eg
Given url
And def textJson = text1
And request{test:'test1.json',test2:'description text'}
when post
then status 200
enter image description here
the json file is read into a variable in another feature file and passed on to this feature file.
As of now i am getting the requested file is missing basically its not reading
Given url
And def textJson = text1
And request{test:'test1.json',test2:'description text'}
So if I understand this correctly, you intend to input the data from a json file into the test key under request. You are currently passing in a string instead of actually reading in a file. To read in a json file and save it as a variable try the following syntax.
And def test1 = read('test1.json')
And request { test1: '#(test1)'}
I am a little confused at some of the other syntax you have included. I can point out a couple other problems in the syntax.
Given url #You need to actually have a url after the url keyword
And def textjson = test1 #This does not seem to point to a reference
And request {test: 'test1.json', test2: 'description text'} # The test is not actually reading json in but the string "test1.json"
I wasn't exactly sure the scope of this question, but I hope that this helps.

Unable to upload multipart file in karate, Required request part '' not present

ActualAPIRequest OutputFromKarate
Trying to upload a json file for an api using karate. Since api takes multipart input i am passing multipart configurations in karate.
But Required request part 'inputData' not present error is coming. Is there any solution for this please?
I have attached actual input and result from karate screenshot for reference
Just make sure that the data type of inputData and maybe swaggerFile is JSON. Looks like you are sending a string.
Please refer to this section of the doc: https://github.com/intuit/karate#type-conversion
If the server does not like the charset being sent for each multipart, try * configure charset = null

Problems Connecting to MtGox API 2 with Python

I am writing a trading program that I need to connect to MtGox (a bitcoin exchange) through the API v2. But I keep getting the following error:
URL: 1 https://data.mtgox.com/api/2/BTCUSD/money/bitcoin/address
HTTP Error 403: Forbidden.
Most of my script is a direct copy from here (that is a pastebin link). I just had to change it to work with Python 3.3.
I suspect that it has to do with the part of script where I use base64.b64encode. In my code, I have to encode my strings to utf-8 to use base64.b64encode:
url = self.__url_parts + '2/' + path
api2postdatatohash = (path + chr(0) + post_data).encode('utf-8') #new way to hash for API 2, includes path + NUL
ahmac = base64.b64encode(str(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest()).encode('utf-8'))
# Create header for auth-requiring operations
header = {
"User-Agent": 'Arbitrater',
"Rest-Key": self.key,
"Rest-Sign": ahmac
}
However, with the other guy's script, he doesn't have too:
url = self.__url_parts + '2/' + path
api2postdatatohash = path + chr(0) + post_data #new way to hash for API 2, includes path + NUL
ahmac = base64.b64encode(str(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest()))
# Create header for auth-requiring operations
header = {
"User-Agent": 'genBTC-bot',
"Rest-Key": self.key,
"Rest-Sign": ahmac
}
I'm wondering if that extra encoding is causing my header credentials to be incorrect. I think this is another Python 2 v. Python 3 problem. I don't know how the other guy got away without changing to utf-8, because the script won't run if you try to pass a string to b64encode or hmac. Do you guys see any problems with what I am doing? Is out code equivalent?
This line specifically seems to be the problem -
ahmac = base64.b64encode(str(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest()).encode('utf-8'))
To clarify, hmac.new() creates an object to which you then call digest(). Digest returns a bytes object such as
b.digest()
b'\x92b\x129\xdf\t\xbaPPZ\x00.\x96\xf8%\xaa'
Now, when you call str on this, it turns to
b'\\x92b\\x129\\xdf\\t\\xbaPPZ\\x00.\\x96\\xf8%\\xaa'
So, see what happens there? The byte indicator is now part of the string itself, which you then call encode() on.
str(b.digest()).encode("utf-8")
b"b'\\x92b\\x129\\xdf\\t\\xbaPPZ\\x00.\\x96\\xf8%\\xaa'"
To fix this, as turning bytes into a string back into bytes was unnecessary anyhow(besides problematic), I believe this will work -
ahmac = base64.b64encode(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest())
I believe you are likely to find help in a related question of mine although it deals with the WebSocket API:
Authenticated call to MtGox WebSocket API in Python 3
Also, the HTTP 403 error seems to indicate that there is something fundamentally wrong with the request. Even if you threw the wrong authentication info at the API you should have gotten an error message as a response and not a 403. My best guess is that you are using the wrong HTTP method so check if you are using the appropriate one (GET/POST).