Card 08/ 10
A GET That Changes Data
A link that deletes a record on GET is followed by crawlers, prefetchers and link previews without anyone clicking.
A GET request that changes data breaks the promise that GET is safe, and the software that relies on that promise will trigger it without any person choosing to. Browsers prefetch links, mail scanners open them to check for malware, chat apps fetch them to build previews, and crawlers follow every one. Any action that changes state belongs on an unsafe method.
Picture an admin page listing orders, each with a "cancel" link to GET /orders/42/cancel. One morning, dozens of orders are cancelled and nobody admits to clicking anything. An administrator had opened the page in a browser that prefetches links it expects to be clicked next.
The symptom. Records that change with no user action in the logs, often in bursts, from user agents that are crawlers, scanners or browsers fetching in the background.
GET /orders/42/cancelfollowed by anything that reads links
A plain link. Prefetching, a link preview or a scanner sends the GET, and the order is cancelled.
POST /orders/42/cancellationsent only on purpose
A button in a form, or a script call. Nothing sends a POST without code or a person choosing to, so the order is cancelled only when someone asks.
Why it happens. A link is the easiest thing to build, and in testing only people click. But every program that handles URLs, from caches to email security filters, is entitled to treat a GET as harmless and send it as often as it likes.
What it costs. Data changed or deleted with no one responsible. The same flaw makes the action easy to trigger from another site, since an image tag on any page can make a visitor's browser send a GET with their cookies.
What to do. Put every action that changes state on POST, PUT, PATCH or DELETE. For links in emails, such as "unsubscribe", let the GET show a page with a confirmation button that sends a POST, so a scanner sees the page and changes nothing.
← → move through sections and cards