SlideShare a Scribd company logo
1 of 30
HTTP HEADERS 與 CACHE 機制
陳振揚(ANSON CHEN)
ABOUT
陳振揚 Anson Chen
Android、ASP.NET-MVC Developer
• Blog : https://anson-programming.blogspot.tw (安森瓦舍)
• 個人作品:http://play.google.com/store/apps/developer?id=CityOne
AGENDA
1. 常見的 Http Headers
2. Cache 的使用情境與最佳化
3. Code example (.NET MVC - Web API)
Code example (Android - okhttp)
https://github.com/
 Http Header 是我們在向目標 Server要求或取得內容時,依附在上
面的一些屬性或參數
 不管是使用哪一種 method,GET.POST.DELETE 還是 PUT 等等….
都可以使用 Header 來傳遞資料
 Header 分為三種-Request(請求)、Response(回應)、General(通
用)
WHAT ARE HTTP HEADERS?
名稱 範例 簡介
Date Wed, 20 Apr 2016 08:46:31
GMT
時間戳記
Cache-Control no-cache,max-age=30 表示使用何種 Cache 機制,經常使用的 directive
有:no-store , no-cache , public , private , max-age
Pragma no-cache 表示使用何種 Cache 機制(在Http 1.1後都改為參考
Cache-Control 了)
Expires -1 表示 Cache 時間(在Http 1.1後都改為參考 Cache-
Control 了)
General headers
名稱 範例 簡介
Content-Length 145698 回應的內容長度
Content-Type application/json 回應的格式,常見的有text/html(網頁)、text/plain(無格
式純文字)、application/json(JSON格式)、
application/xml(XML格式)、text/xml(XML格式)
Content-Language en 回應的語言
Content-Encoding gzip 回應的內容壓縮方式
Server Microsoft-IIS/8.5 表示何種技術的 web server
ETag "12345678" Cache 機制中的*內容驗證權杖,需要用引號("")包住
Last-Modified Wed, 20 Apr 2016
08:46:31 GMT
Cache 機制中的*時間驗證權杖,需使用 Universal Time
X-Powered-By ASP.NET 表示何種技術的 web service,特別說明一下,X 開頭系
列的 Header 通常是非標準(各個語言自定義的),雖說是
非標準,但有些 X 開頭的 Header 幾乎是很常見的
X-Version 4.0.30319 web service 當前版本
Response headers
名稱 範例 簡介
Accept */* 請求的內容的通用欄位
Accept-Charset UTF-8 請求的內容編碼
Accept-Encoding gzip, deflate 請求的內容壓縮方式
Accept-Language zh-TW,zh-CN;q=0.6,en-
US;q=0.2
請求的內容語言,q 代表請求權重(範圍值介於0~1之間,不
寫預設=1),以這個範例來說,我指定可以接受 zh-TW(繁
中)zh-CN(簡中)en-US(英文),其中又以 zh-TW 權重最高=1,
zh-CN 其次=0.6,en-US 最低=0.2
Authorization YWJjOjEyMw== 通常會放身份驗證 token,Http 1.0時的規範格式為base64
encode後的username:password,abc:123 → YWJjOjEyMw==
If-None-Match "12345678" 這裡會放上一次 Server 給的 ETag
If-Modified-Since Wed, 20 Apr 2016
08:46:31 GMT
這裡會放上一次 Server 給的 Last-Modified
Request headers
WHY CACHE?
1. 減少 request 次數
2. 降低 response 資料
• Glide
• Picasso
• Android Query
• Universal Image Loader
• ……
request
• no-cache
• no-store
• max-age = delta-seconds
• max-stale = delta-seconds
• min-fresh = delta-seconds
• no-transform
• only-if-cached
response
• public
• private
• no-store
• no-cache
• max-age = delta-seconds
• no-transform
• must-revalidate
• proxy-revalidate
• s-maxage = delta-seconds
Cache-Control directive
CACHE 的使用情境
no-store
Client Server
200 OK
Cache-Control →no-store
...
200 OK
Cache-Control →no-store
...
GET
Checking
cache
GET
max-age
Client Server
200 OK
Cache-Control →max-age=60
...
…10s
…60s
GET
Checking
cache
GET
Checking
cache
200 OK
Cache-Control →max-age=60
...
GET
no-cache + ETag
Client Server
GET
200 OK
Cache-Control →no-cache, private
ETag →“123"
...
GET
If-None-Match→“123"
Checking
cache
304 Not Modified
no-cache + Last-Modified
Client Server
GET
200 OK
Cache-Control →no-cache, publice
Last-Modified→ Sat, 01 Jan 2000 00:00:00 GMT
...
GET
If-Modified-Since → Sat, 01 Jan 2000 00:00:00 GMT
Checking
cache
304 Not Modified
CODE EXAMPLE - BACKEND
Demo code : https://bitbucket.org/ct7ct7ct7/demo-mvc_testcache
Demo page: http://demo-test-cache.azurewebsites.net
public class UserMaxAgeController : ApiController {
public HttpResponseMessage Get() {
User user = TestCacheHelper.getUser();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, user);
response.Headers.CacheControl = new CacheControlHeaderValue() {
Private = true,
MaxAge = TimeSpan.FromSeconds(10)
};
return response;
}
}
ONLY MAX-AGE
public class UserNoCacheController : ApiController {
public HttpResponseMessage Get() {
User user = TestCacheHelper.getUser();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, user);
response.Headers.ETag = new EntityTagHeaderValue(TestCacheHelper.convertToEtag(user.GetHashCode()));
response.Content.Headers.LastModified = user.LastUpdatedAt.ToUniversalTime(); //GMT
response.Headers.CacheControl = new CacheControlHeaderValue() {
Private = true,
MaxAge = TimeSpan.FromSeconds(10)
};
var modifiedSince = Request.Headers.IfModifiedSince;
var eTag = Request.Headers.IfNoneMatch.FirstOrDefault();
if (modifiedSince != null && modifiedSince.Value.ToUniversalTime().Equals(user.LastUpdatedAt)) {
response.StatusCode = HttpStatusCode.NotModified; //304
}
if (eTag != null && eTag.ToString().Equals(TestCacheHelper.convertToEtag(user.GetHashCode()))) {
response.StatusCode = HttpStatusCode.NotModified; //304
}
return response;
}
}
ETAG + LAST-MODIFIED + MAX-AGE
CODE EXAMPLE - ANDROID
Demo code : https://bitbucket.org/ct7ct7ct7/demo-android_test_cache
private final static int CACHE_SIZE = 10 * 1024 * 1024; // 10 MiB
/*reset code…*/
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY :
HttpLoggingInterceptor.Level.NONE);
okHttpClient = new OkHttpClient.Builder()
.cache(new Cache(Example1Activity.this.getExternalCacheDir(), CACHE_SIZE))
.addInterceptor(interceptor)
.build();
設定 cache size 與 directory path
EXAMPLE - 1
EXAMPLE - 2
/*reset code…*/
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Response originalResponse = chain.proceed(chain.request());
String eTag = originalResponse.headers().get("ETag");
String lastModified = originalResponse.headers().get("Last-Modified");
cacheSharedPreferences.set(originalRequest.method(),originalRequest.url().toString(),
CacheSharedPreferences.Type.E_TAG,eTag);
cacheSharedPreferences.set(originalRequest.method(),originalRequest.url().toString(),
CacheSharedPreferences.Type.LAST_MODIFIED,lastModified);
return originalResponse;
}
透過 interceptor 將 response header 中的 ETag 與 Last-Modified 記下來
EXAMPLE - 2
/*reset code…*/
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
String eTag =
cacheSharedPreferences.get(originalRequest.method(),originalRequest.url().toString(),
CacheSharedPreferences.Type.E_TAG);
String lastModified =
cacheSharedPreferences.get(originalRequest.method(),originalRequest.url().toString(),
CacheSharedPreferences.Type.LAST_MODIFIED);
Request compressedRequest = originalRequest.newBuilder()
.header("If-Modified-Since", lastModified)
.header("If-None-Match", eTag)
.build();
return chain.proceed(compressedRequest);
}
透過 interceptor 在 request header 中添加驗證權杖
If-Modified-Since 與 If-None-Match
EXAMPLE - 3
透過 interceptor 在request header中添加
Cache-Control -> max-stale
/*reset code…*/
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if (CommonUtils.checkNetwork(context) == false) {
int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
Request compressedRequest = originalRequest.newBuilder()
.header("Cache-Control", "public, max-stale=" + maxStale)
.build();
return chain.proceed(compressedRequest);
}
return chain.proceed(originalRequest);
}
OKHTTP - INTERCEPTOR
Application Interceptor
• Log handler
• Exception error handler
• Cache handler
• …..
Network Interceptor
• Log handler
• Header or parameter handler
• Exception error handler
• ……
CACHE 最佳化策略
Add Last-Modified header
1. 檢查網路狀態
1. 無→使用 cache 資料
2. 有→檢查 cache 使用期限
1. 期限內→使用 cache 資料
2. 已過期→添加驗證權杖在 header 中
發送 request 時: 收到 response 時:
1. 200→儲存資料及相關 header 至 cache 中
2. 304→使用 cache 資料
CACHE 最佳化策略
1. Cache原則:減少 request 次數 & 降低 response 資料量
2. max-age 要謹慎使用
3. 為你的 api 加上內容驗證 ( ETag ) 與時間驗證 ( Last-Modified )
CONCLUSION
• Google Developer – HTTP caching
• O3noBLOG - Cache Control 與 ETag
• HTTP 1.1 RFC 2616 - 13 Caching in HTTP
• HTTP 1.1 RFC 2616 – 14 Header Field Definitions
• Soul & Shell Blog - 初探 HTTP 1.1 Cache 機制
• Okhttp - Wiki
REFERENCE
• Email: ct7ct7ct7@gmail.com
• Facebook:https://www.facebook.com/profile.php?id=100000140471745
• LinkedIn:https://goo.gl/j2bPIl
• Blog:https://anson-programming.blogspot.tw (安森瓦舍)
• 個人作品:https://play.google.com/store/apps/developer?id=CityOne

More Related Content

What's hot

Automate with Ansible basic (3/e)
Automate with Ansible basic (3/e)Automate with Ansible basic (3/e)
Automate with Ansible basic (3/e)Chu-Siang Lai
 
twMVC#26 | 淺談 ASP.NET Caching 技術與實踐
twMVC#26 | 淺談 ASP.NET Caching 技術與實踐twMVC#26 | 淺談 ASP.NET Caching 技術與實踐
twMVC#26 | 淺談 ASP.NET Caching 技術與實踐twMVC
 
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用ByPat博客出品-高性能Web服务器nginx及相关新技术的应用
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用redhat9
 
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化Mu Chun Wang
 
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能Mu Chun Wang
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践Frank Cai
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践rewinx
 
使用Nginx轻松实现开源负载均衡
使用Nginx轻松实现开源负载均衡使用Nginx轻松实现开源负载均衡
使用Nginx轻松实现开源负载均衡cachowu
 
Parse, cloud code 介紹
Parse, cloud code 介紹Parse, cloud code 介紹
Parse, cloud code 介紹wantingj
 
lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用hugo
 
聊聊我接触的集群管理
聊聊我接触的集群管理聊聊我接触的集群管理
聊聊我接触的集群管理rfyiamcool
 
基于linux-HA 的PG高可用性
基于linux-HA 的PG高可用性基于linux-HA 的PG高可用性
基于linux-HA 的PG高可用性babyyellow li
 
反向代理工作原理及Squid简介
反向代理工作原理及Squid简介反向代理工作原理及Squid简介
反向代理工作原理及Squid简介diruser
 
高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用redhat9
 
构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 Renaun Erickson
 
Apache trafficserver
Apache trafficserverApache trafficserver
Apache trafficserverDin Dindin
 
JavaScript 80+ Programming and Optimization Skills
JavaScript 80+ Programming and Optimization SkillsJavaScript 80+ Programming and Optimization Skills
JavaScript 80+ Programming and Optimization SkillsHo Kim
 
Golang 高性能实战
Golang 高性能实战Golang 高性能实战
Golang 高性能实战rfyiamcool
 

What's hot (18)

Automate with Ansible basic (3/e)
Automate with Ansible basic (3/e)Automate with Ansible basic (3/e)
Automate with Ansible basic (3/e)
 
twMVC#26 | 淺談 ASP.NET Caching 技術與實踐
twMVC#26 | 淺談 ASP.NET Caching 技術與實踐twMVC#26 | 淺談 ASP.NET Caching 技術與實踐
twMVC#26 | 淺談 ASP.NET Caching 技術與實踐
 
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用ByPat博客出品-高性能Web服务器nginx及相关新技术的应用
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用
 
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化
 
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
使用Nginx轻松实现开源负载均衡
使用Nginx轻松实现开源负载均衡使用Nginx轻松实现开源负载均衡
使用Nginx轻松实现开源负载均衡
 
Parse, cloud code 介紹
Parse, cloud code 介紹Parse, cloud code 介紹
Parse, cloud code 介紹
 
lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用
 
聊聊我接触的集群管理
聊聊我接触的集群管理聊聊我接触的集群管理
聊聊我接触的集群管理
 
基于linux-HA 的PG高可用性
基于linux-HA 的PG高可用性基于linux-HA 的PG高可用性
基于linux-HA 的PG高可用性
 
反向代理工作原理及Squid简介
反向代理工作原理及Squid简介反向代理工作原理及Squid简介
反向代理工作原理及Squid简介
 
高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用
 
构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接
 
Apache trafficserver
Apache trafficserverApache trafficserver
Apache trafficserver
 
JavaScript 80+ Programming and Optimization Skills
JavaScript 80+ Programming and Optimization SkillsJavaScript 80+ Programming and Optimization Skills
JavaScript 80+ Programming and Optimization Skills
 
Golang 高性能实战
Golang 高性能实战Golang 高性能实战
Golang 高性能实战
 

Similar to Http Headers 與 Cache 機制(2016)

缓存技术浅谈
缓存技术浅谈缓存技术浅谈
缓存技术浅谈Robbin Fan
 
高性能网站最佳实践
高性能网站最佳实践高性能网站最佳实践
高性能网站最佳实践longhao
 
Asp.net mvc 培训
Asp.net mvc 培训Asp.net mvc 培训
Asp.net mvc 培训lotusprince
 
Php应用程序常见安全问题解析
Php应用程序常见安全问题解析Php应用程序常见安全问题解析
Php应用程序常见安全问题解析mysqlops
 
运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践Li JianYe
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践self study
 
Huangjing renren
Huangjing renrenHuangjing renren
Huangjing renrend0nn9n
 
钟志 第八期Web标准化交流会
钟志 第八期Web标准化交流会钟志 第八期Web标准化交流会
钟志 第八期Web标准化交流会Zhi Zhong
 
WEB 安全基础
WEB 安全基础WEB 安全基础
WEB 安全基础xki
 
高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用redhat9
 
高性能LAMP程序设计
高性能LAMP程序设计高性能LAMP程序设计
高性能LAMP程序设计fuchaoqun
 
香港六合彩
香港六合彩香港六合彩
香港六合彩aaveow
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型keelii
 
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410maclean liu
 
百姓网如何优化网速-Qcon2011
百姓网如何优化网速-Qcon2011百姓网如何优化网速-Qcon2011
百姓网如何优化网速-Qcon2011Yiwei Ma
 
PHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming SkillsPHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming SkillsHo Kim
 
Real time web实时信息流推送
Real time web实时信息流推送Real time web实时信息流推送
Real time web实时信息流推送yongboy
 
Real-Time Web实时信息流推送
Real-Time Web实时信息流推送Real-Time Web实时信息流推送
Real-Time Web实时信息流推送yongboy
 

Similar to Http Headers 與 Cache 機制(2016) (20)

缓存技术浅谈
缓存技术浅谈缓存技术浅谈
缓存技术浅谈
 
高性能网站最佳实践
高性能网站最佳实践高性能网站最佳实践
高性能网站最佳实践
 
Asp.net mvc 培训
Asp.net mvc 培训Asp.net mvc 培训
Asp.net mvc 培训
 
Php应用程序常见安全问题解析
Php应用程序常见安全问题解析Php应用程序常见安全问题解析
Php应用程序常见安全问题解析
 
运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
Huangjing renren
Huangjing renrenHuangjing renren
Huangjing renren
 
钟志 第八期Web标准化交流会
钟志 第八期Web标准化交流会钟志 第八期Web标准化交流会
钟志 第八期Web标准化交流会
 
WEB 安全基础
WEB 安全基础WEB 安全基础
WEB 安全基础
 
高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用
 
高性能LAMP程序设计
高性能LAMP程序设计高性能LAMP程序设计
高性能LAMP程序设计
 
香港六合彩
香港六合彩香港六合彩
香港六合彩
 
ev2oik
ev2oikev2oik
ev2oik
 
香港六合彩
香港六合彩香港六合彩
香港六合彩
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型
 
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410
 
百姓网如何优化网速-Qcon2011
百姓网如何优化网速-Qcon2011百姓网如何优化网速-Qcon2011
百姓网如何优化网速-Qcon2011
 
PHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming SkillsPHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming Skills
 
Real time web实时信息流推送
Real time web实时信息流推送Real time web实时信息流推送
Real time web实时信息流推送
 
Real-Time Web实时信息流推送
Real-Time Web实时信息流推送Real-Time Web实时信息流推送
Real-Time Web实时信息流推送
 

Http Headers 與 Cache 機制(2016)

  • 1. HTTP HEADERS 與 CACHE 機制 陳振揚(ANSON CHEN)
  • 2. ABOUT 陳振揚 Anson Chen Android、ASP.NET-MVC Developer • Blog : https://anson-programming.blogspot.tw (安森瓦舍) • 個人作品:http://play.google.com/store/apps/developer?id=CityOne
  • 3. AGENDA 1. 常見的 Http Headers 2. Cache 的使用情境與最佳化 3. Code example (.NET MVC - Web API) Code example (Android - okhttp)
  • 5.
  • 6.  Http Header 是我們在向目標 Server要求或取得內容時,依附在上 面的一些屬性或參數  不管是使用哪一種 method,GET.POST.DELETE 還是 PUT 等等…. 都可以使用 Header 來傳遞資料  Header 分為三種-Request(請求)、Response(回應)、General(通 用) WHAT ARE HTTP HEADERS?
  • 7. 名稱 範例 簡介 Date Wed, 20 Apr 2016 08:46:31 GMT 時間戳記 Cache-Control no-cache,max-age=30 表示使用何種 Cache 機制,經常使用的 directive 有:no-store , no-cache , public , private , max-age Pragma no-cache 表示使用何種 Cache 機制(在Http 1.1後都改為參考 Cache-Control 了) Expires -1 表示 Cache 時間(在Http 1.1後都改為參考 Cache- Control 了) General headers
  • 8. 名稱 範例 簡介 Content-Length 145698 回應的內容長度 Content-Type application/json 回應的格式,常見的有text/html(網頁)、text/plain(無格 式純文字)、application/json(JSON格式)、 application/xml(XML格式)、text/xml(XML格式) Content-Language en 回應的語言 Content-Encoding gzip 回應的內容壓縮方式 Server Microsoft-IIS/8.5 表示何種技術的 web server ETag "12345678" Cache 機制中的*內容驗證權杖,需要用引號("")包住 Last-Modified Wed, 20 Apr 2016 08:46:31 GMT Cache 機制中的*時間驗證權杖,需使用 Universal Time X-Powered-By ASP.NET 表示何種技術的 web service,特別說明一下,X 開頭系 列的 Header 通常是非標準(各個語言自定義的),雖說是 非標準,但有些 X 開頭的 Header 幾乎是很常見的 X-Version 4.0.30319 web service 當前版本 Response headers
  • 9. 名稱 範例 簡介 Accept */* 請求的內容的通用欄位 Accept-Charset UTF-8 請求的內容編碼 Accept-Encoding gzip, deflate 請求的內容壓縮方式 Accept-Language zh-TW,zh-CN;q=0.6,en- US;q=0.2 請求的內容語言,q 代表請求權重(範圍值介於0~1之間,不 寫預設=1),以這個範例來說,我指定可以接受 zh-TW(繁 中)zh-CN(簡中)en-US(英文),其中又以 zh-TW 權重最高=1, zh-CN 其次=0.6,en-US 最低=0.2 Authorization YWJjOjEyMw== 通常會放身份驗證 token,Http 1.0時的規範格式為base64 encode後的username:password,abc:123 → YWJjOjEyMw== If-None-Match "12345678" 這裡會放上一次 Server 給的 ETag If-Modified-Since Wed, 20 Apr 2016 08:46:31 GMT 這裡會放上一次 Server 給的 Last-Modified Request headers
  • 10. WHY CACHE? 1. 減少 request 次數 2. 降低 response 資料 • Glide • Picasso • Android Query • Universal Image Loader • ……
  • 11. request • no-cache • no-store • max-age = delta-seconds • max-stale = delta-seconds • min-fresh = delta-seconds • no-transform • only-if-cached response • public • private • no-store • no-cache • max-age = delta-seconds • no-transform • must-revalidate • proxy-revalidate • s-maxage = delta-seconds Cache-Control directive
  • 13. no-store Client Server 200 OK Cache-Control →no-store ... 200 OK Cache-Control →no-store ... GET Checking cache GET
  • 14. max-age Client Server 200 OK Cache-Control →max-age=60 ... …10s …60s GET Checking cache GET Checking cache 200 OK Cache-Control →max-age=60 ... GET
  • 15. no-cache + ETag Client Server GET 200 OK Cache-Control →no-cache, private ETag →“123" ... GET If-None-Match→“123" Checking cache 304 Not Modified
  • 16. no-cache + Last-Modified Client Server GET 200 OK Cache-Control →no-cache, publice Last-Modified→ Sat, 01 Jan 2000 00:00:00 GMT ... GET If-Modified-Since → Sat, 01 Jan 2000 00:00:00 GMT Checking cache 304 Not Modified
  • 17. CODE EXAMPLE - BACKEND Demo code : https://bitbucket.org/ct7ct7ct7/demo-mvc_testcache Demo page: http://demo-test-cache.azurewebsites.net
  • 18. public class UserMaxAgeController : ApiController { public HttpResponseMessage Get() { User user = TestCacheHelper.getUser(); HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, user); response.Headers.CacheControl = new CacheControlHeaderValue() { Private = true, MaxAge = TimeSpan.FromSeconds(10) }; return response; } } ONLY MAX-AGE
  • 19. public class UserNoCacheController : ApiController { public HttpResponseMessage Get() { User user = TestCacheHelper.getUser(); HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, user); response.Headers.ETag = new EntityTagHeaderValue(TestCacheHelper.convertToEtag(user.GetHashCode())); response.Content.Headers.LastModified = user.LastUpdatedAt.ToUniversalTime(); //GMT response.Headers.CacheControl = new CacheControlHeaderValue() { Private = true, MaxAge = TimeSpan.FromSeconds(10) }; var modifiedSince = Request.Headers.IfModifiedSince; var eTag = Request.Headers.IfNoneMatch.FirstOrDefault(); if (modifiedSince != null && modifiedSince.Value.ToUniversalTime().Equals(user.LastUpdatedAt)) { response.StatusCode = HttpStatusCode.NotModified; //304 } if (eTag != null && eTag.ToString().Equals(TestCacheHelper.convertToEtag(user.GetHashCode()))) { response.StatusCode = HttpStatusCode.NotModified; //304 } return response; } } ETAG + LAST-MODIFIED + MAX-AGE
  • 20. CODE EXAMPLE - ANDROID Demo code : https://bitbucket.org/ct7ct7ct7/demo-android_test_cache
  • 21. private final static int CACHE_SIZE = 10 * 1024 * 1024; // 10 MiB /*reset code…*/ HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE); okHttpClient = new OkHttpClient.Builder() .cache(new Cache(Example1Activity.this.getExternalCacheDir(), CACHE_SIZE)) .addInterceptor(interceptor) .build(); 設定 cache size 與 directory path EXAMPLE - 1
  • 22. EXAMPLE - 2 /*reset code…*/ @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); Response originalResponse = chain.proceed(chain.request()); String eTag = originalResponse.headers().get("ETag"); String lastModified = originalResponse.headers().get("Last-Modified"); cacheSharedPreferences.set(originalRequest.method(),originalRequest.url().toString(), CacheSharedPreferences.Type.E_TAG,eTag); cacheSharedPreferences.set(originalRequest.method(),originalRequest.url().toString(), CacheSharedPreferences.Type.LAST_MODIFIED,lastModified); return originalResponse; } 透過 interceptor 將 response header 中的 ETag 與 Last-Modified 記下來
  • 23. EXAMPLE - 2 /*reset code…*/ @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); String eTag = cacheSharedPreferences.get(originalRequest.method(),originalRequest.url().toString(), CacheSharedPreferences.Type.E_TAG); String lastModified = cacheSharedPreferences.get(originalRequest.method(),originalRequest.url().toString(), CacheSharedPreferences.Type.LAST_MODIFIED); Request compressedRequest = originalRequest.newBuilder() .header("If-Modified-Since", lastModified) .header("If-None-Match", eTag) .build(); return chain.proceed(compressedRequest); } 透過 interceptor 在 request header 中添加驗證權杖 If-Modified-Since 與 If-None-Match
  • 24. EXAMPLE - 3 透過 interceptor 在request header中添加 Cache-Control -> max-stale /*reset code…*/ @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); if (CommonUtils.checkNetwork(context) == false) { int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale Request compressedRequest = originalRequest.newBuilder() .header("Cache-Control", "public, max-stale=" + maxStale) .build(); return chain.proceed(compressedRequest); } return chain.proceed(originalRequest); }
  • 25. OKHTTP - INTERCEPTOR Application Interceptor • Log handler • Exception error handler • Cache handler • ….. Network Interceptor • Log handler • Header or parameter handler • Exception error handler • ……
  • 27. 1. 檢查網路狀態 1. 無→使用 cache 資料 2. 有→檢查 cache 使用期限 1. 期限內→使用 cache 資料 2. 已過期→添加驗證權杖在 header 中 發送 request 時: 收到 response 時: 1. 200→儲存資料及相關 header 至 cache 中 2. 304→使用 cache 資料 CACHE 最佳化策略
  • 28. 1. Cache原則:減少 request 次數 & 降低 response 資料量 2. max-age 要謹慎使用 3. 為你的 api 加上內容驗證 ( ETag ) 與時間驗證 ( Last-Modified ) CONCLUSION
  • 29. • Google Developer – HTTP caching • O3noBLOG - Cache Control 與 ETag • HTTP 1.1 RFC 2616 - 13 Caching in HTTP • HTTP 1.1 RFC 2616 – 14 Header Field Definitions • Soul & Shell Blog - 初探 HTTP 1.1 Cache 機制 • Okhttp - Wiki REFERENCE
  • 30. • Email: ct7ct7ct7@gmail.com • Facebook:https://www.facebook.com/profile.php?id=100000140471745 • LinkedIn:https://goo.gl/j2bPIl • Blog:https://anson-programming.blogspot.tw (安森瓦舍) • 個人作品:https://play.google.com/store/apps/developer?id=CityOne