News for hackers. Stuff that matters.
Re:Some items from my “reliability list” by citrusx on Thursday July 25, 2019 @12:51PM (#20527009)
In my opinion, a rejection is an expected outcome, and therefore should have a response code of 200. You're not asking, "Does this card exist?", and sending a 404 if you have no record. You're asking a remote system to do a job for you, and if that job completes successfully, it's a "Success" in the HTTP world.

At that point, you rely on the body content to tell you what the service correctly determined for you. A result that the user doesn't like is way different than a result that comes about because something was done wrong at the client side (4xx) or a failure on the server side (5xx).

Re:Some items from my “reliability list” by bandushrew on Thursday July 25, 2019 @11:00PM (#20532001)
Its the difference between whether you believe you are using HTTP as a transport mechanism or you believe you are using it to create a DSL protocol.

Personally I prefer to think of HTTP as a transport mechanism, with business logic at a higher level. The question "If I replaced this http transport with, say, FTP or a dvd drop, would it require changes at the business logic level?" feels important to me.

That preference puts me on the wrong side of history at the moment though, and Im going with history. Lets express our business logic through the error system provided by our transport mechanism instead....

Re:Some items from my “reliability list” by sagichmal on Thursday July 25, 2019 @02:17PM (#20527901)
> You're asking a remote system to do a job for you, and if that job completes successfully, it's a "Success" in the HTTP world.

But a provided credit card number not existing is not success, it is unambiguously a failure.

HTTP is a transport but its response codes are clearly designed to map somehow to the "business logic" of the thing underneath it. We have to twist ourselves up in knots to map most of our business systems to the set of status codes that make sense for the default HTTP-fronted application (Fields' thesis stuff) but that's what we sign up for when we decide to expose our business services via HTTP. Other transports require different contortions.

Re:Some items from my “reliability list” by treis on Thursday July 25, 2019 @03:05PM (#20528382)
>But a provided credit card number not existing is not success, it is unambiguously a failure.

But the failure is ambiguous. If I get a 404 back I can't rely on that to mean the credit card doesn't exist. It could mean that I have the wrong URL or that the service application screwed up their routing code.

Re:Some items from my “reliability list” by nulagrithom on Thursday July 25, 2019 @03:11PM (#20528448)
You wouldn't put a card number in the path anyway (for obvious reasons). Far more sensible to put that in the request body.

And who's to say you can't put the reason in the body and still keep the code? What are you hurting by sending back 400? Unless you have lb's taking out nodes because of excessive 4xx's (which sounds like insanity) I don't see a reason _not_ to send 4xx's. At the very least it's a useful heuristic tool.

Re:Some items from my “reliability list” by tlynchpin on Thursday July 25, 2019 @09:12PM (#20531454)
What are the obvious reasons? I'll presume you are referring to disclosure of the card number.

I had this discussion recently about 'security' with regard to X-Header versus ?query=param. Either it's http all plaintext on the network or it's http with tls all cyphertext on the network. Every bit in the http request and response is equivalent - verb, path, headers, body, etc - agree?

You could represent the card number as cyphertext in the request body, that's a good practice regardless of tls, but of course don't roll your own crypto. You could put that cyphertext in the path as well but if the cyphertext isn't stable that makes for a huge mess of paths.

You could make a case for trad 'combined' access logs situation with the path disclosed in log files. I can appreciate keeping uris 'clean' makes it safe to integrate a world of http monitoring tools, I would make this argument. In the case of the card represented in a stable cyphertext it's kinda cool to expose it safely to those tools.

Anything else?

Re:Some items from my “reliability list” by tda on Thursday July 25, 2019 @11:57PM (#20532244)
If you grab something from an external service (say a cdn) then I believe by default the referrer will contain the url + query params, but not you X=supersecret header. Bit me once
Re:Some items from my “reliability list” by treis on Thursday July 25, 2019 @03:54PM (#20528918)
>And who's to say you can't put the reason in the body and still keep the code?

Often systems will have application wide error handling to catch that and handle it in a systemic way. It can be a pain to short circuit that in a customizable off the shelf applications like Salesforce.

Philosophically, 4XX means the client did something wrong. Sending invalid data to a validation service is not doing something wrong.

Re:Some items from my “reliability list” by sagichmal on Thursday July 25, 2019 @04:43PM (#20529484)
> Philosophically, 4XX means the client did something wrong. Sending invalid data to a validation service is not doing something wrong.

The precise definition of 400 Bad Request is

    The 400 (Bad Request) status code indicates that the server cannot or
    will not process the request due to something that is perceived to be
    a client error (e.g., malformed request syntax, invalid request
    message framing, or deceptive request routing).
There's some room for interpretation for the phrase "process the request". If the only job of the service is to validate the request and return Valid or Invalid, then I guess yeah even an invalid request will have been processed, and 400 Bad Request may not be totally right. I think you could make a case for it! But I think you could also make a case for 200 OK with a more detailed error message and code in the body.

But if the service both validates the request and _then_ does something more substantial with it, I think 400 Bad Request is probably the most appropriate response to something that fails at step one.

Re:Some items from my “reliability list” by stingraycharles on Thursday July 25, 2019 @02:49PM (#20528233)
Exactly. The parent is thinking along the lines of “but when the error is thrown successfully, it actually means success!” and at the same time missing out on an opportunity to leverage a well-understood error handling standard in HTTP.
Re:Some items from my “reliability list” by nulagrithom on Thursday July 25, 2019 @03:07PM (#20528397)
Agreed. What else would you use 400 for? I don't see how sending back 400 is going to hurt.

The payoff of using 400 is you can watch your 400 rates with almost no effort (HTTP is well established and there's many many tools out there.) If you somehow start accidentally munging the card number sometimes or if your card processor starts doing wacky stuff you'll see a spike in 400 rates.

If it was really that troubling that declined cards are expected, I would personally at least want to see 200 come from the internal API and 400 go out to the client.

And if your "intermediate devices" start doing goofy stuff to 400's then you've got bigger problems... 4xx's shouldn't be taking nodes out of prod. That's wack.

Re:Some items from my “reliability list” by neop1x on Friday July 26, 2019 @12:05PM (#20535810)
In my opinion 404 should really mean the API endpoint doesn't exist and therefore the requested action did nothing. Using HTTP for business logic is like using ethernet frames with parts of IP. It is another level, HTTP is just a transport. 404 - not found, 5xx server problem, 301 - endpoint is now elsewhere etc. HTTP is for browser pages but you are actually making API requests using your JSON(or urlencoding or whatever)-based application protocol.
Re:Some items from my “reliability list” by stingraycharles on Thursday July 25, 2019 @04:23PM (#20529243)
> 4xx's shouldn't be taking nodes out of prod. That's wack.

Welcome to AWS, where this is actually part of standard procedure (at least Elastic Beanstalk does this, not sure if it’s actually Elastic Loadbalancer under the hood).

Re:Some items from my “reliability list” by therein on Thursday July 25, 2019 @10:52PM (#20531975)
Don't you love it when all configured backends/origins for a service are marked unhealthy through healthchecks, Amazon's load balancers route traffic to all origins.
Re:Some items from my “reliability list” by Aeolun on Friday July 26, 2019 @05:34AM (#20533512)
I mean, the alternative is routing it nowhere. Might as well throw it at the wall and see if it sticks.
Re:Some items from my “reliability list” by kyle-rb on Thursday July 25, 2019 @03:52PM (#20528894)
>What else would you use 400 for?

400 is "bad request"; you might use it if the request body was not valid JSON.

Re:Some items from my “reliability list” by hugelgupf on Thursday July 25, 2019 @02:45PM (#20528198)
It is a failure, but not of the HTTP service. It's a failure of the RPC call.

404 means "this API doesn't exist", not "the API exists but it returns an error"

Re:Some items from my “reliability list” by sagichmal on Thursday July 25, 2019 @02:51PM (#20528252)
404 does not mean "this API doesn't exist". It means, quote,

    The 404 (Not Found) status code indicates that the origin
    server did not find a current representation for the target 
    resource or is not willing to disclose that one exists.
Resource here is a transport-level (HTTP) representation of a business-logic concept, in most cases a document, but if your HTTP server happens to front a credit card validation service, potentially a credit card. Or a user. Or a recipe.
Re:Some items from my “reliability list” by p1necone on Thursday July 25, 2019 @04:12PM (#20529096)
I typed up a big spiel about the difference between "expected in business logic failures" and "infrastructure failures", but then I looked at the wikipedia page for HTTP error codes and it does look like some HTTP 400 level errors are intended for cases like clients sending data that fails business logic level validation and the like.
Re:Some items from my “reliability list” by sagichmal on Thursday July 25, 2019 @04:16PM (#20529140)
That's right.

And let me say it's totally valid to just ignore that advice, and say that here, in this company, we use 200 OK for everything that isn't a parse failure. And that's not totally wrong! It won't break anything. You're not really leveraging any of the power of your transport but maybe that's fine for your situation.

Re:Some items from my “reliability list” by meowface on Thursday July 25, 2019 @01:56PM (#20527698)
I think this is the exact right way of looking at it. 4xx/5xx are for layers that are below the business logic (like "is the web server able to route this path", not "did the application successfully validate the user's input data and allow them to continue on to the next step in a process").

It can get a little fuzzy for 401 and 403 errors, though; those seem to be returned by APIs pretty often. Not entirely sure how I feel about that, but I think those are a bit more sensible.

Re:Some items from my “reliability list” by jacobgreenleaf on Thursday July 25, 2019 @02:09PM (#20527833)
The HTTP IETF RFC (2616) states:

> The first digit of the Status-Code defines the class of response. The last two digits do not have any categorization role. There are 5 values for the first digit:

> - 4xx: Client Error - The request contains bad syntax or cannot be fulfilled

What do you think status codes like 404, 405, 406 are for? You say they shouldn't be for "did the application successfully validate the user's input data" but status code 400 is explicitly for bad requests. In your view should a HTTP server ever return 4xx?

Re:Some items from my “reliability list” by meowface on Thursday July 25, 2019 @03:07PM (#20528401)
It depends how you define validate. If the HTTP headers are malformed, sure. If a JSON or XML API receives malformed JSON or XML, sure. But if it's "register this account" and the username already exists, or "pay with this credit card" but it's not a valid credit card number, or "process this invoice" but the total is missing, then I think it should be a 200 status with an error message. It's validating the request was received and loaded by the application vs. validating the business logic requirements for the request's data payload.

Obviously if you send a TAIL method request, you should get a 405, and if you send Accept: eggs/*, you should get a 406. If a route doesn't exist, you should get a 404. If you fail HTTP basic auth, you should get a 403 (but why are you using HTTP basic auth?). If you want certain paths to never be accessed for some reason, you should return a 401.

Re:Some items from my “reliability list” by stcredzero on Thursday July 25, 2019 @02:34PM (#20528088)
You're not asking, "Does this card exist?", and sending a 404 if you have no record.

Doesn't this depend on the nature of the REST API? (Though putting a credit card number on the path doesn't seem like a good practice.)