Replicating Postman endpoints with vanilla python requests - python-requests

After not being able to get the provided python API to work (I simply do not know enough about authentication), but being able to use provided Postman collections to work,
I decided to try and replicate these Collection Endpoints in Python.
I got off to a good start with the auth endpoint
Here it is in Postman:
and my python code replicating this:
base_url = 'https://demo.docusign.net/restapi/v2/'
params = {'api_password':'true'}
headers = {'X-DocuSign-Authentication':json.dumps({"Username":username,"Password":password,"IntegratorKey": clientid}),
'Content-Type':'application/json'}
auth_req = requests.get(base_url+'login_information', params, headers=headers)
Auth request yields 200, just like Postman
But then I try another request to /templates/
Here it is in Postman:
and headers same as Auth request above
I tried many variations of the following:
params = {'accountId':'7787022'}
get_templates = requests.get(base_url+'templates', params, headers=headers)
No matter what I try, I get a 404 instead of a 200 like with postman.
Any idea what I'm doing wrong?

As per your comment, it looks like you don't have a fully built BaseUrl. The full body of a base URL will include the server, the rest API version and your account number. Aside from the Login Information and other authentication calls, all standard* REST API calls will start with https://{{server}}.docusign.net/restapi/v2/accounts/{{accountId}}/
A call to GET templates would be made to https://{{server}}.docusign.net/restapi/v2/accounts/{{accountId}}/templates.
*Organization API calls are coming soon and will likely use a different URL.

The following did not fix, but I thought it would fix, and still think it is importnat information:
In Postman auth call under 'Tests' there is the followign code
var jsonData = JSON.parse(responseBody);
postman.setEnvironmentVariable("accountId", jsonData.loginAccounts[0].accountId);
var jsonData = JSON.parse(responseBody);
postman.setEnvironmentVariable("baseUrl", jsonData.loginAccounts[0].baseUrl);
var jsonData = JSON.parse(responseBody);
postman.setEnvironmentVariable("password", jsonData.apiPassword);
even though this is 'Tests' it is useful for and often used to set variables, (some ppl at my old company used to do this).
In my python code, I need to take the response body from auth request:
{
"loginAccounts": [
{
"name": "Aiden McHugh",
"accountId": "7787022",
"baseUrl": "https://demo.docusign.net/restapi/v2/accounts/7787022",
"isDefault": "true",
"userName": "Aiden McHugh",
"userId": "e87........6a4eb",
"email": "aide....il.com",
"siteDescription": ""
}
],
"apiPassword": "HheDl......3MQ="
}
and use apiPassword variable to reset password in my header

You could also check out the python code example. It includes authentication and many examples.

Related

Always get “Cannot parse non Measurement Protocol hits”

I have a little Python program that other people use and I would like to offer opt-in telemetry such that can get an idea of the usage patterns. Google Analytics 4 with the Measurement Protocol seems to be the thing that I want to use. I have created a new property and a new data stream.
I have tried to validate the request and set it to www.google-analytics.com/debug/mp/collect?measurement_id=G-LQDLGRLGZS&api_secret=JXGZ_CyvTt29ucNi9y0DkA via post and send this JSON payload:
{
"app_instance_id": "MyAppId",
"client_id": "TestClient.xx",
"events": [
{
"name": "login",
"params": {}
}
]
}
The response that I get is this:
{
"validationMessages": [
{
"description": "Cannot parse non Measurement Protocol hits.",
"validationCode": "INTERNAL_ERROR"
}
]
}
I seem to be doing exactly what they do in the documentation or tutorials. I must be doing something wrong, but I don't know, what is missing. What do I have to do in order to successfully validate the request?
Try to remove /debug part in the URL. In the example you followed it is not present so it is not quite exactly the same.
we just came across the same issue and the solution for us was to put https:// in front of the URL. Hope this helps.

Request reuse in Postman

Our team wants to automate our REST API testing. Right now, we have a collection of Postman requests and make them jump through hoops manually.
We could create a collection/folder for each testing scenario, but that would mean a ton of duplication. Our API is still under heavy development and I really don't want to fix the same thing at twenty places after it changes.
I would like to have each endpoint request only once in a collection and some kind of independent logic that can execute them in an arbitrary order. I know Postman doesn't support request reuse in any clean way, so I am looking for at least a hacky way how to do it.
Create a file to load into the Postman Collection Runner, with the following structure:
[{
"testSequence": ["First request name", "Second request name", "..." ],
"anyOtherData": "Whatever the request needs",
"evenMoreData": "Whatever the request needs",
"...": "..."
},{
"testSequence": ["Login", "Check newsfeed", "Send a picture", "Logout" ],
"username": "Example",
"password": "correcthorsebatterystaple",
},{
"...": "keep the structure for any other test scenario or request sequence"
}]
Put all your test sequences in that file, then make Postman check the list after each request and decide what to execute next. This can be done e. g. in a "tests block" of the whole collection:
// Use the mechanism only if there is a test scenario file
// This IF prevents the block from firing when running single requests in Postman
if (pm.iterationData.get("testSequence")) {
// Is there another request in the scenario?
var sequence = pm.globals.get("testSequence");
if ((sequence instanceof Array) && (sequence.length > 0)) {
// If so, set it as the next one
var nextRequest = sequence.shift();
pm.globals.set("testSequence", sequence);
postman.setNextRequest(nextRequest);
} else {
// Otherwise, this was the last one. Finish the execution.
postman.setNextRequest(null);
}
}
If your requests need to use different data during different runs, you can define the data in the input file and use them as variables in the request.

AWS API Gateway - change to 404 if query returns nothing

I have a Dynamodb table with a few fields - my_id is the PrimaryKey. In the API gateway I set up a response with a method that takes in a parameter {my_id}.
Then I have an Integration Request mapping template that takes the passed in parameter and queries the table to return all the fields that match.
Then I have an Integration response mapping template that cleans up the returned items the way I want.
This all works perfect.
The thing I can't figure out how to do is if the parameter that is passed in doesn't match anything in the table, how do I get it to change from a 200 status into a 404?
From what I can tell when the passed in parameter doesn't match anything it doesn't cause an error, it just doesn't return anything.
It seems like I need to change the mapping template on the Integration response to first check if the params are empty and then somehow tell it to change the response status.
I can find info about this type of thing with people using Lambda, but I am not using Lambda - just the Dynamodb table and the API Gateway.
You can use Mapping Template to convert the response that you get from DDB and overrride the response code. You can get more details in the link https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-override-request-response-parameters.html
If you are using cloud formation, you can do this by using below snippet
IntegrationResponses:
- StatusCode: "200"
ResponseTemplates:
application/json: |
{
"payload" : {
}
},
}
IntegrationResponses:
- StatusCode: "200"
ResponseTemplates:
application/json: |
#set($inputRoot = $input.path('$'))
#if($inputRoot.toString().contains("Item"))
$input.json("$")
#set($context.responseOverride.status = 200)
#else
#set($context.responseOverride.status = 404)
#end
Api gateway currently supports mapping the status code using the status code of the integration response (Here dynamodb response code). The only workaround is to use a lambda function which outputs different error messages that can be mapped using a error regex http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-method-settings-execution-console.html.

Override the method of packing HTTP form-urlencoded parameters in Meteor HTTP call

I'm using Meteor to consume a remote API. One of the endpoints of this API requires an (ordered) array of credentials, so the data would look like
{
"country": "de",
"credentials": ["admin", "password"],
"whatever": "whatever"
}
When I provide this plain-object as the value to param property of HTTP.post like this
HTTP.post('https://api.whatever.org/whatever', {
headers: {
"Authorization": "Basic ".concat(...)
},
params: {
"country": "de",
"credentials": ["admin", "password"],
"whatever": "whatever"
}
});
then the parameters are packed this way:
country=de
credentials=admin,password
whatever=whatever
but they should be packed this way:
country=de
credentials=admin
credentials=password
whatever=whatever
I tried using a Content-Type header but it didn't help.
I tried using content and data instead of params with different outcomes and then ended concatenating all the values into a query string an putting it into content property. But this isn't really a nice piece of code and surely not one that is easy to maintain.
I've read docs but haven't found anything that would help.
Where should I look for the information regarding this topic? Is there a better way to override the way HTTP.post (or, in general, HTTP.call) computes the body of the query to send?
Where should I look for the information regarding this topic?
In the source code.
I know nothing about Meteor, but I’m looking into its source code and I see no public hook which could help you. Of course, you can replace URL._encodeParams with your own function, but that is less maintainable than submitting the encoded params as raw data.

Redirect service requests to another server

I've created a filter so that I can intercept all controller actions and forward the request to a different server.
I need to temporarily redirect based on user-agent.
So I have the following in http://www.mysite1.com
class DealsFilters {
def filters = {
all(controller: '*', action: '*') {
before = {
if (someConditionHere)
{
redirect(url:"http://www.mysite2/")
return
}
}
}
}
What I am wondering is will the request and all it params be correctly passed to mysite2?
i.e. mysite1 acts as a service and receives requests to get user data, update deals, add new users, etc...
mysite2 is a new version of mysite1 (mysite1 will be decommisioned after mysite2 has been tested).
Is it as simple as a redirect?
Thanks
I'm using grails 1.3.7 as pointed out to lucke84 (I should have stated this in original question).
Found following link gave me most of the answer:
Best practice for redirecting from one web domain to another in Grails?
redirect(url:"http://localhost:8080${request.forwardURI}?${request.queryString}",params:params)
The documentation says that if you perform a redirect with the url parameter, your url should contain all the information needed to send the new request.
I guess you should recreate your url, more or less like this:
redirect(base: 'http://www.mysite2/', controller: params.controller, action: params.action, params: params)
Not tested, but it should work for most of the cases. Let me know :)

Resources