How to get the original request URI in api gateway? - aws-api-gateway

From a lambda implemented api gateway resource, how to get the original request URI. Or even just the original path?
Lacking a better way I'm currently using the following three variables that I pass down to the lambda using the default request template:
$context.resourcePath contains the path with variable names ex: "/blah/{var}"
$input.params().path contains the variable names and values ex: {"var":"something"}
$context.stage contains the stage ex: "prod"
That's quite a hassle since it requires path variable substitution to get the original call path:
/prod/blah/something
How can I get the original URL or URI?

I'm not finding anything in the documentation that lets you get the original call URI. I can add a feature request to consider adding it. Can you describe your use case. Why do you want to get the original URI?

I found a 'workaround'.
If you create a custom domain name with a BasePathMapping, and call the API using this custom domain, the original request uri actually has your stage name in there:
Call directly to the API gateway:
curl -v 'https://some-id.execute-api.eu-central-1.amazonaws.com/v1/ping'
...
request.url: https://some-id.execute-api.eu-central-1.amazonaws.com/ping'
But if we call it through te custom domain (which is actually a cloudfront distribution):
curl -v -X GET https://api.our.domain.name.com/v1/ping
...
request.url: https://api.our.domain.name.com/v1/ping
In my opinion, the direct call gives you an INCORRECT request url in the lambda function, as the url very clearly has the stage name in there.
This breaks the routing middleware of at least flask.
Any update on the feature request?

Related

Syntax to use parameters in Body section of HTTP Request Sampler in JMeter, using Rest API POST request with body and input from CSV file

I'm using JMeter to test a microservice and I need to use a parameter dynamically with a different value in each request. Also, the parameter is a part of a query that contains other constant values as well.
I defined user variables in the JMeter user.properties file (in JMeter bin folder):
JMeter -- bin/user.properties
# Parameters to use in JMeter
ES_HOST=127.0.0.1
ES_PORT=9200
ES_INDEX=segments
ES_TYPE=_doc
THREAD=5
CSVDATA_ROOT=C:/devtools/apache-jmeter-5.2.1/csv_data
Of course, I have User-Defined Variables:
And how my Test Plan is defined in JMeter
As you can see in the following screenshot of View Result Tree the parameter agentName I defined and shown in the HTTP Request (above) is working.
I want to define it in the body of the HTTP Request, to replace the hardcoded "John Doe" with a parameters that have a different value in each request.
"query":"SearchStartTime=2020-01-01 00:00:00.000TO2020-01-31 23:59:59.999&AgentName=John Doe"}
How can I do that?
I need a way to add a parameter to an existing string
I've already tried Using Apache JMeter to Test Elasticsearch (or any REST API) and In Jmeter, What would be syntax of parameters in Body Data section of HTTP Request Sampler, for Rest APIs and input should be generated dynamically also doesn't solve my problem.
Use same syntax as HTTP request - ${agentname} for getting variable value:
"query":"SearchStartTime=2020-01-01 00:00:00.000TO2020-01-31 23:59:59.999&AgentName=${agentname}"

Jmeter parameter without name in REST method

Hello i have GET method that URL example is:
http://localhost:8050/programs/b3cb6a0f-5d29-4744-a7e8-5fa0099dab18
Where the last String is just programId that I set as parameter in HTTP Request.
JMeter is kinda confused and the respond in raw request is:
GET http://localhost:8050/
GET data:
b3cb6a0f-5d29-4744-a7e8-5fa0099dab18
but there's just 404 in response data.
I can just delete parameter and write /programs/b3cb6a0f-5d29-4744-a7e8-5fa0099dab18 in path instead of /programs/ and everything works perfectly fine. IMO it's awful way. I'd prefer do it with parameter.
Write in path the parameter as /programs/${programId}.
This is part of the path and not parameter, parameters in GET request are different than POST see http methods
path/mypage?param1=value1&param2=value2

how call REST service with path variable in webmethod?

I'm using WM9.8. I want to know how to call a GET REST service with path variable like:
http://localhost:8080/client/1 in webmethod.
I can call POST rest service using pub.client.http. But it dosen't work to GET.
Use String varible called "method" to set type of Http request method.
Just put the path variable in the URL and made a substitution to the path variable
e.g: http://localhost:8080/client/%yourPathVariableHere%
Holy cow this is an old question but I just tumbled across it and I thought I might helps somebody else who does.
URLs in webmethods are fixed to a single value, like /client unless you enable watt.server.url.alias.partialMatching=true
After that, you can simply alias a service to /client and all subURLs like /client/1 are sent to that service. You still have to parse them to get the ID out.
Be careful, though, because ALL sub URLs are sent to the service. So after enabling this flag I get /client, /client/1, /client/1/name all going to the same service. You can see how this can quickly become REST-unfriendly.

Is it possible to use wildcards or catch-all paths in AWS API Gateway

I am trying to redirect all traffic for one domain to another. Rather than running a server specifically for this job I was trying to use AWS API Gateway with lambda to perform the redirect.
I have this working ok for the root path "/" but any requests for sub-paths e.g. /a are not handled. Is there a way to define a "catch all" resource or wildcard path handler?
As of last week, API Gateway now supports what they call “Catch-all Path Variables”.
Full details and a walk-through here: API Gateway Update – New Features Simplify API Development
You can create a resource with path like /{thepath+}. Plus sign is important.
Then in your lambda function you can access the value with both
event.path - always contains the full path
or event.pathParameters.thepath - contains the part defined by you. Other possible use case: define resource like /images/{imagepath+} to only match pathes with certain prefix. The variable will contain only the subpath.
You can debug all the values passed to your function with: JSON.stringify(event)
Full documentation
Update: As of last week, API Gateway now supports what they call “Catch-all Path Variables”. See API Gateway Update – New Features Simplify API Development.
You will need to create a resource for each level unfortunately. The reason for this is API Gateway allows you to access those params via an object.
For example: method.request.path.XXXX
So if you did just /{param} you could access that with: method.request.path.param but if you had a nested path (params with slashes), it wouldn't work. You'd also get a 404 for the entire request.
If method.request.path.param was an array instead...then it could get params by position when not named. For example method.request.path.param[] ...Named params could even be handled under there, but accessing them wouldn't really be easy. It would require using something some sort of JSON path mapping (think like what you can do with their mapping templates). Sadly this is not how it's handled in API Gateway.
I think it's ok though because this might make configuring API Gateway even more complex. However, it does also limit API Gateway and to handle this situation you will ultimately end up with a more confusing configuration anyway.
So, you can go the long way here. Create the same method for multiple resources and do something like: /{1}/{2}/{3}/{4}/{5}/{6}/{7} and so on. Then you can handle each path parameter level if need be.
IF the number of parameters is always the same, then you're a bit luckier and only need to set up a bunch of resources, but one method at the end.
source: https://forums.aws.amazon.com/thread.jspa?messageID=689700&#689700
Related to HTTPAPI that AWS introduced recently, $default is used a wildcard for catching all routes that don't match a defined pattern.
For more details, refer to: aws blogs
You can create a resource with path variable /{param}, and you can treat this as wildcard path handler.
Thanks,
- Ka Hou

a restful api only uses clean urls - no url variables or post variables

A restful api has to use either get, post, put or delete request methods. The behavaiour and data submitted is entirely determined by the uri string. No query paramters or post variables.
Is this true ?
Valid : http://example.com/foo/84
Not valid : http://example.com/foo/?value=84
Valid :
$.ajax({
  type: 'POST',
  url: "http://example.com/foo/84",
  success: success,
  dataType: dataType
});
Not valid :
$.ajax({
type: 'POST',
url: "http://example.com/foo/",
data: 84,
success: success,
dataType: dataType
});
edit
Two answers so far, and the contradict each other.
Here goes a third answer that contradicts the other two.
RESTful URI is almost an oxymoron. The semantics of the URI is irrelevant to REST, the only thing that matters to REST is that one URI identifies only one resource. Other than that, an URI is an atomic identifier, and its semantics are irrelevant.
For REST it doesn't matter if the URI pointing to a user resource for Joe Doe is:
http://example.com/users/joedoe
Or:
http://example.com/users?username=joedoe
Or:
http://example.com/jif892mfd02-18f2
Or even:
ftp://example.com/users/joedoe.json
It doesn't matter! URIs don't need to have any meaning in a RESTful application. People spend so much time designing meaningful URIs for their REST application, while they should be concerned with their media types. When you click a link on a webpage, you don't care about the semantics of the URI, you only care about the label. The same thing happens with a client using a REST API. The documentation of your media type should describe what links are available and what they do, through labels, and you simply follow them.
If you're concerned with the semantics of the URI, this is a sign that your clients are building URIs from some template in documentation, and you're not using HATEOAS, which means you're not doing REST at all.
POST variables are definitely OK otherwise how would you submit a new resource or update it?
GET parameters are fine to specify how the resource should be rendered. So indeed http://example.com/foo/?value=84 is not right - the URL doesn't represent a resource.
However, http://example.com/user/84?fields=first_name,last_name would be ok. In that case, you would use the additional query parameters to specify that you only want the first name and last name for that resource.
Saying that http://example.com/foo/?value=84 is not valid is not entireley true. What i mean is that as long that it is a valid URL it will work and you'll be able to get the parameters via get or post.
On the other hand, REST is an architecture and one of its demands is a clean URL (one that does not include params with a '?') so such a url is not considered a REST like URL.
So if you intend to build a REST based application, you should only use clean urls.
EDIT:
I see from the comments below you have a problem understanding what is REST so i'll try to give a simple example:
In order to get data you will probably use http://example.com/foo/84 as a get request and the rest FW knows to get resource foo with id 84.
In order to post data about foo, you might call: http://example.com/foo/84 as a POST request and now the Rest FW know that since its a post request it will call the method responsible for handling post and not the one for handling get
To delete, you call the same URL with DELETE action and i think you know the rest.
So, although you have the same URL it really matters if its a GET/POST/PUT/DELETE request.