ResponseCache attribute causing non 200 responses to be cached - asp.net-core

We are using the [ResponseCacheAttribute] from Microsoft.AspNetCore.Mvc.Core with a policy like so on action methods or controllers:
[ResponseCache(CacheProfileName = "Default")]
In case a non 200 response is send like 400, 403 or 500 it is also being cached. So the first time we go to the server and get for example bad request. The second time no call is made to the server and the answer is still bad request (from disk cache).
I read in the documentation that when using response cache middleware only 200 responses are being cached. This attribute seems to be flawed and always adds the caching response header no matter what status code.
We like to define caching only on certain controllers or action methods. Not on all requests.
Does anyone know the solution for this?
I simulate the problem by using a status code result:
return StatusCode(500);
I would then expect it to always come back to this code with a breakpoint and never caching it.

Related

404 vs 204 on GET, PUT, DELETE Methods

If a request want to get/delete/update to a resource which isn't exist, what do you prefer to return? 204 or 404?
Sample: api/blog/{id} can take that requests: GET, DELETE, PUT and api/blog can take GET and POST.
GET: api/blog returns list of blogs, GET: api/blog/{id} returns single blog,PUT: api/blog/{id} updates single blog and DELETE: api/blog/{id} deletes single blog.
In my opinion the distinction that matters is whether the request ends up successfully or not.
So generally in most of the cases 404 is the way to go.
I would recommend so, because the HTTP response codes are grouped by, let's say, result. source
Informational responses (100–199)
Successful responses (200–299)
Redirects (300–399)
Client errors (400–499)
Server errors (500–599)
For example, the process can be like this:
The client attempts to DELETE an entity.
The entity is not there.
This situation can be considered a client error, since deletion of nonexistent entity is being attempted
On 204 again cited from MDN:
The HTTP 204 No Content success status response code indicates that a
request has succeeded, but that the client doesn't need to navigate
away from its current page.
This might be used, for example, when implementing "save and continue
editing" functionality for a wiki site. In this case an PUT request
would be used to save the page, and the 204 No Content response would
be sent to indicate that the editor should not be replaced by some
other page.
If a request want to get/delete/update to a resource which isn't exist, what do you prefer to return? 204 or 404?
"It depends."
If the payload in the response is "a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition", then I'm going to use a 4xx Client Error status code. In the case where I want to draw attention to the target-uri of the request, then I'm going to use 404 Not Found.
On the other hand, if the payload in the response is a representation of the resource, or a representation of a status of a successful action, then I'm going to use some 2xx Successful status code, usually 200 OK.
In particular, if that payload is zero bytes long, I'm normally going to use 200 with Content-Length: 0 rather than 204 No Content. 204 I reserve for those cases where I really want the user agent to stay with the same view. See also 205 Reset Content.
(Part of the lesson here - don't try to guess the meaning of a status code from the accompanying reason phrase. Read the definition.)
Whether or not a resource has a "current representation" at any given time is a "resource design" concern. It can make sense to say that this document has a representation even though we've never talked about it before. Maybe that representation is zero bytes long, maybe it has some default representation, like a government form with a bunch of blanks to be filled in later.
For example, a report of activity during some time period might have a current representation even though the time period described by the report is in the future.
404 in response to PUT or DELETE is weird.
PUT is semantically close to UPSERT, it's strange to object that you couldn't find a current representation of the resource when I'm asking you to replace it with the representation provided in the payload.
Similarly, DELETE is about decoupling a resource from its implementation. Why report that you can't do it when it has already been done?

HTTP Status code >= 300 Returning JSON

I was wondering if it is acceptable/common to have a server return a JSON response along side a 3xx or 4xx response?
The reason I ask this is because I do return a JSON response with more details regarding the error, but it seems the engine I am using doesn't agree with what I am doing. I would like to make sure my approach is acceptable before submitting a PR.
It's perfectly fine for 3xx or 4xx responses to have body entities, sometimes it's even required.
For example, for 300 Multiple Choices:
Unless it was a HEAD request, the response SHOULD include an entity containing a list of resource characteristics and location(s) from which the user or user agent can choose the one most appropriate.

REST/HTTP: best status code to prevent cached upload?

I'm designing an API where a client PUTs a file to the server, but the server may already have a copy of this file and not need it re-uploaded.
I'm already planning on using Expect: 100-continue so that the server can inform the client before the client performs the entire, inefficient upload.
My question is, what's the best status code to return instead of 100 Continue in the case that the server doesn't need the upload?
Typically, the client could send an If-None-Match header, and the server could respond with a 412 Precondition Failed if there was already a match.
But, in my case, the de-duplication is almost an implementation detail, and I don't want the client to be concerned with knowing the de-dup'ing strategy (e.g. what the value to match is).
Would a 302 Found, a 303 See Other, or a 304 Not Modified make sense?
It doesn't seem like a 4xx is appropriate since it's not a client error, nor 5xx since I don't want to trigger any automatic retry logic in the client.
Thanks!
From the client's point of view, the PUT succeeded. So I believe a 2xx status code would be right; such as 200 with a message body giving a status message.
At least using cURL as a client, it turns out that 304 works great.

Caching Github API calls

I have a general question related to caching of API calls, in this instance calls to the Github API.
Let's say I have a page in my app that shows the filenames of a repo, and the content of the README. This means that I will have to do a few API calls in order to retrieve that.
Now, let's say I want to add something like memcached in between, so I'm not doing these calls over and over, if I don't need to.
How would you normally go about this? If I don't enable a webhook on Github, I have no way of knowing whether the cache should expire. I could always make a single call to get the current sha of HEAD, and if it hadn't changed, use cache instead. But that's on a repo-level, and not on a file level.
I can imagine I could do something like that with the object-sha's, but if I need to call the API anyway to get those, it defeats the purpose of caching.
How would you go about it? I know a service like prose.io has no caching right now, but if it should, what would the approach be?
Thanks
Would just using HTTP caching be good enough for your use case? The purpose of HTTP caching is not just to provide a way of not making requests if you already have a fresh response, rather - it also enables you to quickly validate if the response you already have in cache is valid (without the server sending the complete response again if it is fresh).
Looking at GitHub API responses, I can see that GitHub is correctly setting the relevant HTTP headers (ETag, Last-modified, Cache-control).
So, you just do a GET, e.g. for:
GET https://api.github.com/users/izuzak/repos
and this returns:
200 OK
...
ETag:"df739f00c5053d12ef3c625ad6b0fd08"
Last-Modified:Thu, 14 Feb 2013 22:31:14 GMT
...
Next time - you do a GET for the same resource, but also supply the relevant HTTP caching headers so that it is actually a conditional GET:
GET https://api.github.com/users/izuzak/repos
...
If-Modified-Since:Thu, 14 Feb 2013 22:31:14 GMT
If-None-Match:"df739f00c5053d12ef3c625ad6b0fd08"
...
And lo and behold - the server returns a 304 Not modified response and your HTTP client will pull the response from its cache:
304 Not Modified
So, GitHub API does HTTP caching right and you should use it. Granted, you have to use an HTTP client that supports HTTP caching also. The best thing is that if you get a 304 Not modified response - GitHub does not decrease your remaining API calls quota. See: https://docs.github.com/en/rest/overview/resources-in-the-rest-api#conditional-requests
GitHub API also sets the Cache-Control: private, max-age=60 header, so you have 60 seconds of freshness -- which means that requests for the same resource made less than 60 seconds apart will not even be made to the server.
Your reasoning about using a single conditional GET request to a resource that surely changes if anything in the repo changed (a resource showing the sha of HEAD, for example) sounds reasonable -- since if that resource hasn't changed, then you don't have to check the individual files since they haven't surely changed.

What is the proper HTTP response code for request without mandatory fields

Consider simple case where user is deleting a post. This is simple HTTP DELETE/POST request with one mandatory field, post_id.
What should server do if post_id is not provided?
Apparently, user should never encounter this behaviour, so let's be puristic.
My first take would be 400 bad request, but spec says
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
and I'd say missing field is OK from syntax/http POV, it's application domain-specific semantic requirement.
200 OK with explanations is bad, 500 feels weird as this is request problem.
Thoughs?
400 is the correct response.
400 is not restricted to a malformed syntax from an HTTP point of view. Missing a mandatory argument is an error in the syntax defined by the application and thus a "Bad Request"
EDIT
At first it seems strange that there is no separate return code for this, but the return codes are designed to differentiate in what actions the client should take. A 400 error code means that the client should change the POST data or query string to the format defined by the application. Hence it is appropriate for this case.
In a REST scenario, the resource to be deleted should be identified by the URL, so the ID of the resource should be a part of that URL in order to properly identify it. Once that assumption is correct, then the URL either is identifying a different resource fr deletion, or it isn't (which would give a 404)
In the general case of a missing parameter, however, I often use a 403 Forbidden error. The reasoning is that the request was understood, but I'm not going to do as asked (because things are wrong). The response entity explains what is wrong, so if the response is an HTML page, the error messages are in the page. If it's a JSON or XML response, the error information is in there.
From rfc2616:
10.4.4 403 Forbidden
The server understood the request, but is refusing to fulfill it.
Authorization will not help and the request SHOULD NOT be repeated.
If the request method was not HEAD and the server wishes to make
public why the request has not been fulfilled, it SHOULD describe the
reason for the refusal in the entity. If the server does not wish to
make this information available to the client, the status code 404
(Not Found) can be used instead.