I am trying to port a class I use to connect to Cryptsy's authenticated API to Python 3.3. I have managed to solve the data type issues, and am getting something that is at least getting a request from the website, but it is rejecting my authentication, this is the code, API keys are not included, for obvious reasons...:
req['method'] = method
req['nonce'] = int(time.time())
post_data = urllib.parse.urlencode(req)
sign = hmac.new(self.Secret, str.encode(post_data), hashlib.sha512).hexdigest()
headers = {
'Sign': sign,
'Key': self.APIKey
}
print('headers: ',headers)
print('post data: ',post_data)
b=urllib.parse.urlencode(headers)
print(b)
test=post_data + '&'+ b
print('test: ',test)
data=test.encode()
print('data: ',data)
ret = urllib.request.urlopen(urllib.request.Request('https://www.cryptsy.com/api', data))
q=ret.read()
w=q.decode()
e=json.loads(w)
return self.post_process(e)
And this is the response from the server:
{'error': 'Unable to Authorize Request - Check Your Post Data', 'success': '0'}
Thanks.
The original script had the DATA and HEADERS components for the Request, but was somehow formatted in a way that confused Python 3 into thinking the HEADERS part was a TIMEOUT argument, and throwing an error about it needing to be an INT. This sent me on a wild goose chase of trying to concatenate the DATA and HEADERS.
Related
I using RestSharp (v 107.3.0.0) to post data on a Web API, when I using postman to test te post is ok, bu when I using RestSharp ever I receive:
"{"message": "TypeError: sign() takes at least 2 arguments (0 given)", "exception": "TypeError"}"
Resumin my code:
var client = new RestClient(http://192.168.2.59);
var request = new RestRequest("api/sign", Method.Post);
/*
here I set some AddParameter, but using parameter or not I ever seen the same error. For that reason I will not put these parementer and too proteted some sensitive proyect information.
*/
RestResponse response = await client.PostAsync(request);
The error will to be clear, but sing is not a method, is a resource.
I know there are many similar kinds of questions available but none of them worked.
Can someone tell me if there is any kind of syntax error for the Testcase below
Create Token
Create Session testsession ${baseUrl} verify=true
${body}= create dictionary clientId=unittest.cc.client clientSecret=RyDQ$xxxxxRtv
${header}= create dictionary Content-Type=application/json
${resp}= POST On Session testsession ${reqUri} json=${body} headers=${header} params=${ApiKeyParameter}
${source data}= Evaluate json.loads("""${resp.content}""") json
${token}= Set Variable ${source data['accessToken']}
#No errors Uptill this much - Bearer token creation was successful after that getting error while using it
${header}= create dictionary Authorization=${tpre} ${token} Content-Type=application/json cookies=ss-id=KF84fFy4txxxxxxxxx76i; ss-pid=StDTDxxxxxxxxxxxxn7r
${body}= get file API/data.txt
log to console ${header}
${resp}= post on session testsession /orders json=${body} headers=${header}
log to console ${resp.status_code}
The problem is every time I run the test I am getting a 400 error. Below is the Python code provided by POSTMAN and the screenshots of the headers used. Now I am not sure of how to get the HOST header in my python or maybe robot framework.
Please let me know if any additional details are needed. I am not sure of headers in the URL formation while get or post request is done
Is there any way to find that out?
import requests
import JSON
url = "https://domain:10001/orders?format=json"
payload = json.dumps({ Can ignore this part
})
headers = {
'Authorization': 'Bearer xxx',
'Content-Type': 'application/json',
'Cookie': 'ss-id=xxx; ss-pid=xxx'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
If you all ever come across this kind of issue don't forget to check the body of the JSON / XML you are sending.
Mine resolved as I was saving the dump JSON in a text file so while reading from the file my code was adding some extra spaces in front so I was getting a 400 error.
For further information try logging the Response Content it must show you the error message.
This question already has an answer here:
Is there a way to update the headers in one feature file and use the Auth token from Karate.config.js?
(1 answer)
Closed 1 year ago.
I'm trying to setup a framework to run Graphql calls and create and E2E environment.
I've got the following setup so far but i can't seem to get the headers part of it working. i have managed to set the auth for each request and it all works but as it logs in for each request it doesn't really work as expected.
I want do the following steps:
run a login Test (different usernames valid/invalid)
run a logout test (Ensure token is removed)
Then login with correct user and extract the "set-cookie" header (to use globally for all future requests)
I was trying to use the following:
Karate-config.js
karate.callSingle('classpath:com/Auth/common-headers.feature', config);
headers.js
function fn() {
var headers = {}
headers["set-cookie"] = sessionAccessId
karate.log('Cookie Value: ', headers)
return headers
}
common-headers.feature
Feature: Login to Application and extract header
Background:
* url serverAuthenticateUri
* header Accept = 'application/json'
Scenario: 'Login to the system given credentials'
Given request { username: '#(username)', password: '#(password)'}
When method post
Then status 200
And match $.success == '#(result)'
And def myResult = response
* def sessionAccessId = responseHeaders['set-cookie'][0]
* configure headers = read('classpath:headers.js')
* print 'headers:', karate.prevRequest.headers
feature-file.feature
Feature: sample test script
Background:
* url serverBaseUri
* def caseResp = call read('classpath:com/E2E/POC/CommonFeatures/CreateCaseRequest.feature')
* def caseReqId = caseResp.response.data.createCaseAndRequest.siblings[0].id
* def caseId = caseResp.response.data.createCaseAndRequest.siblings[0].forensicCaseId
* def graphQlCallsPath = 'classpath:com/E2E/POC/GraphQl/intForensic/'
* def commmonFiles = 'classpath:E2E/CommonFiles/'
Scenario: TC1a - Request Server Details from Config DB (1st Run):
Should handle requesting Server Details Data from Config Database.
* def queryFile = graphQlCallsPath + '20-TC1a_req_req_valid_id.graphql'
* def responseFile = graphQlCallsPath + '20-TC1a_resp_req_valid_id.json'
Given def query = read(queryFile)
And replace query.reqId = caseReqId
And request { query: '#(query)' }
When method post
Then status 200
And json resp = read(responseFile)
And replace resp.reqId = caseReqId
And replace resp.caseID = caseId
And match resp == $
I can log in correctly and i get the set-cookie token but this isn't being passed on the feature-file.feature and i get an error saying "not logged in" in the response.
Any help appreciated! I might be looking at this totally wrong and i have tried to follow the shared-scope as much as i can but can't understand in.
Please make this change and hopefully that works !
headers["set-cookie"] = karate.get('sessionAccessId');
Why is explained here: (read the whole section carefully) https://github.com/intuit/karate#configure-headers
EDIT: one more suggestion:
var temp = karate.callSingle('classpath:com/Auth/common-headers.feature', config);
karate.configure('headers', { 'set-cookie': temp.sessionAccessId });
Some extra suggestions:
If you have just started with Karate - based on your question I would suggest you get one flow working in a single Scenario first without any use of call and with nothing whatsoever in karate-config.js. Hard-code everything and get it working first. Use the header keyword to set any headers you need. I also see you are trying to set a set-cookie header (which may work) but Karate has a special keyword for cookie.
And don't even think about callSingle() to start with :)
Once you get that first "hard-coded" flow working, then attempt to configure headers and then only finally try to do "framework" stuff. You seem to have jumped straight into super-complexity without getting the basics right.
Please read this other answer as well, because I suspect that you or someone in your team is attempting to introduce what I refer to as "too much re-use": https://stackoverflow.com/a/54126724/143475 - try not to do this.
Also note that your question is so complex that I have not been able to follow it, so please ask a simpler or more specifc question next time. If you still are stuck, kindly follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue
I'm not too familiar with the arduino c+ language, but I would like to get this native code to work.
In curl this works:
curl "http://access.alchemyapi.com/calls/text/TextGetTextSentiment?text=i+feel+great&outputMode=json&apikey=my-apikey"^C
So I am trying to use a WiFi client for the same request but it seems the passing and parsing of the URL parameters is causing a problem.
sprintf(request,"/calls/text/TextGetTextSentiment?apikey=%s&text=%s&outputMode=%s","31adba6dfc3a879b88762f50efc9f892bd573207", "i+feel+great", "json");
Serial.println(request);
When I print the request, everything after the & gets truncated.
char serverName[] = "access.alchemyapi.com";
if(client.connect(serverName,port) == 1)
{
sprintf(outBuf,"GET %s HTTP/1.1",page);
client.println(outBuf);
sprintf(outBuf,"Host: %s",serverName);
client.println(outBuf);
client.println(F("Connection: close\r\n"));
}
This works (HTTP status 200, though with missing parameters error from the API service) if I only pass in 1 parameter.
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).