[HAR][1](HTTP Archive),是一个用来储存HTTP请求/响应信息的通用文件格式,基于[JSON]。这个格式的出现可以使HTTP监测工具以一种通用的格式导出所收集的数据,这些数据可以被其他支持HAR的HTTP[分析工具](包括[Firebug],[httpwatch],[Fiddler]等)所使用,来分析网站的性能瓶颈。目前HAR规范最新版本为[HAR 1.2][1]。HAR文件必须是UTF-8编码,有无BOM无所谓。
###HAR数据结构:
一个HAR文件就是一个JSON对象,如下:
{
"log": {
"version" : "1.2",
"creator" : {},
"browser" : {},
"pages": [],
"entries": [],
"comment": ""
}
}
注:每个页面对应一个 对象,每个HTTP请求对应一个对象。如果HTTP的监测分析工具不能把请求按照page分组,那么为空。
###<creator> & <browser>
这两个对象的结构是一样的
"creator": {
"name": "Firebug",
"version": "1.6",
"comment": "",
}
"browser": {
"name": "Firefox",
"version": "3.6",
"comment": ""
}
###<pages>
这个对象保存了页面列表,格式如下:
"pages": [
{
"startedDateTime": "2009-04-16T12:07:25.123+01:00",
"id": "page_0",
"title": "Test Page",
"pageTimings": {...},
"comment": ""
}
]
###<pageTimings>
这个对象描述了在页面加载过程中各个事件发生的时间点。所有的时间都是以毫秒计算的。如果有的时间无法计算出来,那么相应字段置为-1。
"pageTimings": [
{
"onContentLoad": 1720,
"onLoad": 2500,
"comment": ""
}
]
由于不同浏览器实现不一样,onContentLoad属性可能代表DOMContentLoad事件触发,也可能代表document.readyState等于interactive。
###<entries>
这个对象包含了一个数组,数组中每个元素的内容就是一个HTTP请求的相应信息。用startedDateTime来排序的话可以加快数据导出的速度。HAR分析工具要确保此数组是按照startedDateTime排序的。
"entries": [
{
"pageref": "page_0",
"startedDateTime": "2009-04-16T12:07:23.596Z",
"time": 50,
"request": {...},
"response": {...},
"cache": {...},
"timings": {},
"serverIPAddress": "10.0.0.1",
"connection": "52492",
"comment": ""
}
]
###<request>
这个对象包含了请求的详细信息
"request": {
"method": "GET",
"url": "http://www.example.com/path/?param=value",
"httpVersion": "HTTP/1.1",
"cookies": [],
"headers": [],
"queryString" : [],
"postData" : {},
"headersSize" : 150,
"bodySize" : 0,
"comment" : "",
}
###<response>
这个对象包含响应的详细信息。
"response": {
"status": 200,
"statusText": "OK",
"httpVersion": "HTTP/1.1",
"cookies": [],
"headers": [],
"content": {},
"redirectURL": ",
"headersSize" : 160,
"bodySize" : 850,
"comment" : ""
}
###<cookies>
这个对象包含了所有的cookie(在和中被使用)。
"cookies": [
{
"name": "TestCookie",
"value": "Cookie Value",
"path": "/",
"domain": "www.janodvarko.cz",
"expires": "2009-07-24T19:20:30.123+02:00",
"httpOnly": false,
"secure": false,
"comment": "",
}
]
###<headers>
这个对象包含了所有的header(可以在lt;request>and<response>中使用)
"headers": [
{
"name": "Accept-Encoding",
"value": "gzip,deflate",
"comment": ""
},
{
"name": "Accept-Language",
"value": "en-us,en;q=0.5",
"comment": ""
}
]
###<queryString>
这个对象包含了查询字符串中所有的paramter-value对(嵌在对象中)。
"queryString": [
{
"name": "param1",
"value": "value1",
"comment": ""
},
{
"name": "param1",
"value": "value1",
"comment": ""
}
]
###<postData>
这个对象描述了POST的数据(嵌在对象中)
"postData": {
"mimeType": "multipart/form-data",
"params": [],
"text" : "plain posted data",
"comment": ""
}
###<params>
POST请求参数列表(嵌在 对象中)
"params": [
{
"name": "paramName",
"value": "paramValue",
"fileName": "example.pdf",
"contentType": "application/pdf",
"comment": ""
}
]
###<content>
这个对象描述了响应内容的详细情况(嵌在 对象中)
"content": {
"size": 33,
"compression": 0,
"mimeType": "text/html; charset="utf-8",
"text": "n",
"comment": ""
}
在设置text字段之前,HTTP响应内容已经完成了解码(decompressed & unchunked),然后把原始字符编码转换成UTF-8。字段内容同样可以使用base64进行编码,但是HAR工具必须有解码base64的能力。对字段编码还可以把二进制内容包含进HAR文件中。
这有另一个例子,原始响应内容是:
"content": {
"size": 33,
"compression": 0,
"mimeType": "text/html; charset="utf-8",
"text": "PGh0bWw+PGhlYWQ+PC9oZWFkPjxib2R5Lz48L2h0bWw+XG4=",
"encoding": "base64",
"comment": ""
}
###<cache>
这个对象包含了命中的浏览器缓存信息
"cache": {
"beforeRequest": {},
"afterRequest": {},
"comment": ""
}
如果缓存信息为空,那么对象如下(或者也可以直接删掉cache这个字段):
"cache": {}
如果在请求之前,缓存信息不可用,并且在请求之后也没有对内容进行缓存,那么对象如下:
"cache": {
"afterRequest": null
}
如果在请求前后都没有缓存存在,那么对象如下:
"cache": {
"beforeRequest": null,
"afterRequest": null
}
以下对象表示请求之前没有缓存,但是在请求后,下载的内容被存在了本地缓存中。
"cache": {
"beforeRequest": null,
"afterRequest": {
"expires": "2009-04-16T15:50:36",
"lastAccess": "2009-16-02T15:50:34",
"eTag": ",
"hitCount": 0,
"comment": ""
}
}
beforeRequest和afterRequest对象使用以下相同的结构:
"beforeRequest": {
"expires": "2009-04-16T15:50:36",
"lastAccess": "2009-16-02T15:50:34",
"eTag": ",
"hitCount": 0,
"comment": "“”
}
###<timings>
这个对象描述了请求/响应过程的各个阶段。时间都是以毫秒为单位。
"timings": {
"blocked": 0,
"dns": -1,
"connect": 15,
"send": 20,
"wait": 38,
"receive": 12,
"ssl": -1,
"comment": ""
}
send,wait,receive时间是必须提供的,并且不能为负数。导出工具如果不能提供blocked,dns,connect和ssl等时间,那么这些时间可以被忽略。如果工具可以提供这些时间,但是不适用的话,可以把这些值设置为-1。 例如,当请求使用了一个存在的连接,connect会被置为-1。
一个请求所花的时间等于这些时间的和,不包括值为-1的。
entry.time == entry.timings.blocked + entry.timings.dns + entry.timings.connect + entry.timings.send + entry.timings.wait + entry.timings.receive
###自定义字段
HAR规范允许自定义字段,但是要遵循如下规则:
###版本格式
HAR规范的版本号有如下规则:
<主版本号>.<副版本号> 主版本号表示规范的向后兼容性,副版本号表示增量修改。所以,任何向后兼容的修改都会增加副版本号。如果一个存在的字段被废弃了,那么主版本号要增加(例如2.0)。 Examples: 1.2 -> 1.3(向后兼容) 1.111 -> 1.112 (向后兼容) 1.5 -> 2.0 (2.0不兼容1.5) 如果HAR工具只支持HAR1.1,那么以下的代码可以被用来检测不被兼容的版本。 if (majorVersion != 1 || minorVersion < 1) { throw “Incompatible version”; } 这个例子中,如果被解析文件的版本为0.8,0.9,1.0等,那么工具会抛出异常,但是1.1, 1.2, 1.112等版本可以被解析。2.x版本直接拒绝解析。 原文:[http://www.softwareishard.com/blog/har-12-spec/](http://www.softwareishard.com/blog/har-12-spec/) Google Group: [http://groups.google.com/group/http-archive-specification【需翻墙】](http://groups.google.com/group/http-archive-specification) [JSON]: http://www.ietf.org/rfc/rfc4627.txt "JSON" [分析工具]: http://www.softwareishard.com/blog/har-adopters/ "分析工具" [Firebug]: http://getfirebug.com/ "Firebug" [httpwatch]: http://www.httpwatch.com/ "httpwatch" [Fiddler]: http://www.fiddler2.com/fiddler2/ "Fiddler" [1]: http://www.softwareishard.com/blog/har-12-spec/ "har-12-spec" 副版本号>主版本号> (完)