'Header x-rapidapi-proxy-secret not forwarded by Heroku

I wrote and API with RapidAPI and deployed it on Heroku. I then listed the API on RapidAPI marketplace which uses a x-rapidapi-proxy-secret header to help me make the api is accessible only through RapidAPI.

To do this I added the following code to my API:

app = FastAPI()
secret_header = os.environ.get("PROXY_SECRET", None)

@app.middleware("http")
async def check_rapidAPI_proxy_header(request: Request, call_next):
    # Check if server knows about valid "secret"
    if secret_header:
        headers = request.headers
        # If the header is missing, or does not match expected value
        # Reject the request altogether
        print(headers)
        if (
                "X-RapidAPI-Proxy-Secret" not in headers
                or headers["X-RapidAPI-Proxy-Secret"] != secret_header
        ):
            return PlainTextResponse(
                "Direct access to the API not allowed", status_code=403
            )

    response = await call_next(request)
    return response

When a request comes to my API through RapidAPI the headers do include the x-rapidapi-proxy-secret but then Heroku redirects the request to the same dyno but this time the x-rapidapi-proxy-secret is not included.

Here are the Heroku logs showing the redirect and a print I added with all the headers that arrive with each request:

2022-05-13T09:49:58.118798+00:00 heroku[router]: at=info method=GET path="/endpoint?phrase=example_input" host=exampleapi.herokuapp.com request_id=801e146f-6175-491e-8b2f-aae28390e1e6 fwd="176.12.151.31, 176.12.151.31,18.197.117.10" dyno=web.1 connect=0ms service=21ms status=307 bytes=235 protocol=https
2022-05-13T09:49:58.117345+00:00 app[web.1]: Headers({'host': 'exampleapi.herokuapp.com', 'connection': 'close', 'x-real-ip': '176.12.151.31', 'x-forwarded-for': '176.12.151.31, 176.12.151.31, 18.197.117.10', 'accept': '*/*', 'accept-encoding': 'gzip, deflate', 'user-agent': 'python-requests/2.27.1', 'x-rapidapi-host': 'exampleapi.p.rapidapi.com', 'x-forwarded-port': '443', 'x-forwarded-proto': 'https', 'x-mashape-version': '1.2.8', 'x-mashape-proxy-secret': '**censoredkey**', 'x-rapidapi-version': '1.2.8', 'x-rapidapi-proxy-secret': '**censoredkey**', 'x-rapidapi-tenant-name': 'p', 'x-mashape-user': 'myusername', 'x-mashape-subscription': 'BASIC', 'x-rapidapi-user': 'myusername ', 'x-rapidapi-subscription': 'BASIC', 'x-request-id': '**censored**', 'via': '1.1 vegur', 'connect-time': '0', 'x-request-start': '1652435398096', 'total-route-time': '0'})
2022-05-13T09:49:58.117942+00:00 app[web.1]: 176.12.151.31:0 - "GET /endpoint?phrase=input" 307
2022-05-13T09:49:59.164640+00:00 heroku[router]: at=info method=GET path="/endpoint/?phrase=input" host=exampleapi.herokuapp.com request_id=8a88d8f6-ebfb-4da7-9d53-c6b7d8d3072c fwd="176.12.151.31" dyno=web.1 connect=0ms service=6ms status=403 bytes=196 protocol=https
2022-05-13T09:49:59.163686+00:00 app[web.1]: Headers({'host': 'exampleapi.herokuapp.com', 'connection': 'close', 'user-agent': 'python-requests/2.27.1', 'accept-encoding': 'gzip, deflate', 'accept': '*/*', 'x-rapidapi-host': 'exampleapi.p.rapidapi.com', 'x-rapidapi-key': '**censored**', 'x-request-id': '8a88d8f6-ebfb-4da7-9d53-c6b7d8d3072c', 'x-forwarded-for': '176.12.151.31', 'x-forwarded-proto': 'https', 'x-forwarded-port': '443', 'via': '1.1 vegur', 'connect-time': '0', 'x-request-start': '1652435399157', 'total-route-time': '0'})
2022-05-13T09:49:59.163820+00:00 app[web.1]: 176.12.151.31:0 - "GET /endpoint/?phrase=input HTTP/1.1" 403

And the request gets the following response

bash-3.2$ python3 tests/test_rapid_api.py
Direct access to the API not allowed

If I understand this correctly the initial requests arrives at a load balancer which then redirects the request to a worker dyno but doesn't include the x-rapidapi-proxy-secret header which is why the worker dyno rejects the request.

Is there a way to make Heroku forward that header as well? Or is there a different way I should have handled checking the x-rapidapi-proxy-secret in my API?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source