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.