Recent posts from crabmusket.net
The headlines:
Keep reading for the full posts:
Why there should only be 5 HTTP response codes
05 Dec 2024
I’ve developed a strong opinion about exceptions over the last few years. There are only two pieces of information that all exceptions should include:
- Whose fault is the error? Was it you, the client? Or us, the provider?
- How persistent is the error? Should you retry, and if so, should you retry in 10 seconds or 24 hours?
When the client and the provider are not on the same software team, these are the only two answers that determine how an error can be handled.
-
A client error can only be fixed by the client. For example, a field that must be an email address can only be fixed by the person editing the input.
-
Bugs like null pointer exceptions can only be fixed by the developer of the service. It’s useless the client retrying, as they will probably always hit the same code path and there’s nothing they can do about it. In this case, they need to “retry after the next deployment”.
-
Some failures, like deadlocks or other infrastructural or network errors, are transient and the client may choose to retry in a matter of seconds (for interactive uses), or minutes for a queued, batched or other background process. Webhook retries are a classic example; event delivery is often automatically retried over a period of hours and days.
Now, errors should include helpful details beyond just the answers to the questions above. For example, if the email input in a form is incorrect, the response must tell the user exactly which field is wrong and why it is wrong. But these details are pretty much always down to humans to interpret.
This leads me to the conclusion that there are only 5 necessary HTTP status codes:
-
200
: no error -
300
: no error, but client must perform a redirect* -
400
: client did something wrong; fix your submission before retrying -
500
: developer did something wrong; find a workaround or try again next week -
503
: temporary failure, should also provide aRetry-After
response header
*I’ll allow that the semantics of HTTP mean there probably needs to be more than 1 code for redirects. Though I reckon the differences between temporary and permanent redirects etc. could have been expressed just as well with response headers.
I’ve framed this in terms of HTTP response codes, but the same issues apply to exceptions inside your own code. When throwing an exception, ask yourself the questions: who needs to fix this, and when (if ever) should the client retry?
Lightning talk on JSON:API at PHP Sydney
03 Dec 2024
Tonight I gave a lightning talk at the last PHP Sydney Meetup of the year.
The subject was “An Introduction to JSON:API”, which is the spec we use for our APIs at Pylon:
The slides are online here:
https://static.crabmusket.net/2024/json_api_php_sydney/
It was the third talk I’d given at the meetup this year. The talk went well, despite me forgetting to bring the HDMI adapter port for my Framework laptop .
A few small things I forgot to say during the talk:
- It can be tempting to try to fit all API endpoints into the JSON:API mold, but sometimes they just don’t fit well . Like aggregates, charting, RPC calls like “merge these 3 entities”, basically anything outside CRUD. We have come up with various workarounds, but sometimes we just bail and create a cheeky endpoint with a verb in the URL.
- Mentioning some things we need to watch out for when preparing endpoints using Laravel, e.g. preventing 1+n query problems, or avoiding loading relationships entirely when they are excluded by sparse fieldsets.
- I did want to include some Laravel code examples, but since I wrote the slides in about 30min the morning of, I just didn’t have time.
- Someone asked afterwards about type and documentation generation, which I had deliberately excluded from the talk to keep it focused. There seemed to be some interest in a follow-up talk on those aspects of our setup.
I was very slightly disappointed nobody asked me afterwards about JSON Hyper-Schema, though I guess they were just respecting my clearly-stated preference.
That's all folks! Thanks for reading ♥