I use AWS Elastic Load Balancing and was surprised to see that my server is unhealthy, yet handles requests without a problem. Upon further investigation, I discovered that the reason for that is the absence of the
Accept header. I logged on the machine and:
curl -XGET -I localhost:80/admin(which has
Accept: */*by default) returns HTTP 200
curl -XGET -I localhost:80/admin -H "Accept:"(
Acceptis set to empty) returns HTTP 404
This header is lacking in the raw HTTP request that the load balancer sends:
GET /admin HTTP/1.1 Host: 172.31.32.240 Connection: close User-Agent: ELB-HealthChecker/2.0 Accept-Encoding: gzip, compressed
…which results in a 404 and "Severe" state in Elastic Beanstalk.
Then, I tested locally and found out that this only happens in production mode. In development, it returns status code 200, regardless of
Accept. What appears to be fixing it is the Webpack middleware. If I comment out this line:
…I can get the same behavior in development mode as well.
npm run build, then
npm run serveto run Payload in production mode
curl -i localhost:3000/admin -H "Accept:"
HTTP/1.1 404 Not Foundwith the Express error
Cannot GET /admin
Note, however, that requesting a file from the build folder like
curl -XGET -I localhost:3000/admin/styles.css -H "Accept:" correctly returns status 200.
/admin should always return status code 200.
Payload version: 1.3.0
Hey @hdodov — we just looked into this in-depth and I have some explanations for you as well as a potential solution.
In production, we are simply leveraging
express.static to serve static files. The
Accept header is necessary to be able to consume
html, etc. from a server response, and being that your health check request does not specify it, Express does not return with any results - thus 404.
This is not something that Payload can control, and further,
express.static does not have any options for how to treat the
Instead, what you could do would be to point your health check to a custom route that you've opened, like
/health-check and have your route return a 200.
Either that, or you could figure out if there is a way to modify the health check request that you are sending from Elastic Load Balancing to add a header to that request, which should be possible. Because really what you're telling Elastic to do is to hit a static file, with no Accept header, which will rightly 404, as there is no Accept header allowing
html response types.
Does that make sense?
Yep, adding a
/health route is exactly what I did. I just thought that maybe it's an issue with Payload, rather than Express.
Looking into this one @hdodov. I was able to recreate.