How is it possible to get the response status code of a request using lua-http ?
If that is not possible with it what module/library should i use ?
From the docs :
local http_request = require "http.request"
local headers, stream = assert(http_request.new_from_uri("http://example.com"):go())
print(headers:get ":status")
Related
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.
I am trying to call an API from an ejabberd (17.04) module from erlang code by making a Post request. The API is called successfully, however, the data in the request body gets truncated.
Following is my erlang code to make the POST request.
Data = string:join(["to=", binary_to_list(To), "&from=", binary_to_list(From), "&body=", Body], ""),
Request = {binary_to_list(PostUrl), [{"Authorization", binary_to_list(Token)}], "application/x-www-form-urlencoded", Data},
httpc:request(post, Request,[],[]),
I pass the data with the application/x-www-form-urlencoded content type.
There is no error while compiling or running the code, however, if there are some special characters in the Body variable, then the data is not sent to the API.
For example, when the Body variable contains the following value:
{xmlel,<<\"encrypted\">>,\n [{<<\"xmlns\">>,<<\"eu.siacs.conversations.axolotl\">>}],\n [{xmlel,<<\"header\">>,\n [{<<\"sid\">>,<<\"344245169\">>}],\n [{xmlel,<<\"key\">>,\n [{<<\"rid\">>,<<\"684863397\">>}],\n [{xmlcdata,<<\"MwohBTL6tSWIPtugiO0qo0RNrWFC3ypIL5JpwMN1qF8jAoQ1EAAYASIwKnIw/zo43lF4At93Q7PMePlDVGF47Hf6xIvSjm+bpcESskndwFudirxigLSqc6J/P0IEL3sErsE=\">>}]},\n {xmlel,<<\"iv\">>,[],\n [{xmlcdata,<<\"JR7NorYN19NBDwyY3eqXcg==\">>}]}]},\n {xmlel,<<\"payload\">>,[],\n [{xmlcdata,<<\"Da1s4qj6MiPgE1CP9S1ou5Cod//QAfmguc5GUGEk7IfTUJ8VU9CvL6iOfI3qK6Rg7uVNWACTWKBqCWGQstBkEEkwLDZHzJBqoJ6CoE4vxyfEdowWLqt84fNhGcsgvVxqmEDIln0NA2gDRd/vhGi0yIh2JdMQ55+6Ten1+fVb+kwYlKxe94XyMV84Yiz+bfPkAach22oYCZyMx695JSBnaUb8MRLISlnkcpLv/UJtmEMlGER/t5Ac5BK00sbkbVo4zOMbfOgA++prt4mbpceTGyJpmkRa/75xoqDPbYxG3sYujq52RguW1YO649M=\">>}]}]}
The Data variable contains the following value:
"to=186&from=274&body={xmlel,<<\"encrypted\">>,\n [{<<\"xmlns\">>,<<\"eu.siacs.conversations.axolotl\">>}],\n [{xmlel,<<\"header\">>,\n [{<<\"sid\">>,<<\"344245169\">>}],\n [{xmlel,<<\"key\">>,\n [{<<\"rid\">>,<<\"684863397\">>}],\n [{xmlcdata,<<\"MwohBTL6tSWIPtugiO0qo0RNrWFC3ypIL5JpwMN1qF8jAoQ1EAAYASIwKnIw/zo43lF4At93Q7PMePlDVGF47Hf6xIvSjm+bpcESskndwFudirxigLSqc6J/P0IEL3sErsE=\">>}]},\n {xmlel,<<\"iv\">>,[],\n [{xmlcdata,<<\"JR7NorYN19NBDwyY3eqXcg==\">>}]}]},\n {xmlel,<<\"payload\">>,[],\n [{xmlcdata,<<\"Da1s4qj6MiPgE1CP9S1ou5Cod//QAfmguc5GUGEk7IfTUJ8VU9CvL6iOfI3qK6Rg7uVNWACTWKBqCWGQstBkEEkwLDZHzJBqoJ6CoE4vxyfEdowWLqt84fNhGcsgvVxqmEDIln0NA2gDRd/vhGi0yIh2JdMQ55+6Ten1+fVb+kwYlKxe94XyMV84Yiz+bfPkAach22oYCZyMx695JSBnaUb8MRLISlnkcpLv/UJtmEMlGER/t5Ac5BK00sbkbVo4zOMbfOgA++prt4mbpceTGyJpmkRa/75xoqDPbYxG3sYujq52RguW1YO649M=\">>}]}]}"
However, when I try to fetch this value in my API, only the following data is available:
{xmlel,<<\"encrypted\">>,\n [{<<\"xmlns\">>,<<\"eu.siacs.conversations.axolotl\">>}],\n [{xmlel,<<\"header\">>,\n [{<<\"sid\">>,<<\"344245169\">>}],\n [{xmlel,<<\"key\">>,\n [{<<\"rid\">>,<<\"684863397\">>}],\n [{xmlcdata,<<\"MwohBTL6tSWIPtugiO0qo0RNrWFC3ypIL5JpwMN1qF8jAoQ1EAAYASIwKnIw/zo43lF4At93Q7PMePlDVGF47Hf6xIvSjm+bpcESskndwFudirxigLSqc6J/P0IEL3sErsE
I am new to erlang and not sure of what seems to be the problem. Any help is appreciated.
I'm creating a web scraping bot in PhantomJs, I'm using onResourceReceived to sniff the the requests of the site and retrieve them using this simple code:
page.onResourceReceived = function(response)
{
if (response.url.match("XXXXXXX"))
{
console.log(response.url);
}
};
My problem is that response.url automatically update the data to a URL-decoded version of this. I need to check some parameters but instead of receiving something like this :
xxx.com?...&events=event20%2Cevent4%%2Cevent89%3D7%2Cevent50%2Cevent51%2Cevent52%2Cevent53%2Cevent54%2Cevent55%2Cevent56&...
I get this
xxx.com?... &events=event20%2Cevent4%2Cevent89%3D7&....
It looks like when %3D is reached it cuts the value and continues to the next property.
Is there a way to access the raw version of this data?
Thanks a lot for the help.
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.
I am attempting to return an object from a AWS Lambda function instead of a simple string.
// ...
context.fail({
"email": "Email address is too short",
"firstname": "First name is too short"
});
// ...
I have already used the errorMessage for mapping error responses to status codes and that has been great:
// ...
context.fail('That "username" has already been taken.');
// ...
Am I simply trying to do something that the AWS API Gateway does not afford?
I have also already found this article which helped: Is there a way to change the http status codes returned by Amazon API Gateway?.
Update
Since time of writing, lambda has updated the invocation signature and now passes event, context, callback.
Instead of calling context.done(err, res) you should use callback(err, res). Note that what was true for context.done still applies to the callback pattern.
Should also add that with API Gateways proxy and integration implementation this entire thread is pretty much obsolete.
I recommend reading this article if you are integrating API Gateway with Lambda: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html
Original response below
First things first, let's clear a few things up.
context.done() vs. context.fail()/context.success
context.done(error, result); is nothing but a wrapper around context.fail(error); and context.success(response);
The Lambda documentation clearly states that result is ignored if error is non null:
If the Lambda function was invoked using the RequestResponse (synchronous) invocation type, the method returns response body as follows:
If the error is null, set the response body to the string representation of result. This is similar to the context.succeed().
If the error is not null, set the response body to error.
If the function is called with a single argument of type error, the error value will be populated in the response body.
http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html
What this means is that it won't matter whether you use a combination of fail/success or done, the behaviour is exactly the same.
API Gateway and Response Code Mapping
I have tested every thinkable combination of response handling from Lambda in combination with Response code mapping in API Gateway.
The conclusion of these tests are that the "Lambda Error RegExp" is only executed against a Lambda error, i.e: you have to call context.done(error);or context.fail(error); for the RegExp to actually trigger.
Now, this presents a problem as, has already been noted, Lambda takes your error and sticks it in an object and calls toString() on whatever you supplied:
{ errorMessage: yourError.toString() }
If you supplied an error object you'll get this:
{ errorMessage: "[object Object]" }
Not very helpful at all.
The only workaround I have found thus far is to call
context.fail(JSON.stringify(error));
and then in my client do:
var errorObject = JSON.parse(error.errorMessage);
It's not very elegant but it works.
As part of my error I have a property called "code". It could look something like this:
{
code: "BadRequest",
message: "Invalid argument: parameter name"
}
When I stringify this object I get:
"{\"code\":\"BadRequest\",\"message\":\"Invalid argument: parameter name\"}"
Lambda will stick this string in the errorMessage property of the response and I can now safely grep for .*"BadRequest".* in the API Gateway response mapping.
It's very much a hack that works around two somewhat strange quirks of Lambda and API Gateway:
Why does Lambda insist on wrapping the error instead of just giving
it back as is?
Why doesn't API Gateway allow us to grep in the
Lambda result, only the error?
I am on my way to open a support case with Amazon regarding these two rather odd behaviours.
You don't have to use context.fail, use success but send different statusCode and an errorMessage, here is an example of how i format my output:
try {
// Call the callable function with the defined array parameters
// All the function called here will be catched if they throw exceptions
result.data = callable_function.apply(this, params);
result.statusCode = 200;
result.operation = operation;
result.errorMessage = ""
} catch (e) {
result.data = [];
result.statusCode = 500;
result.errorMessage = e.toString();
result.method = method;
result.resource = resource;
}
// If everything went smooth, send back the result
// If context succeed is not called AWS Lambda will fire the function
// again because it is not successfully exited
context.succeed(result);
Use the consumer logic to handle different errors case logic, don't forget that you pay for the time your function is running...
You should replace the use of your context.fail with context.done and use context.fail only for very serious Lambda function failures since it doesn't allow more than one output parameter. Integration Response is able to match mapping template by performing regex on the first parameter passed to context.done this also maps HTTP status code to the response. You can't pass this response status code directly from Lambda since it's the role of API Gateway Integration Response to abstract the HTTP protocol.
See the following:
context.done('Not Found:', <some object you can use in the model>);
and the Integration Response panel this setting:
You can replicate similar approach for any kind of error. You should also create and map the error model to your response.
For those who tried everything put on this question and couldn't make this work (like me), check the thedevkit comment on this post (saved my day):
https://forums.aws.amazon.com/thread.jspa?threadID=192918
Reproducing it entirely below:
I've had issues with this myself, and I believe that the newline
characters are the culprit.
foo.* will match occurrences of "foo" followed by any characters
EXCEPT newline. Typically this is solved by adding the '/s' flag, i.e.
"foo.*/s", but the Lambda error regex doesn't seem to respect this.
As an alternative you can use something like: foo(.|\n)*