This is an automated email from the ASF dual-hosted git repository.
eze pushed a commit to branch 9.2.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/9.2.x by this push:
new 515ae979dc Add Sphinx documentation for statichit plugin. (#11389)
(#11979)
515ae979dc is described below
commit 515ae979dc47db5f5a8319d4217398367a1cc25b
Author: Evan Zelkowitz <[email protected]>
AuthorDate: Wed Jan 22 15:43:00 2025 -0700
Add Sphinx documentation for statichit plugin. (#11389) (#11979)
* Add Sphinx documentation for statichit plugin. (#11389)
* Add Sphinx documentation for statichit plugin.
Also remove obsolete readme file for statichit.
* Improve Au test for statichit plugin.
(cherry picked from commit e226cc7fd16fb3c63143cb16c0f2010ddd8e25fd)
* Add missing autest files for statichit
---------
Co-authored-by: Walt Karas <[email protected]>
---
doc/admin-guide/plugins/index.en.rst | 4 +
doc/admin-guide/plugins/statichit.en.rst | 117 ++++++
plugins/experimental/statichit/README.md | 38 --
tests/gold_tests/pluginTest/statichit/empty.txt | 0
.../gold_tests/pluginTest/statichit/small_body.txt | 1 +
.../pluginTest/statichit/statichit.replay.yaml | 237 +++++++++++++
.../pluginTest/statichit/statichit.test.py | 111 ++++++
.../gold_tests/pluginTest/statichit/story_16.json | 395 +++++++++++++++++++++
8 files changed, 865 insertions(+), 38 deletions(-)
diff --git a/doc/admin-guide/plugins/index.en.rst
b/doc/admin-guide/plugins/index.en.rst
index b0218bab9d..bc4a06f4ae 100644
--- a/doc/admin-guide/plugins/index.en.rst
+++ b/doc/admin-guide/plugins/index.en.rst
@@ -174,6 +174,7 @@ directory of the |TS| source tree. Experimental plugins can
be compiled by passi
Parent Select <parent_select.en>
Rate Limit <rate_limit.en>
Remap Stats <remap_stats.en>
+ Static Hit <statichit.en>
URI Signing <uri_signing.en>
Legacy Signed URLs <url_sig.en>
Slice <slice.en>
@@ -260,6 +261,9 @@ directory of the |TS| source tree. Experimental plugins can
be compiled by passi
This remap plugin allows the administrator to easily setup remotely
controlled ``PURGE`` for the content of an entire remap rule.
+:doc:`Static Hit <statichit.en>`
+ Serve static content from proxy's local filesystem.
+
:doc:`URI Signing <uri_signing.en>`
Adds support for verifying URL signatures for incoming requests to either
deny or redirect access,
implementing the IETF URI Signing draft RFC.
diff --git a/doc/admin-guide/plugins/statichit.en.rst
b/doc/admin-guide/plugins/statichit.en.rst
new file mode 100644
index 0000000000..f673fc9d15
--- /dev/null
+++ b/doc/admin-guide/plugins/statichit.en.rst
@@ -0,0 +1,117 @@
+.. _admin-plugins-statichit:
+.. include:: ../../common.defs
+
+Static Hit Plugin
+*****************
+
+.. Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+This is a simple plugin to serve static content from the proxy's local
filesystem. It shares some
+of the same functionality as the `healthchecks` plugin, but is a remap plugin
(thereby making it
+reloadable). When an object is served by the plugin (not from HTTP cache),
the plugin re-reads the
+current contents of the file containing the object data.
+
+When the plugin is invoked during remapping, if the transaction already has a
status other than OK, the plugin
+will ignore the transaction.
+
+These are the available options for the plugin:
+
+================= ======= ========= ====== ==============
+Long Name One Required? Has Description
+ Letter Value?
+ Name
+================= ======= ========= ====== ==============
+\-\-file-path -f Yes Yes File path. If the given path is
relative, it is relative to the |TS|
+ configuration directory. If
the specified file is a directory, it implies
+ \-\-disable-exact, and URL path
is appended to this directory path to get
+ the path for the file
containing the body. If the specified file is not a
+ directory, it should contain
the body.
+\-\-mime-type -m No Yes Defaults to "text/plain".
+\-\-max-age -a No Yes Defaults to "0". If the value
is not 0, it gives the number of seconds the
+ static body will remain fresh
when cache. (Including in the proxy's cache, if
+ enabled.)
+\-\-failure-code -c No Yes Defaults to "404" (NOT FOUND).
This response status will be returned if the
+ file which should contain the
body does not exist. This option is
+ particularly useful when
\-\-file-path specifies a directory.
+\-\-success-code -s No Yes Defaults to "200" (OK). This is
the response status when the static object is
+ successfully returned in the
transaction response.
+\-\-disable-exact -d No No Disable "exact" URL match.
"Exact" match, for this plugin, means the URL must
+ not include a path.
+================= ======= ========= ====== ==============
+
+When using long option names, the value can be specified by appending = and
then the value. `@pparam=\-\-max-age=5` for
+example. Otherwise, the value must be specified as the next pparam.
`@pparam=-a @pparam=5` for example.
+
+When exact match is enabled, if the request URL has a path, a response with
NOT FOUND status will be sent.
+
+Mime Headers in Responses with OK/200 Status
+============================================
+
+#. Content-Type. The value given with the \-\-mime-type parameter, or its
default value.
+#. Content-Length.
+#. Cache-Control. If \-\-max-age is 0, the value will be "no-cache".
Otherwise, the value will be "max-age=d", where
+ d stands for the value given with the \-\-max-age parameter.
+#. if \-\-max-age is not 0, Last-Modified is present, and gives the time the
static body was last cached.
+
+Metrics
+=======
+
+The plugin publishes the following metrics:
+
+======================== ====================================================
+Name Description
+======================== ====================================================
+statichit.response_bytes The total number of bytes emitted
+statichit.response_count The number of HTTP responses generated by the plugin
+======================== ====================================================
+
+remap.config Examples:
+======================
+
+Serve a request for /internal/healthcheck with the contents of the file
located at /var/run/trafficserver/healthcheck.txt.
+If the file is present, send with a Mime-type of text/plain. Also set the
Cache-Control: header to no-cache.
+
+| map /internal/healthcheck \\
+| \http://127.0.0.1 \\
+| @plugin=statichit.so
@pparam=\-\-file-path=/var/run/trafficserver/healthcheck.txt \\
+| @pparam=\-\-mime-type=text/plain \\
+| @pparam=\-\-success-code=200 \\
+| @pparam=\-\-failure-code=403 \\
+| @pparam=\-\-max-age=0 \\
+| @pparam=\-\-disable-exact
+
+Serve a request for content.example.com/content_xyz.txt with the contents of
the file content_bodies/content_xyz.txt
+under the |TS| configuration file directory (as content_bodies is meant to
imply a directory in this example).
+
+| map \http://content.example.com/content_xyz.txt \\
+| \http://127.0.0.1 \\
+| @plugin=statichit.so @pparam=\-\-file-path=content_bodies \\
+| @pparam=\-\-failure-code=404 \\
+| @pparam=\-\-max-age=604800
+
+Serve a request for content.example.com/content_abc.json with the contents of
the file content_bodies/content_xyz.txt
+under the |TS| configuration file directory (as content_bodies is meant to
imply a directory in this example)
+with a mime-type of application/json. Set cache-control to have a max-age of 7
days (604800 seconds).
+
+| map \http://content.example.com/content_abc.json \\
+| \http://127.0.0.1 \\
+| @plugin=statichit.so @pparam=\-\-file-path=content_bodies \\
+| @pparam=\-\-mime-type=application/json \\
+| @pparam=\-\-max-age=604800
+
+NOTE: The remap origin is never contacted because this plugin intercepts the
request and acts as the origin server. For that reason, the origin
specification must be syntactically valid and resolvable in DNS.
diff --git a/plugins/experimental/statichit/README.md
b/plugins/experimental/statichit/README.md
deleted file mode 100644
index cb7001d525..0000000000
--- a/plugins/experimental/statichit/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-This is a simple plugin to serve static content from a local filesystem. It
shares some of the same functionality as the `healthchecks` plugin, but can be
used in the remap context(thereby making it reloadable). It does not use
fsnotify for watching the source files.
-
-If the file specified by the `--file-path` parameter is not found, the plugin
will return the status code specified
-by the `--failure-code` parameter, defaulting to a 404. If the file is found,
it will return the contents of the file
-setting the `Content-Type` header to the value specified on the `--mime-type`
parameter.
-
-Metrics
---------
-
-The plugin publishes the following metrics:
-
-statichit.response_bytes:
- The total number of bytes emitted
-statichit.response_count:
- The number of HTTP responses generated by the plugin
-
-Examples:
------------
-
-remap.config:
-```
-map /internal/healthcheck \
- http://127.0.0.1 \
- @plugin=statichit.so
@pparam=--file-path=/var/run/trafficserver/healthcheck.txt \
- @pparam=--mime-type=text/plain \
- @pparam=--success-code=200 \
- @pparam=--failure-code=403 \
- @pparam=--max-age=0
-
-map http://content.example.com/content.txt \
- http://127.0.0.1 \
- @plugin=statichit.so
@pparam=--file-path=/opt/ats/etc/trafficserver/static/content_source.txt \
- @pparam=--failure-code=404 \
- @pparam=--max-age=604800
-
-```
-
-NOTE: The remap origin is never contacted because this plugin intercepts the
request and acts as the origin server. For that reason, the origin
specification must be syntactically valid and resolvable in DNS.
diff --git a/tests/gold_tests/pluginTest/statichit/empty.txt
b/tests/gold_tests/pluginTest/statichit/empty.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/gold_tests/pluginTest/statichit/small_body.txt
b/tests/gold_tests/pluginTest/statichit/small_body.txt
new file mode 100644
index 0000000000..9858bc75e7
--- /dev/null
+++ b/tests/gold_tests/pluginTest/statichit/small_body.txt
@@ -0,0 +1 @@
+small body content
diff --git a/tests/gold_tests/pluginTest/statichit/statichit.replay.yaml
b/tests/gold_tests/pluginTest/statichit/statichit.replay.yaml
new file mode 100644
index 0000000000..4dbb3b10de
--- /dev/null
+++ b/tests/gold_tests/pluginTest/statichit/statichit.replay.yaml
@@ -0,0 +1,237 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This replay file tests the stale response plugin when no
+# --stale-while-revalidate-default and no --stale-if-error-default are
+# specified.
+
+sessions:
+
+- transactions:
+
+ - client-request:
+ method: GET
+ url: /
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, fqdn1 ]
+ - [ uuid, 1 ]
+
+ proxy-response:
+ status: 200
+ headers:
+ fields:
+ - [ Content-Length, { value: 19, as: equal } ]
+ - [ Cache-Control, { value: no-cache, as: equal } ]
+ - [ Content-Type, { value: text/plain, as: equal } ]
+ - [ Server, { value: ATS, as: contains } ]
+ content:
+ encoding: plain
+ data: |
+ small body content
+ verify: { as: equal }
+
+ - client-request:
+ method: GET
+ url: /path
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, fqdn1 ]
+ - [ uuid, 2 ]
+
+ proxy-response:
+ status: 404
+ headers:
+ fields:
+ - [ Cache-Control, { value: no-store, as: equal } ]
+ - [ Content-Type, { value: text/html, as: equal } ]
+ - [ Server, { value: ATS, as: contains } ]
+ content:
+ encoding: plain
+ data: Error
+ verify: { as: contains }
+
+ - client-request:
+ method: GET
+ url: /
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, fqdn2 ]
+ - [ uuid, 3 ]
+
+ proxy-response:
+ status: 200
+ headers:
+ fields:
+ - [ Content-Length, { value: 19, as: equal } ]
+ - [ Cache-Control, { value: max-age=123, as: equal } ]
+ - [ Content-Type, { value: text/plain, as: equal } ]
+ - [ Server, { value: ATS, as: contains } ]
+ content:
+ encoding: plain
+ data: |
+ small body content
+ verify: { as: equal }
+
+ - client-request:
+ method: GET
+ url: /path
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, fqdn3 ]
+ - [ uuid, 4 ]
+
+ proxy-response:
+ status: 200
+ headers:
+ fields:
+ - [ Content-Length, { value: 19, as: equal } ]
+ - [ Cache-Control, { value: no-cache, as: equal } ]
+ - [ Content-Type, { value: text/plain, as: equal } ]
+ - [ Server, { value: ATS, as: contains } ]
+ content:
+ encoding: plain
+ data: |
+ small body content
+ verify: { as: equal }
+
+ - client-request:
+ method: GET
+ url: /
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, fqdn4 ]
+ - [ uuid, 5 ]
+
+ proxy-response:
+ status: 412
+ headers:
+ fields:
+ - [ Server, { value: ATS, as: contains } ]
+
+ - client-request:
+ method: GET
+ url: /
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, fqdn5 ]
+ - [ uuid, 6 ]
+
+ proxy-response:
+ status: 200
+ headers:
+ fields:
+ - [ Content-Length, { value: 10917, as: equal } ]
+ - [ Cache-Control, { value: no-cache, as: equal } ]
+ - [ Content-Type, { value: application/json, as: equal } ]
+ - [ Server, { value: ATS, as: contains } ]
+ content:
+ encoding: plain
+ data: http://en.wikipedia.org/wiki/Main_Page
+ verify: { as: contains }
+
+ - client-request:
+ method: GET
+ url: /
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, fqdn6 ]
+ - [ uuid, 7 ]
+
+ proxy-response:
+ status: 200
+ headers:
+ fields:
+ - [ Content-Length, { value: 0, as: equal } ]
+ - [ Cache-Control, { value: no-cache, as: equal } ]
+ - [ Content-Type, { value: text/plain, as: equal } ]
+ - [ Server, { value: ATS, as: contains } ]
+
+ - client-request:
+ method: GET
+ url: /path
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, fqdn7 ]
+ - [ uuid, 8 ]
+
+ proxy-response:
+ status: 200
+ headers:
+ fields:
+ - [ Content-Length, { value: 19, as: equal } ]
+ - [ Cache-Control, { value: no-cache, as: equal } ]
+ - [ Content-Type, { value: text/plain, as: equal } ]
+ - [ Server, { value: ATS, as: contains } ]
+ content:
+ encoding: plain
+ data: |
+ small body content
+ verify: { as: equal }
+
+ - client-request:
+ method: GET
+ url: /path
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, fqdn8 ]
+ - [ uuid, 8 ]
+
+ proxy-response:
+ status: 200
+ headers:
+ fields:
+ - [ Content-Length, { value: 19, as: equal } ]
+ - [ Cache-Control, { value: no-cache, as: equal } ]
+ - [ Content-Type, { value: text/plain, as: equal } ]
+ - [ Server, { value: ATS, as: contains } ]
+ content:
+ encoding: plain
+ data: |
+ small body content
+ verify: { as: equal }
+
+ - client-request:
+ method: GET
+ url: /small_body.txt
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, fqdn9 ]
+ - [ uuid, 9 ]
+
+ proxy-response:
+ status: 200
+ headers:
+ fields:
+ - [ Content-Length, { value: 19, as: equal } ]
+ - [ Cache-Control, { value: no-cache, as: equal } ]
+ - [ Content-Type, { value: text/plain, as: equal } ]
+ - [ Server, { value: ATS, as: contains } ]
+ content:
+ encoding: plain
+ data: |
+ small body content
+ verify: { as: equal }
diff --git a/tests/gold_tests/pluginTest/statichit/statichit.test.py
b/tests/gold_tests/pluginTest/statichit/statichit.test.py
new file mode 100644
index 0000000000..c82d498907
--- /dev/null
+++ b/tests/gold_tests/pluginTest/statichit/statichit.test.py
@@ -0,0 +1,111 @@
+'''
+Verify correct statichit plugin behavior
+'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+
+Test.Summary = '''
+Verify correct statichit plugin behavior
+'''
+
+Test.SkipUnless(Condition.PluginExists('statichit.so'),)
+
+
+class RemapData:
+ """Data for each remap rule"""
+
+ @staticmethod
+ def setup():
+ # Path relative to config directory. The statichit directory will be
created, and small_body.txt copied to it,
+ # by the 2nd (dummy) test run.
+ RemapData.small_body_path = os.path.join('statichit', 'small_body.txt')
+
+ Test.Setup.Copy('story_16.json', Test.RunDirectory)
+ RemapData.json_body_path = os.path.join(Test.RunDirectory,
'story_16.json')
+
+ Test.Setup.Copy('empty.txt', Test.RunDirectory)
+ RemapData.empty_body_path = os.path.join(Test.RunDirectory,
'empty.txt')
+
+ # This directory will be created, and a file copied to it, by the 1st
(dummy) test run.
+ RemapData.dir_path = os.path.join(Test.RunDirectory, 'body_dir')
+
+ def __init__(self, from_url, *args) -> None:
+ self.remap_from = from_url
+ self.plugin_args = args
+ self.body = RemapData.small_body_path
+
+ def bad_body(self):
+ self.body = 'invalid'
+ return self
+
+ def json_body(self):
+ self.body = RemapData.json_body_path
+ return self
+
+ def empty_body(self):
+ self.body = RemapData.empty_body_path
+ return self
+
+ def dir(self):
+ self.body = RemapData.dir_path
+ return self
+
+
+RemapData.setup()
+
+remap_data = [
+ RemapData('http://fqdn1'),
+ RemapData('http://fqdn2', '--max-age=123'),
+ RemapData('http://fqdn3', '--success-code=200', '--disable-exact',
'--failure-code=222'),
+ RemapData('http://fqdn4', '--success-code=200',
'--failure-code=412').bad_body(),
+ RemapData('http://fqdn5', '--success-code=200', '--failure-code=412',
"--mime-type=application/json").json_body(),
+ RemapData('http://fqdn6', '--success-code=200',
'--failure-code=222').empty_body(),
+ RemapData('http://fqdn7', '--success-code', '200', '--disable-exact',
'--failure-code', '222'),
+ RemapData('http://fqdn8', '-s', '200', '-d', '-c', '222'),
+ RemapData('http://fqdn9').dir(),
+]
+
+ts = Test.MakeATSProcess('ts')
+
+ts.Disk.records_config.update({
+ "proxy.config.diags.debug.enabled": 1,
+ "proxy.config.diags.debug.tags": "http|statichit",
+})
+
+for d in remap_data:
+ arg_str = ''
+ for arg in d.plugin_args:
+ arg_str += ' @pparam=' + arg
+ ts.Disk.remap_config.AddLine(f'map {d.remap_from} http://127.0.0.1/
@plugin=statichit.so @pparam=--file-path={d.body}{arg_str}')
+
+# Dummy test run for copying a file.
+tr = Test.AddTestRun()
+p = tr.Processes.Default
+p.Command = (f'mkdir {Test.RunDirectory}/body_dir ; ' + f'cp
{Test.TestDirectory}/small_body.txt {Test.RunDirectory}/body_dir/.')
+
+# Dummy test run for copying a file.
+tr = Test.AddTestRun()
+p = tr.Processes.Default
+p.Command = (
+ f'mkdir {ts.Variables.CONFIGDIR}/statichit ; ' + f'cp
{Test.TestDirectory}/small_body.txt {ts.Variables.CONFIGDIR}/statichit/.')
+p.StartBefore(ts)
+p.StillRunningAfter = ts
+
+tr = Test.AddTestRun()
+p = tr.AddVerifierClientProcess('client', 'statichit.replay.yaml',
http_ports=[ts.Variables.port], other_args='--thread-limit 1')
+p.StillRunningAfter = ts
diff --git a/tests/gold_tests/pluginTest/statichit/story_16.json
b/tests/gold_tests/pluginTest/statichit/story_16.json
new file mode 100644
index 0000000000..38e589636b
--- /dev/null
+++ b/tests/gold_tests/pluginTest/statichit/story_16.json
@@ -0,0 +1,395 @@
+{
+ "cases": [
+ {
+ "seqnum": 0,
+ "headers": [
+ {
+ ":method": "GET"
+ },
+ {
+ ":scheme": "http"
+ },
+ {
+ ":authority": "en.wikipedia.org"
+ },
+ {
+ ":path": "/"
+ },
+ {
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0)
Gecko/20100101 Firefox/16.0"
+ },
+ {
+ "accept":
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
+ },
+ {
+ "accept-language": "en-US,en;q=0.5"
+ },
+ {
+ "accept-encoding": "gzip, deflate"
+ },
+ {
+ "connection": "keep-alive"
+ },
+ {
+ "cookie": "centralnotice_bucket=1;
clicktracking-session=eJko6IiUcEm69ehQfaakQlJfiLy9lShNP;
mediaWiki.user.bucket%3Aext.articleFeedback-tracking=10%3Atrack;
mediaWiki.user.id=EM83jsjaqPzIMLwBTiKF3aLiiTKeweez;
mediaWiki.user.bucket%3Aext.articleFeedback-options=8%3Ashow"
+ }
+ ],
+ "wire":
"8286418c2d4bf8375356590c35cf64df847abcd07f66a281b0dae053fad0321aa49d13fda992a49685340c8a6adca7e28102ef7da9677b8171707f6a62293a9d810020004015309ac2ca7f2c05c5c153b0497ca589d34d1f43aeba0c41a4c7a98f33a69a3fdf9a68fa1d75d0620d263d4c79a68fbed00177febe58f9fbed00177b518b2d4b70ddf45abefb4005db90408721eaa8a4498f5788ea52d6b0e83772ff60ff3d216a4d83a2a3a4c42c51da4ea54c01fb5094189d5360c9d4d54cb20a8418f5405cbd4ee64370260a5c7cb3ec9463ebb28cb29b3fa7e8dd3e9d7f6a52590c3e46ea65ed416c5e3b49d4a95
[...]
+ },
+ {
+ "seqnum": 1,
+ "headers": [
+ {
+ ":method": "GET"
+ },
+ {
+ ":scheme": "http"
+ },
+ {
+ ":authority": "en.wikipedia.org"
+ },
+ {
+ ":path": "/wiki/Main_Page"
+ },
+ {
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0)
Gecko/20100101 Firefox/16.0"
+ },
+ {
+ "accept":
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
+ },
+ {
+ "accept-language": "en-US,en;q=0.5"
+ },
+ {
+ "accept-encoding": "gzip, deflate"
+ },
+ {
+ "connection": "keep-alive"
+ },
+ {
+ "cookie": "centralnotice_bucket=1;
clicktracking-session=eJko6IiUcEm69ehQfaakQlJfiLy9lShNP;
mediaWiki.user.bucket%3Aext.articleFeedback-tracking=10%3Atrack;
mediaWiki.user.id=EM83jsjaqPzIMLwBTiKF3aLiiTKeweez;
mediaWiki.user.bucket%3Aext.articleFeedback-options=8%3Ashow"
+ }
+ ],
+ "wire": "8286c3448b63c1ba998d0335516b1cc5c3c2c190c0bf"
+ },
+ {
+ "seqnum": 2,
+ "headers": [
+ {
+ ":method": "GET"
+ },
+ {
+ ":scheme": "http"
+ },
+ {
+ ":authority": "bits.wikimedia.org"
+ },
+ {
+ ":path": "/en.wikipedia.org/load.php"
+ },
+ {
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0)
Gecko/20100101 Firefox/16.0"
+ },
+ {
+ "accept": "text/css,*/*;q=0.1"
+ },
+ {
+ "accept-language": "en-US,en;q=0.5"
+ },
+ {
+ "accept-encoding": "gzip, deflate"
+ },
+ {
+ "connection": "keep-alive"
+ },
+ {
+ "referer": "http://en.wikipedia.org/wiki/Main_Page"
+ },
+ {
+ "if-modified-since": "Wed, 31 Oct 2012 17:52:04 GMT"
+ }
+ ],
+ "wire":
"8286418d8cc942fe0dd4d496430d73d937449360b52fe0dd4d596430d73d933141c722f5cf5fc5538e497ca582211f5f2c7cfdf6800b87c490c3739c9d29aee30c16a5fc1ba9ab2c861ae7b2663c1ba998d0335516b1cc5f6896e4593e94642a6a225410022502edc6c5700d298b46ff"
+ },
+ {
+ "seqnum": 3,
+ "headers": [
+ {
+ ":method": "GET"
+ },
+ {
+ ":scheme": "http"
+ },
+ {
+ ":authority": "bits.wikimedia.org"
+ },
+ {
+ ":path": "/en.wikipedia.org/load.php"
+ },
+ {
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0)
Gecko/20100101 Firefox/16.0"
+ },
+ {
+ "accept": "text/css,*/*;q=0.1"
+ },
+ {
+ "accept-language": "en-US,en;q=0.5"
+ },
+ {
+ "accept-encoding": "gzip, deflate"
+ },
+ {
+ "connection": "keep-alive"
+ },
+ {
+ "referer": "http://en.wikipedia.org/wiki/Main_Page"
+ },
+ {
+ "if-modified-since": "Thu, 01 Nov 2012 09:33:27 GMT"
+ }
+ ],
+ "wire":
"8286c2c1c8c0c690c5bf6896df3dbf4a002a693f75040089403f71966e09d53168df"
+ },
+ {
+ "seqnum": 4,
+ "headers": [
+ {
+ ":method": "GET"
+ },
+ {
+ ":scheme": "http"
+ },
+ {
+ ":authority": "bits.wikimedia.org"
+ },
+ {
+ ":path": "/en.wikipedia.org/load.php"
+ },
+ {
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0)
Gecko/20100101 Firefox/16.0"
+ },
+ {
+ "accept": "*/*"
+ },
+ {
+ "accept-language": "en-US,en;q=0.5"
+ },
+ {
+ "accept-encoding": "gzip, deflate"
+ },
+ {
+ "connection": "keep-alive"
+ },
+ {
+ "referer": "http://en.wikipedia.org/wiki/Main_Page"
+ },
+ {
+ "if-modified-since": "Sat, 03 Nov 2012 12:53:27 GMT"
+ }
+ ],
+ "wire":
"8286c3c2c95383f963e7c890c7c16896dc34fd280654d27eea0801128115c6d9b82754c5a37f"
+ },
+ {
+ "seqnum": 5,
+ "headers": [
+ {
+ ":method": "GET"
+ },
+ {
+ ":scheme": "http"
+ },
+ {
+ ":authority": "bits.wikimedia.org"
+ },
+ {
+ ":path": "/en.wikipedia.org/load.php"
+ },
+ {
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0)
Gecko/20100101 Firefox/16.0"
+ },
+ {
+ "accept": "*/*"
+ },
+ {
+ "accept-language": "en-US,en;q=0.5"
+ },
+ {
+ "accept-encoding": "gzip, deflate"
+ },
+ {
+ "connection": "keep-alive"
+ },
+ {
+ "referer": "http://en.wikipedia.org/wiki/Main_Page"
+ },
+ {
+ "if-modified-since": "Wed, 31 Oct 2012 17:52:04 GMT"
+ }
+ ],
+ "wire": "8286c5c4cbbfc990c8c2c1"
+ },
+ {
+ "seqnum": 6,
+ "headers": [
+ {
+ ":method": "GET"
+ },
+ {
+ ":scheme": "http"
+ },
+ {
+ ":authority": "bits.wikimedia.org"
+ },
+ {
+ ":path": "/en.wikipedia.org/load.php"
+ },
+ {
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0)
Gecko/20100101 Firefox/16.0"
+ },
+ {
+ "accept": "*/*"
+ },
+ {
+ "accept-language": "en-US,en;q=0.5"
+ },
+ {
+ "accept-encoding": "gzip, deflate"
+ },
+ {
+ "connection": "keep-alive"
+ },
+ {
+ "referer": "http://en.wikipedia.org/wiki/Main_Page"
+ },
+ {
+ "if-modified-since": "Thu, 01 Nov 2012 09:33:27 GMT"
+ }
+ ],
+ "wire": "8286c5c4cbbfc990c8c2c0"
+ },
+ {
+ "seqnum": 7,
+ "headers": [
+ {
+ ":method": "GET"
+ },
+ {
+ ":scheme": "http"
+ },
+ {
+ ":authority": "upload.wikimedia.org"
+ },
+ {
+ ":path": "/wikipedia/en/c/ca/Kanthirava_cropped.png"
+ },
+ {
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0)
Gecko/20100101 Firefox/16.0"
+ },
+ {
+ "accept": "image/png,image/*;q=0.8,*/*;q=0.5"
+ },
+ {
+ "accept-language": "en-US,en;q=0.5"
+ },
+ {
+ "accept-encoding": "gzip, deflate"
+ },
+ {
+ "connection": "keep-alive"
+ },
+ {
+ "referer": "http://en.wikipedia.org/wiki/Main_Page"
+ },
+ {
+ "if-modified-since": "Fri, 02 Nov 2012 23:46:59 GMT"
+ },
+ {
+ "if-none-match": "288bdb2fd5e5a4f7272f58fcb083a7e1"
+ }
+ ],
+ "wire":
"8286418fb6ba0e3917f06ea6a4b2186b9ec9bf449e63c1ba9ab2c861b05a9823041b198752673583ee388961ebacb22f5d537fcd539a352398ac5754df46a473158f9fbed00177bebe58f9fbed00176fcc90cbc56896c361be940094d27eea0801128266e34e5c6df53168df699713cf4724629646cad8da95d13a295b7a524607991ba50f"
+ },
+ {
+ "seqnum": 8,
+ "headers": [
+ {
+ ":method": "GET"
+ },
+ {
+ ":scheme": "http"
+ },
+ {
+ ":authority": "upload.wikimedia.org"
+ },
+ {
+ ":path":
"/wikipedia/commons/thumb/d/d2/Dancing_girl_ajanta_%28cropped%29.jpg/72px-Dancing_girl_ajanta_%28cropped%29.jpg"
+ },
+ {
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0)
Gecko/20100101 Firefox/16.0"
+ },
+ {
+ "accept": "image/png,image/*;q=0.8,*/*;q=0.5"
+ },
+ {
+ "accept-language": "en-US,en;q=0.5"
+ },
+ {
+ "accept-encoding": "gzip, deflate"
+ },
+ {
+ "connection": "keep-alive"
+ },
+ {
+ "referer": "http://en.wikipedia.org/wiki/Main_Page"
+ },
+ {
+ "if-modified-since": "Tue, 30 Oct 2012 17:37:15 GMT"
+ },
+ {
+ "if-none-match": "6e8d56df9be35494b4d9f0ea72ed1a3e"
+ }
+ ],
+ "wire":
"8286c244cf63c1ba9ab2c861b043d349ea43099eda636246241317c7510d54d14c6b28887d07524712a278961ebacb22a27d7e95ccc3a2afcad7c7510d54d14c6b28887d07524712a278961ebacb22a27d7e95cdd1c1cf90cec86896df697e94640a6a225410022502edc65db816d4c5a37f699770af48db924afc6565b69f6a36a47e50146e88b2046c97"
+ },
+ {
+ "seqnum": 9,
+ "headers": [
+ {
+ ":method": "GET"
+ },
+ {
+ ":scheme": "http"
+ },
+ {
+ ":authority": "bits.wikimedia.org"
+ },
+ {
+ ":path": "/en.wikipedia.org/load.php"
+ },
+ {
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0)
Gecko/20100101 Firefox/16.0"
+ },
+ {
+ "accept": "*/*"
+ },
+ {
+ "accept-language": "en-US,en;q=0.5"
+ },
+ {
+ "accept-encoding": "gzip, deflate"
+ },
+ {
+ "connection": "keep-alive"
+ },
+ {
+ "referer": "http://en.wikipedia.org/wiki/Main_Page"
+ },
+ {
+ "if-modified-since": "Sat, 03 Nov 2012 12:53:27 GMT"
+ }
+ ],
+ "wire": "8286cdccd3c7d190d0cac6"
+ }
+ ],
+ "description": "Apache Traffic Server"
+}