Is there any AMI function to get UserAgent variable for any SIP channel?
I tried "Getvar" but got empty value.
ps. I used asterisk 13.18.5
Action: Getvar
Channel: SIP/2000-0000003c
Variable: SIPUSERAGENT
Response: Success
Variable: SIPUSERAGENT
Value:
SIPUserAgent is FUNCTION.
And yes, it is not same as SIPUSERAGENT
In modern versions you should use
SIP_HEADER(UserAgent)
Related
How do I find out if a variable has been defined in my Robot Framework script? I am doing API testing, not UI testing. I have a complex set up and tear-down sequence and, since I am interacting with multiple computers through the script, it is important to know the current state if a fatal error has occurred. I could track what I have done with some complex set of meta variables or a variable tracking list, but I would prefer to query if a particular variable has been defined and if so take the appropriate tear-down steps.
A simplified version is something like:
*** Test Cases ***
Check monitor
${monitored}= Connect to Monitor ${Monitor IP Address} ${User name} ${password}
${peer connected}= Connect to Monitor ${Peer IP Address} ${User name} ${password}
Get Information from Monitor ${IP Address}
Send Info to Peer ${buffer1}
Report back to Monitor ${Monitor IP Address}
We are assuming that the tear-down closes the connections. I want to close any connections that are open, but if I failed to open the peer connection I will close the monitor connection and fail on closing the monitor connection.
I am trying to determine if ${peer connected} is defined. Can I look into Robot Framework's variable storage to see if it is there (in that dictionary?)?
You can call Get Variables to get a dictionary of all variables, then check whether the variable you're interested in is in the dictionary.
*** Test cases ***
Example
${foo}= set variable hello, world
${variables}= Get variables
Should be true "\${foo}" in $variables
Should not be true "\${bar}" in $variables
There a pretty straightforward approach - the built-in keyword Get Variable Value returns python's None (by default) if there is no such variable defined:
${the var}= Get Variable Value ${peer connected}
${is set}= Set Variable If """${the var}""" != 'None' ${True} ${False}
I am fine with this approach. In case the variable is not defined, the test case does not fail....
${variables} Get variables
${status} Run Keyword And Return Status Evaluate $new_table in $variables
${new_table} Set variable if ${status}==${FALSE} new_tbl ${new_table}
Also possible is:
${variables} Get Variables
IF "\${dataPluginVersion}" in "${variables}"
No Operation
ELSE
${dataPluginVersion} Set Variable 0
END
Or:
${variables} Get Variables
IF not "\${dataPluginVersion}" in "${variables}"
${dataPluginVersion} Set Variable 0
END
A shorter way:
OEM-T01-99-Test-variables
[Tags] TEST
Variable Should Not Exist \${TESTDEVICE_SSH_CONNECTION}
Variable Should Exist \${TEST_NAME}
This method is more readable and less verbose than using "Get Variables" keyword, IMHO
Reference: Robotframework built-in keywords
I am using WsReceive() function of the ATEasy framework and wanted to ask what is the meaning of the values "aioDefault
and aioDisableWsReceiveEarlyReturn" of "enMode" parameter?
I found this in the ATEASY documentation:
If enMode, input receive mode includes aioDisableWsReceiveEarlyReturn,
it prevents WsReceive from an "early return" when there is a momentary
interruption in the data being received.
And this from the online help of ateasy (By a tip of an expert from the ateasy forum) :
If sEos parameter is an empty string and aioDisableWsReceiveEarlyReturn mode flag is not used (default case), the function will return immediately if characters are found in the input buffer, and the timeout will be ignored. Using the aioDisableWsReceiveEarlyReturn flag will ensure that the function will return only if the timeout is reached or all lBytes characters were received.
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)*
I am trying to get the query parameters in the url.
There doesn't seem to be an easy way to do this...
which leaves me with the feeling that I must have missed a something in the doc.
Just call
Router.current().params //params is the dict you wanted
in Iron Router 7.1+
Interestingly three answers and no one offered the complete answer.
Iron-Router 1.0.x
From within a route, use:
// URL: http://example.com/page/?myquerykey=true
this.params.query // returns the full query object
this.params.query.myquerykey // returns a particular query value
Similarly, outside of the route (but still inside the client code), and inside your template, use:
// URL: http://example.com/page/?myquerykey=true
Router.current().params.query
Router.current().params.query.myquerykey
Query parameters, not to be confused with parameters passed via the URL.
iron router >= 1.0
A route's query parameters are available as properties of this.params.query.
If your URL looked like:
/posts/5?sort_by=created_at
then this.params.query.sort_by would equal 'created_at'.
iron router < 1.0
A route's query parameters are available as properties of this.params.
If your URL looked like:
/posts/5?sort_by=created_at
then this.params.sort_by would equal 'created_at'.
In Iron Router 1.0.0, you need to use
this.params.query.YOUR_PARAMETER_NAME
to get it
For example, if you route is /xxx/?a=b
this.params.query.a
outputs 'b'
try tihs:
Router.current().params.parametername;
and in router.js file routing must be:
route(routername/:parametername)
Ensure that if you are using Router.go that your first parameter is a template name, and not a path. query parameters are not passed if you specify a path.
Encoded URI undefined Solution:
The better way to get the query parameters object is:
this.request.query.MyParam
Using the suggested option of:
this.params.query.MyParam
Is ok as long as you are not working with encodedURI parameters, when using this option with encodedURI parameter, the parameter will be equal to undefined.
Example below:
{ // console.log(this.params.query)
product: 'Chair',
ip: '172.0.1.183',
message: 'My Little Chair',
request: '100% Discount',
severity: '4',
api_key: 'XXXXX'
}
{ // console.log(this.params.query)
product: 'Chair',
ip: '172.0.1.183',
message: 'My Little Chair',
request: 'undefined', // NOTICE THIS CHANGED TO UNDEFINED!
severity: '4',
api_key: 'XXXXX'
}
Original Query String:
?product=Chair&ip=172.0.1.183&message=My Little Chair&request=100%25%20Discount&severity=4&api_key=XXXXX
You can pass queries like this depending on where you accessing the router:
In the template
{{pathFor 'routeName' query='queryName=queryValue'}}
In the helper
Router.go ('routeName',{},{query: 'queryName=queryValue'}
Note: the empty object between the routeName and the query is if you want to specify any parameters (refer to the full docs to see the difference).
If you would like to pass multiple queries do it like this:
query: 'queryName1=queryValue&queryName2=queryValue'
Don't use spaces and remember to use the & sign.