How to return non 200 HTTP status codes with Serverless + OpenWhisk and behind IBM Cloud API Gateway? - openwhisk

I can't figure out how to return http status codes for functions behind an API GW. No matter what I return, it always comes back as a 200. I've tried statusCode and code to no avail.
I'm using the Serverless framework with the OpenWhisk plugin. I'm deploying to IBM Cloud.

Web Action response content type parameter must be set to http to manually configure the HTTP response. This value defaults to json which ignores returned headers and statusCode values.
In The Serverless Framework, this value is set in the event configuration section of your YAML.
functions:
my_function:
handler: index.main
events:
- http:
method: GET
path: /api/greeting
resp: http

Related

KrakenD returns a 500 when the body of the backend endpoint doesnt have any data

I am using KrakenD to make a call to a Salesforce endpoint
/services/data/v56/jobs/ingest/{{_jobId}}/batches
This backend endpoint doesn't return any data in the response body and as a result the call fails with a 500. From the logs -
[00] [KRAKEND] 2023/01/27 - 23:39:45.615 ▶ ERROR [ENDPOINT: /ingest/:jobId/batches] EOF
How do I solve this error? How can I tell KrakenD to expect the empty response body?
I am not using any custom plugins.
You should check the encoding defined at the backend section (by default, it's JSON) and select one that suits your backend responses. Here you'll find some recommendations: https://www.krakend.io/docs/backends/supported-encodings/#how-to-choose-the-backend-encoding
If you are expecting empty responses, you could use no-op (https://www.krakend.io/docs/endpoints/no-op/)

AWS Apigw v2 custom headers not being passed

I've got an API gateway v2 which is using a proxy integration to lambda.
I'm trying to pass a custom header value via a GET call to my API.
...
fetch(new Request(refreshUrl, {
method: 'GET',
headers: new Headers({
'refreshToken': user?.tokens.refreshToken
})
}))
...
I can't for the life of me figure out how to get APIGW to pass that header value to my lambda. When I log the event received in my lambda, my "refreshToken" header is nowhere to be seen.
I've tried to add parameter mapping such as the following to my lambda integration in apigw with no success:
$request.header.refreshtoken
And the documentation for such scenarios with AWS only seems to show for APIGW v1.
Solved:
The issue wasn't related to APIGW. The request parameter mapping is correct.
The problem was that I was proxying the api via cloud front and I needed to whitelist the header in my distribution.

Google API Gateway: Authorization Header not forwarded

I have a google cloud api gateway deployed to send requests to a cloud run service.
The cloud run service hosts a laravel docker container image and to authenticate with my authenticated pages, I need to send an Authorization header (Authorization: Bearer my-user-token-here).
When I send the request directly to the cloud run service, I am able to get the response I need with the Authorization header set. But, when I send the request through the api gateway, I always get an unauthenticated message showing the header is missing in the api request to the cloud run. I am not sure of this though.
I can't find any useful documentation on google cloud api gateway to suggest whether cloud run drops the header.
I am also not sure whether the error is from the openapi.yaml. So far I realized I cannot use the v3 of the openapi documentation but rather v2 as api gateway does not support v2. In the v2 of the openapi docs, the securityDefinitions don't support Authorization header Bearer token but instead supports Authorization header basic.
My Openapi yaml
# openapi2-run.yaml
swagger: "2.0"
info:
title: my-api
description: my custom api
version: 1.0.0
schemes:
- https
produces:
- application/json
consumes:
- application/json
x-google-backend:
address: https://some-cloud-run-url
basePath: /api
host: my-api.nw.gateway.dev
x-google-endpoints:
- name: "my-api.nw.gateway.dev"
allowCors: True
paths:
/user:
get:
summary: Requested user details.
operationId: UserDetails
responses:
"200":
description: Return Requested User Details.
schema:
type: string
"default":
description: Unexpected error
The surprising fact is that if I send the request either locally or directly to the cloud run, it works and I get no authentication error, but when I use the api-gateway, then I get the error. So I am guessing it has to do with the header going missing when the request reaches the cloud run, probably because the yaml definition I have here does not have an authorization header.
We have an API gateway instance which sends requests to cloud functions.
If any incoming requests have an Authorization header, the gateway maps the header details into an X-Forwarded-Authorization header in the request to the cloud function.
I assume it's the same for requests to Cloud Run. I don't have any experience with Laravel to know if it has options to look in the forwarded header, though.
Actually you can ignore it by setting the disable_auth in x-google-backend.
The document is not in google gateway, but in google endpoint as follow.
https://cloud.google.com/endpoints/docs/openapi/openapi-extensions
By the document it said:
When configuring your target backend, you may not want to use IAP or IAM to authenticate requests from ESPv2 if either of these conditions apply:
The backend should allow unauthenticated invocations.
The backend requires the original Authorization header from the API client and cannot use X-Forwarded-Authorization (described in the jwt_audience section).
So in your particular case, you just need to modify a single block like this:
x-google-backend:address:
https://some-cloud-run-url
disable_auth: True
And it will work like a charm.
Beware that once you decide to do the authorization yourself, you cannot set the securityDefinitions in the gateway config. The gcp gateway will throw 401 if you do this.

API GW V2 HTTP API and legacy lambda authorizer

I'm trying to integrate API GW v2 HTTP API with legacy (payload version 1.0) custom lambda authorizer. It's able to invoke the custom lambda authorizer but getting below response ($context.authorizer.error) in gateway logs with 500 status ($context.authorizer.status https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-logging-variables.html)-
The response from the Lambda Authorizer function doesn't match the format that API Gateway expects. Invalid value for 'context'
Which indicates that it's not abiding to the response format as mentioned here-
https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html#http-api-lambda-authorizer.payload-format-response
But same legacy lambda is working fine with API GW v1 REST APIs. Also cannot enable the execution logs like REST API so not able to see the actual response returned by lambda if by any chance it's not returning the correct response but i doubt that.
So problem seems to be API GW HTTP API doesn't like null values in context variable from Lambda authorizer. For now going to suppress the null values but ideally API GW should handle the null values gracefully. Another problem is it seems to be timing out in case time taken is more than 10 secs by Lambda authorizer but there's no way timeout can be configured for lambda authorizer.

AWS api gateway - http proxy should take status code from origin

I am currently trying to setup AWS Api Gateway, to proxy to another api, that has fully functional methods, response content, status codes etc. This is fairly simple to setup, but I have noticed that the Api Gateway always returns 200 OK no matter what the origin api responds with.
Fx. if there was a bad request (in the origin api) which results in a error message in JSON and a 400 Bad Request, the Api Gateway will respond with a the exact same error message, but a status code of 200 OK
If I remove all settings from the Message Response in the API Gateway web-interface, I get an internal error in the API Gateway. Can it be true that I have to map all the different status codes from the origin api manually in the Api Gateway?
I would prefer if it was possible to just let the status code (as well as the response, which currently works great) pass through, and not have the Api Gateway touch it in any way.
Proxy integration can be used to achieve this. In this case, it is HTTP Proxy. Lambda Proxy integration can also be used but will need some code logic in lambda. API GW will then return the result as-is.
You are correct that currently when using API Gateway you are required to map all response codes in your integration responses. We have heard this "pass through" request from other customers and we may consider including this in future updates to the service.

Resources