MVC Framework Browser Caching Issue with RC1 - asp.net-mvc

In my latest project which is in RC1 I have noticed that I have this browser caching issue that I just can't shake. This is what my header looks like
HTTP/1.1 200 OK
Date: Tue, 03 Mar 2009 15:11:34 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
X-AspNetMvc-Version: 1.0
Cache-Control: private
Expires: Tue, 03 Mar 2009 15:11:34 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 4614
Now technically if this is private it shouldn't have an expiration date on the content right? I've tried no-cache as well with the same results. Anybody have any experience with this particular issue?

Cache-Control: private only specifies that the response is only intended for a single user and should not be stored in a shared cache (say, in a proxy) and used to serve requests for other users. I don't see anything in the protocol documentation that would preclude the use of an Expires header with a value. In fact, it seems a perfectly reasonable thing to say "use this for subsequent requests for this user only, but not after this time." There are other values for Cache-Control where Expires may not make sense, but I believe that the protocol has a means for disambiguating between conflicting headers (See section 4 of the protocol docs).
Quoting from Section 16.2 of the HTTP 1.1 protocol docs:
private
Indicates that all or part of the response message is intended for
a single user and MUST NOT be cached by a shared cache. This
allows an origin server to state that the specified parts of the
response are intended for only one user and are not a valid
response for requests by other users. A private (non-shared)
cache MAY cache the response.
Note: This usage of the word private only controls where the
response may be cached, and cannot ensure the privacy of the
message content.

There's no reason why private content can't be cached, its just that it should only be cached by the browser in the current users context, it should not be cached server side or by other caches such as a proxy server.

Related

Chunked Transfer Encoding not working, response completely buffered by GFE

Cloud Run / the "Google Frontend" seems to completely buffer responses from a Cloud Run application, even when using chunked transfer encoding for the response. This is bad for incremental rendering.
I have a Java web app based on com.sun.net.HttpServer which supports chunked encoding for the response. Especially flushing the output stream creates a chunk, so I can do:
write response line
flush
compute for 10s
write more response lines
Locally, this results in a chunked response:
HTTP/1.1 200 OK
Date: Sat, 07 Mar 2020 17:08:10 GMT
Transfer-encoding: chunked
Content-type: text/plain;charset=utf-8
1c
<first output>
14
<next output>
17
<next output>
0
Using curl, I can see the output appear incrementally.
In contrast, when deploying the same app in Cloud Run, the response gets fully buffered and returned in full, no matter how long the pause (many seconds), how many chunks or how much content is returned (I've tested up to several megabytes):
curl -v https://...
< HTTP/2 200
< content-type: text/plain;charset=utf-8
< x-cloud-trace-context: 3872abb809e97a76298f4c46b9217656;o=1
< date: Sat, 07 Mar 2020 17:18:48 GMT
< server: Google Frontend
< content-length: 2450359
(Example has 50k chunks!)
Is there a way to have the GFE pass through the chunked encoding?
Cloud Run does not support streaming responses where data is sent in incremental chunks to the client while a request is being processed. All data from your service is sent as a single HTTP response.
Also, the 'Content-Length' and 'Transfer-Encoding' headers are removed from responses your application may serve. Those headers are then added by the Google Front End and finally, the response is served.
Source of information:
1) Internal conversations with the Cloud Run engineering team.
2) Google Cloud Security Whitepaper that details the GFE (Google Frontend) which sits in front of Cloud Run Managed.
https://services.google.com/fh/files/misc/security_whitepapers_march2018.pdf

Get/Set cookie while using dart web app http

I am working on an AngularDart web app.
I need to retrieve a cookie from a json server that works with cookie authentication.
So on connection, I have to post credentials in body, then the server give me back a response containing the cookie.
import 'package:http/browser_client.dart';
Response response = await _http.post(_loginUrl, body: json.encode(datas));
The response is ok, I get 200 statuscode and the json response from the server, but impossible to find the cookie while in Postman I do get it.
So how to retrieve cookies from response?
EDIT: Informations returned from the server to postman :
ASP.NET_SessionId=03e95c12-6098-4f07-b9a9-054377b0311d; path=/; domain=.www.xxxxx.fr; HttpOnly; Expires=Tue, 19 Jan 2038 03:14:07 GMT;
EDIT: This is the raw headers from the server to the Dart app :
t=1462088 [st=142] HTTP_TRANSACTION_READ_RESPONSE_HEADERS
--> HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.5
Set-Cookie: ASP.NET_SessionId=f229a77e-5eb6-4c6c-9c57-9280947cb434; path=/; HttpOnly
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Date: Fri, 30 Nov 2018 09:52:50 GMT
Content-Length: 22443
So the server sends back the cookie, but the browser does not seem to save it ...
Ok so finally, a problem was found on the API server, the developer did not check correctly the cookie. Generally, only one cookie is sent to this server, so in its code, it took the first... But from a browser, severals cookie can be sent at the same time. So he made some change to check the good one...
Postman should show that this is an HttpOnly cookie that can't be read from JavaScript (and the same applies for Dart of course)
See also https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies
The cookie will be sent back to the server automatically therefore there is no need to read it from JavaScript. Allowing access from JavaScript only undermines security.

Get HTTP Status Description from RestKit .20.3

I'm able to get the status code just fine, but I'm looking for a way to get the "HTTP Reason Phrase" from the response. I've spelunked through RKObjectRequestOperation and don't see it anywhere. I feel like I'm just missing it. Is this something that's supported by RestKit?
In my particular case, the service I'm hitting is sending this back:
HTTP/1.1 409 A user with this phone number already exists
Cache-Control: private
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Tue, 24 Feb 2015 22:13:21 GMT
Content-Length: 0
I'm trying to get at the "A user with this phone number already exists" bit.
Thanks very much in advance.
This isn't a RestKit thing, it's a URL handling system thing as it is the HTTP underpinnings that RestKit is built on top of.
So it should be provided by localizedStringForStatusCode: from the NSHTTPURLResponse that you can ferret out of the RestKit operation.
To be honest I've never had cause to use it so I'm not sure if it's purely a local client lookup from the returned status code or if it does link to any server response data. As the docs reference RFC 2616 it should pick up the text if the server sends it out...

MVC's HTTP Caching - Last-Modified response header always equals Date

I'm not fully understanding how .NET MVC's HTTP caching works because it doesn't seem like it's actually retrieving cached resource files. I'm thinking I need to add some additional code somewhere...
First, let's take a look at how I've set up HTTP caching on static content (ie. images). In my web.config, I have the following:
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseExpires" httpExpires="Tue, 19 Jan 2038 03:14:07 GMT" />
</staticContent>
</system.webServer>
This results in the images in my application to appear to be caching properly. When I look at the response headers for an image, I see this (removed unnecessary headers):
Date:Thu, 27 Feb 2014 16:27:48 GMT
ETag:"086f8d199a4ce1:0"
Expires:Tue, 19 Jan 2038 03:14:07 GMT
Last-Modified:Thu, 29 Aug 2013 09:26:20 GMT
I'm seeing an ETag value which is good and my Expires is what it should be. Additionally, the Last-Modified date is in the past. I understand the Last-Modified date to be the date the server was last asked for that file.
Now let's look at the response headers for a javascript file that has been optimized by MVC. As a reminder, this article states that "Bundles set the HTTP Expires Header one year from when the bundle is created."
Cache-Control:public
Date:Thu, 27 Feb 2014 16:44:16 GMT
Expires:Fri, 27 Feb 2015 16:44:16 GMT
Last-Modified:Thu, 27 Feb 2014 16:44:16 GMT
Vary:User-Agent
The Response Headers for the MVC cached file is missing the ETag for one. There is a Cache-Control value of "public" which wasn't present on the static content response header. Lastly, the Expires is 1 year after the Last-Modified date which is correct, but the Last-Modified date is always the same as the Date value. These response headers to me seem like what they'd be when a resource is requested from the server for the first time and cached, not when it's been subsequently requested and retrieved from cache.
Thanks in advance for any insight.
UPDATE: It actually seems to be caching in IE. The Last-Modified date on subsequent requests remains a value in the past. I'm not seeing this in FF or Chrome, though. I confirmed that in both of those browsers, I haven't disabled caching. What gives?
First of all, system.webServer/staticContent/clientCache is for static resources (files) only. So it works if you directly access pictures.
A bundle is a dynamic resource (a handler is generating the content). That is why the configuration directive does not apply.
Secondly, using ETag, Expires, Last-Modified are three different caching techniques. You should not use both techniques together as they work in a different way.
Expires tells the browser to keep the file in cache until a specified date. The browser will never call the server until that date.
ETag is a dynamic cache mechanism. The browser will always call the server but the server may not respond with the content if it has not changed.
Last-Modified is an ancient dynamic cache mechanism. It work the same way as ETag but is has a problematic requirement of exposing the correct modification date. Which is not a easy thing to find when creating dynamic content.
I think that combining multiple techniques should be reserved for well thought cases only. See this answer for details.
You may want to read the basics: HTTP caching
And then for your issue, I am not sure why so many header are exposed by your app. The presence of Last-Modified on a bundle is strange to explain. A bundle is a virtual thing that exposes various files combined as one. So it has no real date of last modification. Are you using extra caching code/modules?

Is there a way to get Indy to accept expired cookies?

Using Delphi XE2 Update 4 and Indy components 10.5.8.0 as installed by Delphi.
A website I am trying to work with is deliberately sending me a cookie with an already expired date for security reasons. It is deliberate on their part and I have to live with it and other developers working with them have managed to do so.
The server response to my IdHTTP.Get() looks like this:
Recv 8/30/2012 3:06:15 PM: HTTP/1.1 200 OK<EOL>
Date: Thu, 30 Aug 2012 19:06:35 GMT<EOL>
Server: Apache/2.2.3 (CentOS)<EOL>
X-Powered-By: PHP/5.1.6<EOL>
Set-Cookie: dati=eJxLtDKxqi62MrdSykyJLy1OLVKyLrYytVIyNjcxtISyc%2FLTM%2FNAbKAqt4CgYJfUMhDPEqinOB4omZ6aAuIbWilFgmkDkGGpeSWZaZkQ8wyNrZTSchKLMwryM%2FNK4ouKlaxrAYdvJUQ%3D;
expires=Thu, 01-Jan-1970 00:03:00 GMT<EOL>
Content-Length: 16<EOL>
Connection: close<EOL>
Content-Type: text/plain;; charset=ISO-8859-1<EOL><EOL>
0 24.141.251.145
Note the 1970 expiry! I have been using Indy for all of 3 days now and as near as I can tell this attempt to create a cookie is simply ignored by IdHttp and the associated CookieManager.
Assuming I need to receive and use the cookie anyway what would be the proper approach to capture it, or should I just run away screaming now? I have a lot of Delphi experience but this is my first foray into the wonderful world of internet connectivity and this expired-on-arrival cookie business is leaving me scratching my head!
Sending an expired cookie is how a webserver deletes a cookie on the client end. Indy's cookie manager supports that. When it receives a cookie, it will delete any existing cookie of the same name/domain/path trio and will then discard the new cookie if it is already expired. This is hard-coded behavior.
If, for whatever reason, you have to keep the expired cookie (which does not make sense as no webclient should ever do that), you will have to use the TIdCookieManager.OnNewCookie event to alter the expiration of the cookie after it is parsed by TIdCookie but before it is processed by TIdCookieManager. You can set the TIdCookie.Expires property to a future date, or to 0.0 to disable its expiration. You will have to do this anyway, as TIdCookieManager implements cleanup of expired cookies (which is triggered whenever TIdHTTP asks for cookies to send in an HTTP request), so if you don't alter the expiration then the cookie will just get discarded anyway at a later time.

Resources