We named our path parameter {pokemon} in the httpApi route, so to access this value in our function, we have to use event.path_parameters.get("pokemon").
event.path_parameters is a HashMap<String, String>, so we can use get to get the value the user passed in for the pokemon parameter.
.get returns an Option<String> because it’s possible the key we ask for might not be there, so we use match to take care of both cases.
async fn handler(
event: LambdaEvent<ApiGatewayV2httpRequest>,
) -> Result<ApiGatewayV2httpResponse, Error> {
let (event, _context) = event.into_parts();
match event.path_parameters.get("pokemon") {
None => Ok(ApiGatewayV2httpResponse {
status_code: 400,
headers: HeaderMap::new(),
multi_value_headers: HeaderMap::new(),
body: Some(Body::Text(serde_json::to_string(
&json!({
"error": "No pokemon requested",
"data": {}
}),
)?)),
is_base64_encoded: Some(false),
cookies: vec![],
}),
Some(pokemon_requested) => {
Ok(ApiGatewayV2httpResponse {
status_code: 200,
headers: HeaderMap::new(),
multi_value_headers: HeaderMap::new(),
body: Some(Body::Text(
serde_json::to_string(&json!({
"data": {
"requested": pokemon_requested
}
}))?,
)),
is_base64_encoded: Some(false),
cookies: vec![],
})
}
}
}
In the None case, we return a 400 status code and some json with an error field. The JSON here is entirely our own construction. We can send back whatever we want.
In the case of having a pokemon parameter, we return the same 200 we did before, except in this case I’ve chosen to also return the Pokemon’s name in lieu of the data from the Table which we haven’t fetched yet.
After compiling we can run diff to confirm that we’ll be uploading the new asset and deploy.
cargo zigbuild --target x86_64-unknown-linux-gnu.2.26 --release -p pokemon-api
cp target/x86_64-unknown-linux-gnu/release/pokemon-api lambdas/pokemon-api/bootstrap
cd infra
npm run cdk diff -- --profile rust-adventure-playground
> infra@0.1.0 cdk
> cdk "diff" "--profile" "rust-adventure-playground"
Stack InfraStack
Resources
[~] AWS::Lambda::Function PokemonHandler PokemonHandlerC37D7DE3
├─ [~] Code
│ └─ [~] .S3Key:
│ ├─ [-] 68f781d3b50360c320feaabb183c897660e306ccb8bfa65d497306a4af953237.zip
│ └─ [+] 49d3cea05431f80231ac814a6554a2c71c449a4363984373e8ea1f666fcc4dde.zip
└─ [~] Metadata
└─ [~] .aws:asset:path:
├─ [-] asset.68f781d3b50360c320feaabb183c897660e306ccb8bfa65d497306a4af953237
└─ [+] asset.49d3cea05431f80231ac814a6554a2c71c449a4363984373e8ea1f666fcc4dde
Curling the endpoint as before will now return us the requested Pokemon name.
❯ curl https://72i5uisgr5.execute-api.us-east-1.amazonaws.com/pokemon/bulbasaur
{"data":{"requested":"bulbasaur"}}
It’s actually pretty tough to get the None case to fire in production as the API Gateway will only send us requested to the /pokemon/{pokemon} route in the first place, which means {pokemon} is defined, even if it’s an empty string.
We can, however, make it happen if we set up our sample JSON from earlier to cause it. I’ll leave that as an exercise to you if you wish to try.