10 ms·
Imagine that we didn't have a fancy dynamic system and we were still using files for web pages like the good old days. In that scenario, what would happen if so
by grose 4y ago
Imagine that we didn't have a fancy dynamic system and we were still using files for web pages like the good old days. In that scenario, what would happen if someone accessed the non-existent `/api/v1/employees/100` path? It would return 404 Not Found. From that perspective, I think it's hard to justify that the original intentions of HTTP would want you to return a 200.
- Spivak 4y agoIt's the difference between "There is nothing handling this route at all" and "there is something handling this route but the object isn't found." To me the former is an HTTP 404 and the latter is an application "Not Found." But I also very much don't like playing the "if you expose your app over HTTP you should assimilate HTTP semantics and do a fuzzy lossy map of your application to HTTP verbs and HTTP status codes." I leave the HTTP semantics to the front end web server and live on top.
- zeveb 4y ago> It's the difference between "There is nothing handling this route at all" and "there is something handling this route but the object isn't found." 'Nothing handling this route' has no meaning, because routes have no meaning in a hypertext application. Clients should not generally be constructing URLs by hand; they should be receiving them from the servers they communicate with. In the example in the article, an application dealing with employees should not be constructing URLs by appending employee IDs to strings; rather, every reference to an employee in the application should be to a URL rather than an ID. So when it requests a list of employees, it receives the equivalent of {/api/v1/employees/1, /api/v1/employees/2 … /api/v1/employees/N} rather than {1, 2 … N}. > I also very much don't like playing the "if you expose your app over HTTP you should assimilate HTTP semantics and do a fuzzy lossy map of your application to HTTP verbs and HTTP status codes." If you are building a hypertext application, then you should build a hypertext application. It's completely possible. Off the top of my head, protocols such as ACME (used by Let's Encrypt) are good examples to follow.
- NoGravitas 4y agoYep, there's absolutely no reason an application ought to be guessing URLs, and therefore no reason it should ever be requesting /api/v1/employees/69 where employee 69 doesn't exist. If it does, it's playing silly buggers exactly as much as if it were to request /api/v69/nice/. Any user resources it needs to access will have had URLs provided to the application by another page.
- Spivak 4y agoExample Code: users = http.client.get("https://yourapi.com/users") # Frobulate each user for user in users: user = http.client.post(user.frobulate_url) # While this is running somewhere on the other side of # the world someone deletes one of the users. Oops. Assuming, users (i.e developers) will just never mistype a URL so you don't have to give useful feedback is just like being a bad netzen.
- NoGravitas 4y agoThat's a fair example. And returning 404 (Not Found) or 410 (Gone) is the most useful kind of feedback. More explanation in the body of the 404 response is helpful too, of course.
- Spivak 4y ago> Clients should not generally be constructing URLs by hand I'm not sure I get this, every API doc is like "go to /users for the users and here's the methods we support, the payloads, and responses" If someone mistypes it and tried to get "/user" I want to send a 404 to be like "there is nothing here." > In the example in the article, an application dealing with employees. This is all very nice when your domain maps nicely to objects. My litmus tests for this is what would the semantics of mysql.net/query?db=mydb,q='select * from table;' look like. * If the result is an empty record set should it return 404? Ew. I think it should be 200 with the response being `[]`. * If you're not allowed to access a table should you get 403?
- 4y ago
- jmbwell 4y agoIndeed. The application contemplated by HTTP is hypertext. If we are being sticklers for the RFCs, modern applications implementing non-hypertext business logic via HTTP are abusing more than just response status codes. But if we relax the “hypertext” presumption a bit and consider HTTP a protocol for the transfer of resources, surely an API can be implemented such that using response codes is sensible and useful. REST and SOAP for CRUD operations can still work just fine, and response codes can still make sense in the context of the API itself, even if the content is JSON describing business logic state. It’s a messy world, so we have to be liberal in what we accept, but using status codes is not inherently abuse. Any ambiguity might just be a symptom of leaky abstractions in the API.
- yread 4y agoIsn't that enough that there are originalists for constitution, do we now have to have "what did the founding fathers^H^H^H^H^H creators of HTTP mean"-people? That was 30 years ago. Web has evolved since then. What was a good solution then may not be one now. How people work with HTTP now and then is completely different.
- rglullis 4y agoI'll take "People who really need to understand the principle of of Chesterton's fence" for $200, Alex...
- NoGravitas 4y agoOr, people who should be designing a protocol specific to their application, rather than abusing HTTP. Really, it's okay! You don't actually have to use HTTP for everything!
- dragonwriter 4y agoThe most recent specification of HTTP semantics is about a month old.
- treis 4y ago>non-existent `/api/v1/employees/100` path But the path does exist. The employee record represented by that path doesn't exist.
- kweingar 4y agoI guess in a pedantic sense, all possible paths “exist.”
- treis 4y agoNo, paths that reach a server and get processed exist.
- that_james 4y agoThat's a succinct definition, happy to admit that's a better argument than mine
- quesera 4y agoDefine "processed"? A request with a path that reaches a server, is looked up in the routing table or filesystem, resulting in no resources found, is expected to return "404 Not Found". You can say the path "exists", but only as a label. All labels can exist. Only a subset of these are semantically valid resource locator paths, and only a further subset reference objects that exist. Colloquially, https://news.ycombinator.com/this/path/does/not/exist https://news.ycombinator.com/this/path/does/not/exist (path "/this/path/does/not/exist") "does not exist" because we're talking about the requested resource. Of course the path exists, I just wrote it and it's semantically valid. That's not an interesting question though, and if API responses were this shallow -- just a "semantic correctness checker" -- then response codes would be useless.
- treis 4y ago>Define "processed"? Why? We all know what it means. >Colloquially, https://news.ycombinator.com/this/path/does/not/exist https://news.ycombinator.com/this/path/does/not/exist (path "/this/path/does/not/exist") "does not exist" because we're talking about the requested resource. That path is 404 - Not found and returns "Unknown" https://news.ycombinator.com/item?id=52081900 https://news.ycombinator.com/item?id=52081900 Returns 200 - No such item. In 10 years when we have that many threads it will return content. As I've said in several other places it depends what you want to tell the client. 404 if you want to tell them you didn't find the resource. 200 if you want to tell them the resource doesn't exist.
- afiori 4y agoIn this context you would also have to include discoverability of URLs. In this philosophy you would not suppose how employees are named and would ask for a list of valid employees URLs to a URL previously returned by `/api/v1/`. In this way you only ever call URLs that the api provided you with, so that you are not expected to find out by trial and error whether `/api/v1/employees/100` exists or not; the api itself has already told you this and a 404 is the response to trying to build your own URLs by hand.