Will try to be precise in asking question. Sorry if couldn't do it up to the mark!
Was given an assignment to automate api from the given below link
https://restful-booker.herokuapp.com/apidoc/index.html
Using the Api chaining I am suppose to automate "Update booking" api by first generating token from "Create Token" api and passing it in headers for authorization. I checked it on postman its working fine there for karate I wrote this code
* def auth_token = response.token
Given url 'https://restful-booker.herokuapp.com/booking/5591'
* def request_header = { Accept: '*/*' , Accept-Encoding : 'gzip, deflate, br' , Connection : 'keep-alive', Content-Type : 'application/json' , Accept : 'application/json' , Cookie : 'token=' + auth_token }
the variable auth_token is getting token from the first api response and under same scenario I am trying to run update api by using above headers but it keeps giving this error
net.minidev.json.parser.ParseException: Unexpected token + at position 168.
Could not find a valid solution so dropping question here.
I think you need to read and understand the docs, that's not how you set request headers. Here's what I think you were trying to do, and I hope that this helps others who try to use this "Restful Booker" application.
Feature:
Scenario:
* url 'https://restful-booker.herokuapp.com'
* path 'auth'
* request { username: 'admin', password: 'password123' }
* method post
* status 200
* def token = response.token
* header Accept = 'application/json'
* path 'booking'
* request
"""
{
"firstname" : "Jim",
"lastname" : "Brown",
"totalprice" : 111,
"depositpaid" : true,
"bookingdates" : {
"checkin" : "2018-01-01",
"checkout" : "2019-01-01"
},
"additionalneeds" : "Breakfast"
}
"""
* method post
* status 200
* path 'booking', response.bookingid
* cookie token = token
* method delete
* status 201
Related
I am trying to query my cosmos db for documents and I am having trouble generating the correct authorization header, the example in the official documentation does not show querying.
I am trying it in Postman using Javascript by POST to this URI:
POST https://MyDatabase.documents.azure.com:443/dbs/MyContainer/colls/MyDocuments/docs
With these headers:
The authorization is generated like this:
var now = new Date().toUTCString();
pm.request.headers.upsert({key: "x-ms-date", value: now })
var verb = 'POST';
var resourceType = "docs";
var resourceLink = 'dbs/MyContainer/colls/MyCollection/docs';
var text = (verb || "").toLowerCase() + "\n" +
(resourceType || "").toLowerCase() + "\n" +
(resourceLink || "") + "\n" +
now.toLowerCase() + "\n" +
"" + "\n";
//Hash and Encode by using the masterkey.
var key = CryptoJS.enc.Base64.parse("MyMasterKey");
var signature = CryptoJS.HmacSHA256(text, key).toString(CryptoJS.enc.Base64);
var authToken = encodeURIComponent("type=master&ver=1.0&sig=" + signature);
pm.request.headers.upsert({key: "Authorization", value: authToken })
Here is the error I am getting:
{
"code": "Unauthorized",
"message": "The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'post\ndocs\ndbs/MyContainer/colls/MyCollection\nwed, 27 may 2020 19:34:41 gmt\n\n'\r\nActivityId: 724657c7-0532-4c5d-a7ff-c95900ef13cf, Microsoft.Azure.Documents.Common/2.11.0"
}
I am guessing my signature is created wrong, what is the correct format?
Our docs on our Authorization Header should have what you're looking for.
hope this is helpful.
A required fix for your scenario is that you have to remove "/docs" at the end of the resourceLink value -keep it in the request URL- and also if your containter was created using a partitionKey you have to add the following header:
'x-ms-documentdb-query-enablecrosspartition': true
I am sending a PATCH request to my DRF server in Postman and it works perfect
However when I do the same in Python I get:
<Response [405]> http://127.0.0.1:8000/api/title/8174/
b'{"detail":"Method \\"PATCH\\" not allowed."}'
Method Not Allowed
My function that sends data:
ss_token = os.getenv('SS_TOKEN')
headers = {
'Authorization': 'Token ' + ss_token,
}
source = Source.objects.all().first()
url = source.url + str(self.ss_id) + '/'
response = requests.patch(source.url, headers=headers, data={'key':'value'})
print(response, url)
print(response.content)
print(response.reason)
return True
Do I have to send other headers to the API to make the PATCH work?
Ah looks like I made a mistake. Forgot to replace source.url with the new url variable called 'url' variable. Because that add the 'ss_id' at the url' so it becomes 'api/title/ID/' instead of just 'api/title'
url = source.url + str(self.ss_id) + '/'
response = requests.patch(url, headers=headers, data={'key':'value'})
I'm trying to create new order on PayU, via their REST api. I'm sending "get access token", and i have correct answer. Then i send 'create new order', aaaaand i ve got 103 error, error syntax.
I was trying on https://webhook.site/ , and realized why syntax is bad - i have no values in list.
Code of sending POST, when creating new order:
data = {
"notifyUrl": "https://your.eshop.com/notify",
"customerIp": "127.0.0.1",
"merchantPosId": "00000",
"description": "RTV market",
"currencyCode": "PLN",
"totalAmount": "15000",
"products": [{
"name": "Wireless mouse",
"unitPrice": "15000",
"quantity": "1"}]}
headers = {
"Content-Type": "application/json",
"Authorization": str('Bearer ' + access_token).encode()}
r = requests.post('https://webhook.site/9046f3b6-87c4-4be3-8544-8a3454412a55',
data=payload,
headers=headers)
return JsonResponse(r.json())
Webhooc show what i have posted:
customerIp=127.0.0.1¬ifyUrl=https%3A%2F%2Fyour.eshop.com%2Fnotify¤cyCode=PLN&products=name&products=unitPrice&products=quantity&description=RTV+market&merchantPosId=00000&totalAmount=15000
There is no values of 'name', 'unitprice' and 'quantity'. PayU confirmed thats the only problem.
Why? What is wrong?
Sending simple POST request to get a token is always successful.
If you want to send JSON, use the json argument of post():
r = requests.post('https://webhook.site/9046f3b6-87c4-4be3-8544-8a3454412a55',
json=payload, # Use the json argument
headers=headers)
Otherwise the data will be sent as form-encoded data, which I guess isn't what you want, given you're expecting to send the nested products list.
When you use the json argument, the content type is automatically set to application/json so you don't have to set it yourself.
headers = {
# Content-Type not required
"Authorization": str('Bearer ' + access_token).encode()
}
Further info on using requests to send JSON here
This is with respect to google drive API integration where I have a Lambda python event code that gets triggered when I do . This is the push notification implentation of Google drive API.
In order to allow google drive push notification to call us, I have created the associated api gateway endpoint as webhook using their API. Now this lambda do gets triggered when I edit the file so this means that webhook is successful and google calls back the hook.
Google Drive sends HTTP POST messages to the webhook url once you do any change.
The following HTTP headers are returned with empty body to the lambda function:
{
"Content-Type": "application/json; utf-8",
"Content-Length": "5000",
"X-Goog_Channel-ID": "05a349fd-c363-4d8c-9409-8b6f310b7379",
"X-Goog-Channel-Token": "to66728b-21c7-4605-8445-d7a297b9ae7f",
"X-Goog-Channel-Expiration": "Fri, 14 Oct 2016 20:05:58 GMT",
"X-Goog-Resource-ID": "SuIweVX_iBzKmM5PQVMbIDYFrr8",
"X-Goog-Resource-URI": "https://www.googleapis.com/drive/v3/files/1QvVo67IJ3_o5g2tCyxpNA29JHx183-bOOblKMoSAGv4?acknowledgeAbuse=false&alt=json",
"X-Goog-Resource-State": "update",
"X-Goog-Changed": "content,properties",
"X-Goog-Message-Number": "480896"
}
However, the event object of lambda handler is empty. I assume that event object is the HTTP body and in my case the body is empty, so I have added custom mapping template in Integration Request (to retrieve headers) of the API Gateway POST method as the following:
#set($inputRoot = $input.path('$'))
{
"Content-Type" : "$input.params('Content-Type')",
"Content-Length" : "$input.params('Content-Length')",
"X-Goog-Channel-ID" : "$input.params('X-Goog-Channel-ID')",
"X-Goog-Channel-Token" : "$input.params('X-Goog-Channel-Token')",
"X-Goog-Channel-Expiration" : "$input.params('X-Goog-Channel-Expiration')",
"X-Goog-Resource-ID" : "$input.params('X-Goog-Resource-ID')",
"X-Goog-Resource-URI" : "$input.params('X-Goog-Resource-URI')",
"X-Goog-Resource-State" : "$input.params('X-Goog-Resource-State')",
"X-Goog-Changed" : "$input.params('X-Goog-Changed')",
"X-Goog-Message-Number" : "$input.params('X-Goog-Message-Number')",
"body" : $input.json('$')
}
But I am not sure how should I retrieve these headers from event object if at all they are getting received from google drive. Just logging the event object shows it as empty {}. What is the expected mapping if the above is incorrect? Also, event['header-name'] is not even getting executed it seems as when I print
print 'Event header:{}'.format(event['header-name']) I don't even get Event header statement in the logs. So it means the line is not exceuted but the line above that is executed which is simple print statement like print 'Printing results' I am not sure why the code is not getting there or if there is an error.
Could you please guide me how we can retrieve headers using event object in python? And if all my steps above look correct or am I missing something?
I was able to get this working without any problem. I can't tell from your post why your event object is empty. My best guess is that you forgot to add the headers to the "HTTP Request Headers" section of the Method Request.
Here's my Lambda function:
from __future__ import print_function
import json
print('Loading function')
def lambda_handler(event, context):
print("Received event: " + json.dumps(event, indent=2))
print("Content-Type = " + event['Content-Type'])
print("Content-Length = " + event['Content-Length'])
print("X-Goog-Channel-ID = " + event['X-Goog-Channel-ID'])
print("X-Goog-Channel-Token = " + event['X-Goog-Channel-Token'])
print("X-Goog-Channel-Expiration = " + event['X-Goog-Channel-Expiration'])
print("X-Goog-Resource-ID = " + event['X-Goog-Resource-ID'])
print("X-Goog-Resource-URI = " + event['X-Goog-Resource-URI'])
print("X-Goog-Resource-State = " + event['X-Goog-Resource-State'])
print("X-Goog-Changed = " + event['X-Goog-Changed'])
print("X-Goog-Message-Number = " + event['X-Goog-Message-Number'])
print("body = " + event['body'])
return {
'statusCode': '200',
'body': event['body'],
'headers': {
'Content-Type': 'application/json',
'X-Goog-Channel-ID': event['X-Goog-Channel-ID'],
'X-Goog-Channel-Token': event['X-Goog-Channel-Token'],
'X-Goog-Channel-Expiration': event['X-Goog-Channel-Expiration'],
'X-Goog-Resource-ID': event['X-Goog-Resource-ID'],
'X-Goog-Resource-URI': event['X-Goog-Resource-URI'],
'X-Goog-Resource-State': event['X-Goog-Resource-State'],
'X-Goog-Changed': event['X-Goog-Changed'],
'X-Goog-Message-Number': event['X-Goog-Message-Number'],
}
}
My mapping template is the same as yours.
Here's the return value from a test call, using the same input headers from your example:
{
"body": "Test input body content",
"headers": {
"X-Goog-Resource-ID": "SuIweVX_iBzKmM5PQVMbIDYFrr8",
"X-Goog-Channel-ID": "",
"X-Goog-Resource-State": "update",
"X-Goog-Changed": "content,properties",
"X-Goog-Resource-URI": "https://www.googleapis.com/drive/v3/files/1QvVo67IJ3_o5g2tCyxpNA29JHx183-bOOblKMoSAGv4?acknowledgeAbuse=false&alt=json",
"X-Goog-Message-Number": "480896",
"X-Goog-Channel-Token": "to66728b-21c7-4605-8445-d7a297b9ae7f",
"Content-Type": "application/json",
"X-Goog-Channel-Expiration": "Fri, 14 Oct 2016 20:05:58 GMT"
},
"statusCode": "200"
}
I'm looking for a way to add 2 custom cookies to every http request.
The browsermob proxy (https://github.com/lightbody/browsermob-proxy) has removeHeaders() and addHeader() methods, but what can I do to keep existing cookies in request, but add 2 more cookies?
Thanks!
You can use this method to invoke your custom js code in each request/response
https://github.com/lightbody/browsermob-proxy#http-request-manipulation
Some example in Python
def response_interceptor(self, js):
"""
Executes the javascript against each response
:param js: the javascript to execute
"""
r = requests.post(url='%s/proxy/%s/interceptor/response' % (self.host, self.port),
data=js,
headers={'content-type': 'x-www-form-urlencoded'})
return r.status_code
def request_interceptor(self, js):
"""
Executes the javascript against each request
:param js: the javascript to execute
"""
r = requests.post(url='%s/proxy/%s/interceptor/request' % (self.host, self.port),
data=js,
headers={'content-type': 'x-www-form-urlencoded'})
return r.status_code
and test:
def test_request_interceptor_with_parsing_js(self):
"""
/proxy/:port/interceptor/request
"""
js = 'alert("foo")'
status_code = self.client.request_interceptor(js)
assert(status_code == 200)
As I answered above, you could use proxy's REST API to set custom js handler on every request, made through the proxy.
For example you could add any custom cookies to every request:
curl -X POST -H 'Content-Type: text/plain' -d 'js code' http://10.100.100.20:8080/proxy/8081/interceptor/request
In php it would look like:
/**
* #param Proxy $proxyObject
* #param array $cookiesArray
*/
protected function _setRequestCookies(Proxy $proxyObject, array $cookiesArray)
{
foreach ($cookiesArray as $nameString => $valueString) {
$cookiesArray[$nameString] = $nameString . '=' . $valueString;
}
$jsHandlerString = sprintf(
'var c = request.getMethod().getFirstHeader("Cookie") ? request.getMethod().getFirstHeader("Cookie").getValue() : ""; request.getMethod().setHeader("Cookie", c + "; %s");',
implode('; ', $cookiesArray)
);
$urlString = sprintf('%sproxy/%u/interceptor/request', $this->_hubUrlString, $proxyObject->getPort());
$this->_requesterObject->makeRequest($urlString, Requester::REQUEST_METHOD_POST, $jsHandlerString);
}