Back to Feed
article 2m read

Chore delete said it worked and deleted nothing

The browser started sending a chore's id in the query string, the server compared that text to a stored number with a strict check, and every delete rewrote the same file and reported success. Now the id is parsed once on arrival, with a few loose ends I still don't like.

Article DepthPractice

Flow

My chore delete, before and after

  1. 1One id per delete

    The browser sends one request with the id in the web address.

  2. 2Text arrives

    Anything in the address reaches the server as text.

  3. 3Strict compare

    A number never equals text, so every chore was kept.

  4. 4Same reply

    The server said all went fine either way.

  5. 5Convert on arrival

    Now the id becomes a number, or the request is refused.

  6. 6Still loose

    Decimals and a zero id slip through, and the reply has no count yet.

Deleting a chore in my scheduling app didn't stick. The row went away, a success message showed up, and when the list loaded again, the chore was back.

The app is small. It has a schedule, a chore list and a print view. The chores live in one JSON file on the server, and a short PHP script reads and rewrites it.

One request per delete, and the id became text

That day I'd changed the delete. The browser used to send back the whole list. Now it sends one request with the chore's id in the web address. That's better. I'd guess it's also what showed the bug, because anything in a web address arrives as text.

I'd bet the file stores the id as a number. The server compared that number to the text with a strict check, which also checks type:

42 !== "42"   // true, so the row is kept

So every chore was kept. The server wrote the same list back and said everything went fine.

Why every layer reported success

The server's answer never changed, whatever it removed. The browser didn't read the answer anyway. It dropped the row and showed its message. Only the file knew, and it only told me on the next load.

Converting at the door

Now the server turns the id into a number as soon as it arrives. If it can't, it refuses the request before touching the file. It turns the stored ids into numbers too, so both sides match.

The numeric check is more generous than I'd like

The check lets odd values through, like decimals, and turns them into some real chore's number. A chore saved with no id counts as zero, so a request for zero would delete all of those. I'd rather accept plain digits only.

The other hard-coded id

The browser had been spotting one special chore by its id. Now it checks a type field. The print view uses the same rule.

Still missing: a test and a count

There's no test yet, and the server still doesn't say how many chores it removed. The next change I want is small: the browser reads the answer before it shows the message.

Keep reading

Pick up a connected idea or branch into a nearby one.

5 paths forward
Related idea

Auth middleware would have logged everyone out the minute the auth server hiccupped

The SDK middleware turned every failed token check into a redirect to sign-in, so an outage on my side would have looked like a mass logout. I split the answer into yes, no and couldn't-check, and made the middleware answer an outage with a 503. In the same commit the browser client went the other way and now throws away good tokens when the server is unreachable.

via #reliability · #contracts