Recommended health check strategy is impossible using AWS load balancer

Apollo recommends enabling CSRF (solid recommendation :white_check_mark:)

Apollo recommends making a GET query to perform a health check against the Apollo server, not just the underlying (e.g. Express) server (also a solid recommendation :white_check_mark:)

In order to make a GET query for the health check, you must include headers. The docs are explicit:

Sending an apollo-require-preflight: true header alongside your health check ensures that Apollo Server’s CSRF prevention feature won’t block it.

A common way of configuring a health check (at least in AWS) is a load balancer health check. The AWS Load Balancer health check does not support configuring headers in the request. Therefore, using Apollo’s recommended health check strategy is impossible.

Is there any workaround for this? Is this a known issue? Does this deserve a bug report?

Thanks.

3 Likes

Spot on Eric. We are stuck with the same thing.

Have you managed to find a workaround?

2 Likes

+1 to you both. Having the same issue. My temporary fix was to turn off CSRF protection. I think a bug report might make sense for health checks that can’t have headers in the request. Maybe it’s just a documentation improvement (on how to implement a health check that tests that the GraphQL parts are working.

I can create an issue if the two of you haven’t figured out another way around this.

1 Like

Actually, I ended up creating a quick health check endpoint of my own just now that worked and is aligned with the health check that Apollo proposes.

    app.get('/check-health', (_req, res) => {
      server
        .executeOperation({ query: '{ __typename }' })
        .then((data) => {
          if (data.body.kind === 'single') {
            if (data.body.singleResult.errors) {
              res.status(400).send(JSON.stringify(data.body.singleResult.errors));
            } else {
              res.status(200).send(JSON.stringify(data.body.singleResult.data));
            }
          }
        })
        .catch((error) => {
          res.status(400).send(JSON.stringify(error));
        });
    });

I turned CSRF protection back on, pointed the load balancer to my new endpoint, and everything seems good.

1 Like

Appreciate the tip. It took me a bit of scratching my head (and just asking ChatGPT) to recognize that this snippet of code had to be executed before app.use(), otherwise Apollo’s CSRF rule will still affect the outcome.