octokit/octokit.net — pull request #369 by niik (2014-02-11 23:06:26+00:00)
Title: Support ETags in the HTTP-layer

There's an ongoing [discussion](https://github.com/octokit/octokit.net/issues/352) about ETag support in Octokit. My take on this is that Octokit should just if possible defer to the http-level caching layer provided by WinInet. It makes it completely transparent to Octokit and it has the added benefit of supporting all of the other http headers that deal with caching (well, ```If-Modified-Since``` at least).

Doing it in the layer below means no custom cache repositories, no sqlite, no custom file-level cache storage and/or in-memory storage (and the problems associated with that) and apps relying on it won't have to provide a place or provider to store/cache.

In order to utilize the WinInet cache **I needed to add a reference to** ```System.Net.Http.WebRequest```. This might throw a wrench in all of this since that's not supported in WinRT. It shouldn't be too hard to compile this conditionally for .NET 4.5 and keep on going without ETags in WinRT.

Consider it a PoC at least.

### Proof request and response (with stripped tokens, of course)

#### Initial request with no cache

```
GET /user HTTP/1.1
Accept: application/vnd.github.v3+json; charset=utf-8
User-Agent: niik-etag-test/0.1 (Win32NT 6.2.9200; amd64; sv-SE; Octokit 0.1.8)
Authorization: Token secret
Accept-Encoding: gzip
Host: api.github.com
Connection: Keep-Alive
```
```
HTTP/1.1 200 OK
Server: GitHub.com
Date: Tue, 11 Feb 2014 22:54:40 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Status: 200 OK
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4996
X-RateLimit-Reset: 1392160209
Cache-Control: private, max-age=60, s-maxage=60
Last-Modified: Tue, 11 Feb 2014 16:18:43 GMT
ETag: "8f0904628f0be22511cd822a05ab3846"
X-OAuth-Scopes: user, public_repo, repo, gist
X-Accepted-OAuth-Scopes: repo
Vary: Accept, Authorization, Cookie, X-GitHub-OTP
X-GitHub-Media-Type: github.v3; format=json
X-Content-Type-Options: nosniff
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
Access-Control-Allow-Origin: *
X-GitHub-Request-Id: 4E522CC5:149D:92F550:52FAAA2F
Vary: Accept-Encoding
Content-Encoding: gzip
```

#### Second request

```
GET /user HTTP/1.1
Accept: application/vnd.github.v3+json; charset=utf-8
User-Agent: niik-etag-test/0.1 (Win32NT 6.2.9200; amd64; sv-SE; Octokit 0.1.8)
Authorization: Token secret
Accept-Encoding: gzip
Host: api.github.com
If-None-Match: "8f0904628f0be22511cd822a05ab3846"
If-Modified-Since: Tue, 11 Feb 2014 16:18:43 GMT
Connection: Keep-Alive
```

Response
```
HTTP/1.1 304 Not Modified
Server: GitHub.com
Date: Tue, 11 Feb 2014 22:43:04 GMT
Status: 304 Not Modified
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4996
X-RateLimit-Reset: 1392160209
Cache-Control: private, max-age=60, s-maxage=60
Last-Modified: Tue, 11 Feb 2014 16:18:43 GMT
ETag: "8f0904628f0be22511cd822a05ab3846"
X-Content-Type-Options: nosniff
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
Access-Control-Allow-Origin: *
X-GitHub-Request-Id: 4E522CC5:22DD:AB3E81:52FAA777
Vary: Accept-Encoding
```