async Lambda invocation from Api Gatway with parameters - aws-lambda

I have an Api Gateway GET method called /tasks/{tasktype}
It's pointed to a Lambda function with the X-Amz-Invocation-Type set to 'Event'
Then in my Lambda I have this
public void FunctionHandler(Object input, ILambdaContext context)
{
LambdaLogger.Log($"GOT: {input.ToString()}");
}
This all works fine, except input is null.
Is there any way I can pass through and access the value of {tasktype} from the Api Gateway?
Thanks

You need to pass them in using either a mapping template or check the box for "Use Lambda Proxy integration".
Mapping Template reference:
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
Proxy Integration reference:
https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html

Related

Pass User-defined parameter in Elsa WorkFlow

I want to pass project_Cost (input parameter) in this Elsa WorkFlow Builder APi
public void Build(IWorkflowBuilder builder , int project_Cost)
{
}
Currently, it's giving an error because Build method doesn't have a second user-defined input parameter
how to pass this parameter, is there any other method there in Elsa WokFlow to pass custom user-defined input parameter
?
So, if I invoke https://localhost:44302/ProjectStatus?project_Cost=15000
then Elsa WorkFlow activates and passes 15000 as an input parameter value
The builder API is designed to define workflow blueprints, and it doesn't make sense to pass parameters to it.
For your use case you can take advantage of Http endpoints activity and there's a sample on the repo that I guess is close to what you need.
Something like the following:
public void Build(IWorkflowBuilder builder)
{
builder
// Configure a Receive HTTP Request trigger that executes on incoming HTTP GET requests.
.HttpEndpoint(activity => activity.WithPath("/ProjectStatus").WithMethod(HttpMethods.Get))
// Store the parameter as a workflow variable
.SetVariable(context => ((HttpRequestModel)(context.Input))?.QueryString["project_Cost"]))
// Then whatever you need to do with the parameter
}

Invoking an AWS Lambda function from another Lambda with multiple method of a service without any conditional parameter

I am familiar with invoking lambda from another lambda and also to pass param to handler function based on which it calls different methods from a service(Same as stated here AWS Lambda - Invoke a method of another lambda function), But when there is a case to expose all the methods of a service its quite tedious to add multiple condition in the handler function.
So my question is Is there any dynamic way we can expose all the methods of the service using single lambda handler function, or may be any other efficient way. My main motive is to expose whole method in a service using lambda handler so that I don't have to add different conditions and another lambda can invoke it method name without any conditional parameter.
Sample code here
export const handler = async function(params: params,
context: Context,
callback: Callback) {
if(params.type === 'type1'){
const results = await testService.testmethod1(params.value);
context.succeed(results);
}
else if(params.type === 'type2'){
const results = await testService.testmethod2(params.value);
context.succeed(results);
} and so on...
};
So Is there any way we can expose all methods of testService(above we have exposed to methods testmethod1 and testmethode, there can be other methods as well) without all these conditional statements?

Spring Cloud Function with Function Routing in AWS Lambda using API Gateway

I have tried to deploy a Spring Cloud Function with multiple functions in AWS Lambda.
For HTTP access I have created an HTTP API Gateway (not a REST API). I wanted to use function routing as described here: https://cloud.spring.io/spring-cloud-static/spring-cloud-function/3.0.1.RELEASE/reference/html/spring-cloud-function.html#_function_routing.
With the following configuration, the RoutingFunction shoud deleagte the call to the correct function based on the function HTTP-Header:
spring.cloud.function.routing-expression=headers.function
The Lambda Handler class is:
org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler
and the configured function name (FUNCTION_NAME) is: functionRouter.
When I send a Request to the API-Gateway, the FunctionRouter gets a FluxJust object instead of a Message object, because the RequestHandler seems to be a Publisher.
So I get the following exception:
EL1008E: Property or field 'headers' cannot be found on object of type
'reactor.core.publisher.FluxJust' - maybe not public or not valid?:
org.springframework.expression.spel.SpelEvaluationException
org.springframework.expression.spel.SpelEvaluationException:
EL1008E: Property or field 'headers' cannot be found on object of type
'reactor.core.publisher.FluxJust' - maybe not public or not valid?
My current workaround is to intercept the request before the request is delegated to the RoutingFunction and try to reconstruct the payload from the HashMap with the following code:
#Autowired
RoutingFunction f;
#Bean
public Function<Message<LinkedHashMap>,?> router() {
return value -> {
String json = new JSONObject(value.getPayload()).toString();
Message<?> m = MessageBuilder.createMessage(json, value.getHeaders());
Object result = f.apply(m);
return result;
};
}
Is there a way proper way to use the HTTP API Gateway in combination with Function Routing in AWS?
On my project I've set function.definition and function.routing-expression like that:
spring.cloud.function.definition=functionRouter
spring.cloud.function.routing-expression=headers['pathParameters']['proxy']
This will be using the org.springframework.cloud.function.context.config.RoutingFunction that Spring Cloud Function provides and the expression would get the function name from the path.
If you still want to use the headers you could do:
spring.cloud.function.routing-expression=headers['headers']['function'].
The HTTP headers are added in the Message headers in the headers property.
So first we get the Message headers and then the HTTP headers and then the header key.

How can I use SwaggerValidator(com.atlassian.oai.validator) to validate Lagom API Response?

Well, I am stuck in this scenario that I want to use Swagger API to validate response of my Lagom Service API.
Here is some sample code:
#Test
public void shouldPayloadFromFileConformToSchema() throws Exception {
// first test the plain json is valid with schema
SwaggerRequestResponseValidator validator = SwaggerRequestResponseValidator
.createFor("my-service-schema.yaml").build();
final Request validRequest = SimpleRequest.Builder.get("/myService/AL20170730/11111555556161/191919")
.withHeader("api-key", "TESTKEY")
.build();
Response validResponse = SimpleResponse.Builder.ok()
.withBody(ValidatorTestUtil.loadResponse("my_service_sample_response_2017_03_16")).build();
ValidationReport reportForText = validator.validate(validRequest, validResponse);
logger.info(
"shouldPayloadFromFileConformToSchema() ################# VALIDATION PAYLOAD REPORT ##################");
reportForText.getMessages().forEach((m) -> {
logger.info("{}", m);
});
assertFalse(reportForText.hasErrors());
logger.info(
"shouldPayloadFromFileConformToSchema() ################# VALIDATION PAYLOAD REPORT END ##################");
logger.info(validRequest.getHeaders().toString());
SwaggerModule swagger = new SwaggerModule();
}
When This code runs It seems that it goes into the service(as it prints some logs of the service.) but not invokes the method which will the database with the given values.
I need to do something here that it invokes the method of the service and validates the response on the basis of this swagger spec.
I saw this link but didn't get the solution How to validate API in tests with Swagger?
If you're looking to validate an actual interaction against your running service I'd recommend using the RestAssured module (https://bitbucket.org/atlassian/swagger-request-validator/src/master/swagger-request-validator-restassured/)
This will let you execute a request against your running service and then validate that the request/response interaction matches your swagger specification.
There's an example of its use in the examples module - https://bitbucket.org/atlassian/swagger-request-validator/src/master/swagger-request-validator-examples/src/test/java/com/atlassian/oai/validator/examples/restassured/SwaggerValidationFilterTestExample.java (note that the example there uses WireMock to stub out a real service, but you would replace that with your actual running service).

How to customize WebApi OAuth token validation?

Context
I have a working WebApi2 application, which uses the out of the box bearer token validation, just as was in the original Visual Studio project template.
I would like to add a custom data to the generated token, then check against that custom data when the subsequent api calls happen what are presenting this token.
For the sake of example say I would like to store the IP address of the caller when the token was created, then when validating the token check if the call which is uses the token have the very same IP.
I found the custom class
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
in my project and I also see that OAuthOptions is configured to use that custom class in start up.
I suppose where to add my custom token data (the ip):
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
here I can add it to the ticket properties as custom data.
Question
However I can not find out in what method to check against the token has this data, and it matches to the actual call's ip, and if not, then regard the token invalid?
You are absolutely right when you decided to implement OAuthAuthorizationServerProvider . Now you need to add something like this:
private ClaimsIdentity CreateIdentity(User user, string authenticationType)
{
var identity = new ClaimsIdentity(authenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, user.Login));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.UserID.ToString())); // or ip instead of user.UserID if you need
return identity;
}
And then use it in your Grant... method (for instance GrantResourceOwnerCredentials) like this:
ClaimsIdentity identity = CreateIdentity(user, context.Options.AuthenticationType);
context.Validated(identity);
Then when request come to your webapi controller you can check your data in your custom Attribute:
Claim userIdClaim = ((ClaimsIdentity)actionContext.ControllerContext.RequestContext.Principal.Identity)
.Claims
.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
hope it helps.

Resources