diff --git a/doc/.tx/config b/doc/.tx/config index d3e330292a0..485fea9620c 100644 --- a/doc/.tx/config +++ b/doc/.tx/config @@ -417,11 +417,6 @@ file_filter = locale//LC_MESSAGES/admin-guide/plugins/memcache.en.po source_file = _build/locale/pot/admin-guide/plugins/memcache.en.pot source_lang = en -[apache-traffic-server-6x.admin-guide--plugins--metalink_en] -file_filter = locale//LC_MESSAGES/admin-guide/plugins/metalink.en.po -source_file = _build/locale/pot/admin-guide/plugins/metalink.en.pot -source_lang = en - [apache-traffic-server-6x.admin-guide--plugins--mp4_en] file_filter = locale//LC_MESSAGES/admin-guide/plugins/mp4.en.po source_file = _build/locale/pot/admin-guide/plugins/mp4.en.pot @@ -2201,4 +2196,3 @@ source_lang = en file_filter = locale//LC_MESSAGES/developer-guide/documentation/plugins.en.po source_file = _build/locale/pot/developer-guide/documentation/plugins.en.pot source_lang = en - diff --git a/doc/admin-guide/plugins/collapsed_forwarding.en.rst b/doc/admin-guide/plugins/collapsed_forwarding.en.rst deleted file mode 100644 index 8f4024acc15..00000000000 --- a/doc/admin-guide/plugins/collapsed_forwarding.en.rst +++ /dev/null @@ -1,188 +0,0 @@ -.. 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. - -.. include:: ../../common.defs - -.. _admin-plugins-collapsed-forwarding: - -Collapsed Forwarding Plugin -*************************** - -This is a plugin for Apache Traffic Server that allows to achieve -effective connection collapse by blocking all but one of the multiple -concurrent requests for the same object from going to the Origin. - -Installation ------------- - -To make this plugin available, you must either enable experimental plugins -when building |TS|:: - - ./configure --enable-experimental-plugins - -Or use :program:`tsxs` to compile the plugin against your current |TS| build. -To do this, you must ensure that: - -#. Development packages for |TS| are installed. - -#. The :program:`tsxs` binary is in your path. - -#. The version of this plugin you are building, and the version of |TS| against - which you are building it are compatible. - -Once those conditions are satisfied, enter the source directory for the plugin -and perform the following:: - - make -f Makefile.tsxs - make -f Makefile.tsxs install - -Using the plugin ----------------- - -This plugin can function as a per remap plugin or a global plugin, and it takes two optional -arguments for specifying the delay between successive retries and a max -number of retries. - -To activate the plugin in per remap mode, in :file:`remap.config`, simply append the -below to the specific remap line:: - - @plugin=collapsed_forwarding.so @pparam=--delay= @pparam=--retries= - -To activate the plugin globally, in :file:`plugin.config`, add the following line:: - - collapsed_forwarding.so --delay= --retries= - -If the plugin is enabled both globally and per remap, Traffic Server will issue an error on startup. - -Functionality -------------- - -Traffic Server plugin to allow collapsed forwarding of concurrent requests for -the same object. This plugin is based on open_write_fail_action feature, which -detects cache open write failure on a cache miss and returns a 502 error along -with a special @-header indicating the reason for 502 error. The plugin acts -on the error by using an internal redirect follow back to itself, essentially -blocking the request until a response arrives, at which point, relies on -read-while-writer feature to start downloading the object to all waiting -clients. The following config parameters are assumed to be set for this -plugin to work: - -- :ts:cv:`proxy.config.http.cache.open_write_fail_action` ``1`` -- :ts:cv:`proxy.config.cache.enable_read_while_writer` ``1`` -- :ts:cv:`proxy.config.http.number_of_redirections` ``10`` -- :ts:cv:`proxy.config.http.redirect_use_orig_cache_key` ``1`` -- :ts:cv:`proxy.config.http.background_fill_active_timeout` ``0`` -- :ts:cv:`proxy.config.http.background_fill_completed_threshold` ``0`` - -Additionally, given that collapsed forwarding works based on cache write -lock failure detection, the plugin requires cache to be enabled and ready. -On a restart, Traffic Server typically takes a few seconds to initialize -the cache depending on the cache size and number of dirents. While the -cache is not ready yet, collapsed forwarding can not detect the write lock -contention and so can not work. The setting :ts:cv:`proxy.config.http.wait_for_cache` -may be enabled which allows blocking incoming connections from being -accepted until cache is ready. - -Description ------------ -Traffic Server has been affected severely by the Thundering Herd problem caused -by its inability to do effective connection collapse of multiple concurrent -requests for the same segment. This is especially critical when Traffic Server -is used as a solution to use cases such as delivering a large scale video -live streaming. This problem results in a specific behavior where multiple -number of requests for the same file are leaked upstream to the Origin layer -choking the upstream bandwidth due to the duplicated large file downloads or -process intensive file at the Origin layer. This ultimately can cause -stability problems on the origin layer disrupting the overall network -performance. - -Traffic Server supports several kind of connection collapse mechanisms including -Read-While-Writer (RWW), Stale-While-Revalidate (SWR) etc each very effective -dealing with a majority of the use cases that can result in the -Thundering herd problem. - -For a large scale Video Streaming scenario, there's a combination of a -large number of revalidations (e.g. media playlists) and cache misses -(e.g. media segments) that occur for the same file. Traffic Server's -RWW works great in collapsing the concurrent requests in such a scenario, -however, as described in :ref:`admin-configuration-reducing-origin-requests`, -Traffic Server's implementation of RWW has a significant limitation, which -restricts its ability to invoke RWW only when the response headers are -already received. This means that any number of concurrent requests for -the same file that are received before the response headers arrive are -leaked upstream, which can result in a severe Thundering herd problem, -depending on the network latencies (which impact the TTFB for the -response headers) at a given instant of time. - -To address this limitation, Traffic Server supports a few Cache tuning -solutions, such as Open Read Retry, and a new feature called -Open Write Fail action from 6.0. To understand how these approaches work, -it is important to understand the high level flow of how Traffic Server -handles a GET request. - -On receiving a HTTP GET request, Traffic Server generates the cache key -(basically, a hash of the request URL) and looks up for the directory -entry (dirent) using the generated index. On a cache miss, the lookup -fails and Traffic Server then tries to just get a write lock for the -cache object and proceeds to the origin to download the object. On -the Other hand, if the lookup is successful, meaning, the dirent -exists for the generated cache key, Traffic Server tries to obtain -a read lock on the cache object to be able to serve it from the cache. -If the read lock is not successful (possibly, due to the fact that -the object's being written to at that same instant and the response -headers are not in the cache yet), Traffic Server then moves to the -next step of trying to obtain an exclusive write lock. If the write -lock is already held exclusively by another request (transaction), the -attempt fails and at this point Traffic Server simply disables the -cache on that transaction and downloads the object in a proxy-only -mode:: - - 1). Cache Lookup (lookup for the dirent using the request URL as cache key). - 1.1). If lookup fails (cache miss), goto (3). - 1.2). If lookup succeeds, try to obtain a read lock, goto (2). - 2). Open Cache Read (try to obtain read lock) - 2.1). If read lock succeeds, serve from cache, goto (4). - 2.2). If read lock fails, goto (3). - 3). Open Cache Write (try to obtain write lock). - 3.1). If write lock succeeds, download the object into cache and to the client in parallel - 3.2). If write lock fails, disable cache, and download to the client in a proxy-only mode. - 4). Done - -As can be seen above, if a majority of concurrent requests arrive before -response headers are received, they hit (2.2) and (3.2) above. Open Read -Retry can help to repeat (2) after a configured delay on 2.2, thereby -increasing the chances for obtaining a read lock and being able to serve -from the cache. - -However, the Open Read Retry can not help with the concurrent requests -that hit (1.1) above, jumping to (3) directly. Only one such request will -be able to obtain the exclusive write lock and all other requests are -leaked upstream. This is where, the recently developed Traffic Server -feature Open Write Fail Action will help. The feature detects the write -lock failure and can return a stale copy for a Cache Revalidation or a -5xx status code for a Cache Miss with a special internal header -<@Ats-Internal> that allows a TS plugin to take other special actions -depending on the use-case. - -``collapsed_forwarding`` plugin catches that error in SEND_RESPONSE_HDR_HOOK -and performs an internal 3xx Redirect back to the same host, the configured -number of times with the configured amount of delay between consecutive -retries, allowing to be able to initiate RWW, whenever the response headers -are received for the request that was allowed to go to the Origin. - - -More details are available at :ref:`admin-configuration-reducing-origin-requests` \ No newline at end of file diff --git a/doc/admin-guide/plugins/healthchecks.en.rst b/doc/admin-guide/plugins/healthchecks.en.rst index 4f19479dc99..63ddadbcb0d 100644 --- a/doc/admin-guide/plugins/healthchecks.en.rst +++ b/doc/admin-guide/plugins/healthchecks.en.rst @@ -22,6 +22,9 @@ Health Checks Plugin ******************** +**Note:** As of ATS v10.0.0, this plugin is deprecated. Please migrate over +to the new `statichit` plugin instead. + This is a simple plugin, to provide basic (but configurable) health checks. This is a server intercept plugin, and it takes one single configuration option in plugin.config, the configuration file name. @@ -62,6 +65,3 @@ type of ``text/plain`` and a status code of ``200``. If the file does not exist, a ``403`` response is sent:: /__hc /var/run/ts-alive text/plain 200 403 - - - diff --git a/doc/admin-guide/plugins/icap.en.rst b/doc/admin-guide/plugins/icap.en.rst index a93ba1277b1..02167c9d815 100644 --- a/doc/admin-guide/plugins/icap.en.rst +++ b/doc/admin-guide/plugins/icap.en.rst @@ -22,6 +22,8 @@ ICAP Plugin under the License. +**Note:** As of ATS v10.0.0, this plugin is deprecated and unsupported. + The ICAP plugin enables passing along the response header and body to an external server for additional processing (generally scanning) using the ICAP protocol. The scanner, depending on whether the file contains diff --git a/doc/admin-guide/plugins/index.en.rst b/doc/admin-guide/plugins/index.en.rst index eb53b1f36e6..27a3bc22913 100644 --- a/doc/admin-guide/plugins/index.en.rst +++ b/doc/admin-guide/plugins/index.en.rst @@ -61,12 +61,16 @@ Plugins that are considered stable are installed by default in |TS| releases. Header Rewrite Health Checks HTTP Stats + JA3 Fingerprint Lua Regex Remap Regex Revalidate Remap Purge + Remap Stats Stats over HTTP TCPInfo + Traffic Dump + WebP Transform XDebug :doc:`AuthProxy ` @@ -117,6 +121,9 @@ Plugins that are considered stable are installed by default in |TS| releases. :doc:`HTTP Stats ` A remap-based plugin that provides an HTTP interface to all |TS| statistics. +:doc:`JA3 Fingerprint ` + Calculates JA3 Fingerprints for incoming SSL traffic. + :doc:`Lua ` Allows plugins to be written in Lua instead of C code. @@ -126,12 +133,21 @@ Plugins that are considered stable are installed by default in |TS| releases. :doc:`Regex Revalidate ` Configurable rules for forcing cache object revalidations using regular expressions. +:doc:`Remap Stats ` + This global plugin adds remap stats to the stats. + :doc:`Stats over HTTP ` Provide an HTTP interface to all |TS| statistics. :doc:`TCPInfo ` Log TCP metrics at various points of the HTTP processing pipeline. +:doc:`Traffic Dump ` + Dumps traffic data into a JSON format file which can be used to replay traffic. + +:doc:`WebP Transform ` + Converts jpeg and png images to webp format. + :doc:`XDebug ` Allows HTTP clients to debug the operation of the Traffic Server cache using the X-Debug header. @@ -154,24 +170,19 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi Cache Fill Certifier Cert Reporting Tool - Collapsed-Forwarding GeoIP ACL FQ Pacing Header Frequency Hook Trace ICAP - JA3 Fingerprint Maxmind ACL Memcache Memory Profile - Metalink Money Trace MP4 Multiplexer OpenTelemetry Tracer - Parent Select Rate Limit - Remap Stats URI Signing Legacy Signed URLs Slice @@ -179,9 +190,7 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi SSL Session Reuse STEK Share System Statistics - Traffic Dump Wasm - WebP Transform Prefetch :doc:`Access Control ` @@ -193,10 +202,6 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi :doc:`Cert Reporting Tool ` Examines and logs information on loaded certificates. -:doc:`Collapsed-Forwarding ` - Allows to Collapse multiple Concurrent requests by downloading once from the Origin and serving - all clients in parallel. - :doc:`FQ Pacing ` FQ Pacing: Rate Limit TCP connections using Linux's Fair Queuing queue discipline @@ -209,18 +214,12 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi :doc:`ICAP ` Pass response data to external server for further processing using the ICAP protocol. -:doc:`JA3 Fingerprint ` - Calculates JA3 Fingerprints for incoming SSL traffic. - :doc:`MaxMind ACL ` ACL based on the maxmind geo databases (GeoIP2 mmdb and libmaxminddb) :doc:`Memcache ` Implements the memcache protocol for cache contents. -:doc:`Metalink ` - Implements the Metalink download description format in order to try not to download the same file twice. - :doc:`Money Trace ` Allows Trafficserver to participate in a distributed tracing system based upon the Comcast Money library. @@ -239,16 +238,9 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi :doc:`Prefetch ` Pre-fetch objects based on the requested URL path pattern. -:doc:`Parent Select ` - This remap plugin allows selection of parent proxies or origins during requests. This - provides the same functionality as the core :file:`parent.config` and :file:`strategies.yaml` config files. - :doc:`Rate Limit ` Simple transaction rate limiting. -:doc:`Remap Stats ` - This global plugin adds remap stats to the stats. - :doc:`Remap Purge ` This remap plugin allows the administrator to easily setup remotely controlled ``PURGE`` for the content of an entire remap rule. @@ -281,11 +273,5 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi :doc:`System Stats ` Inserts system statistics in to the stats list -:doc:`Traffic Dump ` - Dumps traffic data into a JSON format file which can be used to replay traffic. - :doc:`Wasm ` Allows WebAssembly/Wasm (proxy-wasm) module to be used as ATS Plugin. - -:doc:`WebP Transform ` - Converts jpeg and png images to webp format. diff --git a/doc/admin-guide/plugins/metalink.en.rst b/doc/admin-guide/plugins/metalink.en.rst deleted file mode 100644 index 921924f2733..00000000000 --- a/doc/admin-guide/plugins/metalink.en.rst +++ /dev/null @@ -1,123 +0,0 @@ -.. 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. - -.. _admin-plugins-metalink: - - -Metalink Plugin -=============== - -The `Metalink` plugin implements the Metalink_ download description -format in order to try not to download the same file twice. This -improves cache efficiency and speeds up users' downloads. - -It takes standard headers and knowledge about objects in the cache and -potentially rewrites those headers so that a client will use a URL -that's already cached instead of one that isn't. The headers are -specified in RFC 6249 (Metalink/HTTP: Mirrors and Hashes) and RFC 3230 -(Instance Digests in HTTP) and are sent by various download -redirectors or content distribution networks. - -A lot of download sites distribute the same files from many different -mirrors and users don't know which mirrors are already cached. These -sites often present users with a simple download button, but the -button doesn't predictably access the same mirror, or a mirror that's -already cached. To users it seems like the download works sometimes -(takes seconds) and not others (takes hours), which is frustrating. - -An extreme example of this happens when users share a limited, -possibly unreliable internet connection, as is common in parts of -Africa for example. - - -How it Works ------------- - -When the plugin sees a response with a :mailheader:`Location: ...` -header and a :mailheader:`Digest: SHA-256=...` header, it checks if -the URL in the :mailheader:`Location` header is already cached. If it -isn't, then it tries to find a URL that is cached to use instead. It -looks in the cache for some object that matches the digest in the -:mailheader:`Digest` header and if it succeeds, then it rewrites the -:mailheader:`Location` header with that object's URL. - -This way a client should get sent to a URL that's already cached and -won't download the file again. - - -Installation ------------- - -The `Metalink` plugin is a :term:`global plugin`. Enable it by adding -``metalink.so`` to your :file:`plugin.config` file. There are no -options. - - -Implementation Status ---------------------- - -The plugin implements the :c:data:`TS_HTTP_SEND_RESPONSE_HDR_HOOK` -hook to check and potentially rewrite the :mailheader:`Location` and -:mailheader:`Digest` headers after responses are cached. It doesn't -do it before they're cached because the contents of the cache can -change after responses are cached. It uses :c:func:`TSCacheRead` to -check if the URL in the :mailheader:`Location` header is already -cached. In future, the plugin should also check if the URL is fresh -or not. - -The plugin implements the :c:data:`TS_HTTP_READ_RESPONSE_HDR_HOOK` -hook and :ref:`a null transformation ` -to compute the SHA-256 digest for -content as it's added to the cache. It uses SHA256_Init(), -SHA256_Update(), and SHA256_Final() from OpenSSL to compute the -digest, then it uses :c:func:`TSCacheWrite` to associate the digest -with the request URL. This adds a new cache object where the key is -the digest and the object is the request URL. - -To check if the cache already contains content that matches a digest, -the plugin must call :c:func:`TSCacheRead` with the digest as the key, -read the URL stored in the resultant object, and then call -:c:func:`TSCacheRead` again with this URL as the key. This is -probably inefficient and should be improved. - -An early version of the plugin scanned :mailheader:`Link: <...>; -rel=duplicate` headers. If the URL in the :mailheader:`Location: ...` -header wasn't already cached, it scanned :mailheader:`Link: <...>; -rel=duplicate` headers for a URL that was. The :mailheader:`Digest: -SHA-256=...` header is superior because it will find content that -already exists in the cache in every case that a :mailheader:`Link: -<...>; rel=duplicate` header would, plus in cases where the URL is not -listed among the :mailheader:`Link: <...>; rel=duplicate` headers, -maybe because the content was downloaded from a URL not participating -in the content distribution network, or maybe because there are too -many mirrors to list in :mailheader:`Link: <...>; rel=duplicate` -headers. - -The :mailheader:`Digest: SHA-256=...` header is also more efficient -than :mailheader:`Link: <...>; rel=duplicate` headers because it -involves a constant number of cache lookups. RFC 6249 requires a -:mailheader:`Digest: SHA-256=...` header or :mailheader:`Link: <...>; -rel=duplicate` headers MUST be ignored: - - If Instance Digests are not provided by the Metalink servers, the - :mailheader:`Link` header fields pertaining to this specification - MUST be ignored. - - Metalinks contain whole file hashes as described in Section 6, and - MUST include SHA-256, as specified in [FIPS-180-3]. - - -.. _Metalink: http://en.wikipedia.org/wiki/Metalink diff --git a/doc/admin-guide/plugins/parent_select.en.rst b/doc/admin-guide/plugins/parent_select.en.rst deleted file mode 100644 index 6ff352ee5f3..00000000000 --- a/doc/admin-guide/plugins/parent_select.en.rst +++ /dev/null @@ -1,65 +0,0 @@ -.. 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. - -.. include:: ../../common.defs - -.. _admin-plugins-parent-select: - -Parent Select Plugin -******************** - -This remap plugin allows selection of parent proxies or origins during -requests. This provides the same functionality as the core :file:`parent.config` -and :file:`strategies.yaml` config files via a plugin. - -Purpose -======= - -The purpose of this plugin is to provide a base for creating custom -parent selection plugins, as well as to eventually replace the core -parent and strategy logic so all nontrivial parent selection will -be done via plugins. - -Installation -============ - -This plugin is still experimental, but is included with |TS| when you -build with the experimental plugins enabled via ``configure``. - -Configuration -============= - -This plugin only functions as a remap plugin, and is therefore -configured in :file:`remap.config`. - -It requires two options: the strategies config file, and the name of the strategy. - -For example, a remap.config line might look like: - -.. code-block:: - - map https://example.net/ https://example.net/ @plugin=parent_select.so @pparam=strategies.yaml @pparam=example-strategy - -This means all remap rules can use the same ``strategies.yaml`` file containing multiple strategies, or each remap rule can have its own strategies file, whichever the operator prefers. - - -Strategies file ---------------- - -The ``strategies.yaml`` file is the same format as the core ``strategies.yaml`` config file. - -See :doc:`../files/strategies.yaml.en`. diff --git a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/collapsed_forwarding.en.po b/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/collapsed_forwarding.en.po deleted file mode 100644 index 3484a8c80b1..00000000000 --- a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/collapsed_forwarding.en.po +++ /dev/null @@ -1,233 +0,0 @@ -# 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. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: Apache Traffic Server 7.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-06-30 14:07+0900\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.2.0\n" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:23 -msgid "Collapsed Forwarding Plugin" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:25 -msgid "" -"This is a plugin for Apache Traffic Server that allows to achieve effective " -"connection collapse by blocking all but one of the multiple concurrent " -"requests for the same object from going to the Origin." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:30 -msgid "Installation" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:32 -msgid "" -"To make this plugin available, you must either enable experimental plugins " -"when building |TS|::" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:37 -msgid "" -"Or use :program:`tsxs` to compile the plugin against your current |TS| " -"build. To do this, you must ensure that:" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:40 -msgid "Development packages for |TS| are installed." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:42 -msgid "The :program:`tsxs` binary is in your path." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:44 -msgid "" -"The version of this plugin you are building, and the version of |TS| " -"against which you are building it are compatible." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:47 -msgid "" -"Once those conditions are satisfied, enter the source directory for the " -"plugin and perform the following::" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:54 -msgid "Using the plugin" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:56 -msgid "" -"This plugin functions as a per remap plugin, and it takes two optional " -"arguments for specifying the delay between successive retries and a max " -"number of retries." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:60 -msgid "" -"To activate the plugin in per remap mode, in :file:`remap.config`, simply " -"append the below to the specific remap line::" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:66 -msgid "Functionality" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:68 -msgid "" -"Traffic Server plugin to allow collapsed forwarding of concurrent requests " -"for the same object. This plugin is based on open_write_fail_action " -"feature, which detects cache open write failure on a cache miss and returns " -"a 502 error along with a special @-header indicating the reason for 502 " -"error. The plugin acts on the error by using an internal redirect follow " -"back to itself, essentially blocking the request until a response arrives, " -"at which point, relies on read-while-writer feature to start downloading " -"the object to all waiting clients. The following config parameters are " -"assumed to be set for this plugin to work::" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:86 -msgid "" -"Additionally, given that collapsed forwarding works based on cache write " -"lock failure detection, the plugin requires cache to be enabled and ready. " -"On a restart, Traffic Server typically takes a few seconds to initialize " -"the cache depending on the cache size and number of dirents. While the " -"cache is not ready yet, collapsed forwarding can not detect the write lock " -"contention and so can not work. The setting :ts:cv:`proxy.config.http." -"wait_for_cache` may be enabled which allows blocking incoming connections " -"from being accepted until cache is ready." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:96 -msgid "Description" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:97 -msgid "" -"Traffic Server has been affected severely by the Thundering Herd problem " -"caused by its inability to do effective connection collapse of multiple " -"concurrent requests for the same segment. This is especially critical when " -"Traffic Server is used as a solution to use cases such as delivering a " -"large scale video live streaming. This problem results in a specific " -"behavior where multiple number of requests for the same file are leaked " -"upstream to the Origin layer choking the upstream bandwidth due to the " -"duplicated large file downloads or process intensive file at the Origin " -"layer. This ultimately can cause stability problems on the origin layer " -"disrupting the overall network performance." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:108 -msgid "" -"Traffic Server supports several kind of connection collapse mechanisms " -"including Read-While-Writer (RWW), Stale-While-Revalidate (SWR) etc each " -"very effective dealing with a majority of the use cases that can result in " -"the Thundering herd problem." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:113 -msgid "" -"For a large scale Video Streaming scenario, there's a combination of a " -"large number of revalidations (e.g. media playlists) and cache misses (e.g. " -"media segments) that occur for the same file. Traffic Server's RWW works " -"great in collapsing the concurrent requests in such a scenario, however, as " -"described in ``_admin-configuration-reducing-origin-requests``, Traffic " -"Server's implementation of RWW has a significant limitation, which " -"restricts its ability to invoke RWW only when the response headers are " -"already received. This means that any number of concurrent requests for the " -"same file that are received before the response headers arrive are leaked " -"upstream, which can result in a severe Thundering herd problem, depending " -"on the network latencies (which impact the TTFB for the response headers) " -"at a given instant of time." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:126 -msgid "" -"To address this limitation, Traffic Server supports a few Cache tuning " -"solutions, such as Open Read Retry, and a new feature called Open Write " -"Fail action from 6.0. To understand how these approaches work, it is " -"important to understand the high level flow of how Traffic Server handles a " -"GET request." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:132 -msgid "" -"On receiving a HTTP GET request, Traffic Server generates the cache key " -"(basically, a hash of the request URL) and looks up for the directory entry " -"(dirent) using the generated index. On a cache miss, the lookup fails and " -"Traffic Server then tries to just get a write lock for the cache object and " -"proceeds to the origin to download the object. On the Other hand, if the " -"lookup is successful, meaning, the dirent exists for the generated cache " -"key, Traffic Server tries to obtain a read lock on the cache object to be " -"able to serve it from the cache. If the read lock is not successful " -"(possibly, due to the fact that the object's being written to at that same " -"instant and the response headers are not in the cache yet), Traffic Server " -"then moves to the next step of trying to obtain an exclusive write lock. If " -"the write lock is already held exclusively by another request " -"(transaction), the attempt fails and at this point Traffic Server simply " -"disables the cache on that transaction and downloads the object in a proxy-" -"only mode::" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:160 -msgid "" -"As can be seen above, if a majority of concurrent requests arrive before " -"response headers are received, they hit (2.2) and (3.2) above. Open Read " -"Retry can help to repeat (2) after a configured delay on 2.2, thereby " -"increasing the chances for obtaining a read lock and being able to serve " -"from the cache." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:166 -msgid "" -"However, the Open Read Retry can not help with the concurrent requests that " -"hit (1.1) above, jumping to (3) directly. Only one such request will be " -"able to obtain the exclusive write lock and all other requests are leaked " -"upstream. This is where, the recently developed Traffic Server feature Open " -"Write Fail Action will help. The feature detects the write lock failure and " -"can return a stale copy for a Cache Revalidation or a 5xx status code for a " -"Cache Miss with a special internal header <@Ats-Internal> that allows a TS " -"plugin to take other special actions depending on the use-case." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:176 -msgid "" -"``collapsed_forwarding`` plugin catches that error in " -"SEND_RESPONSE_HDR_HOOK and performs an internal 3xx Redirect back to the " -"same host, the configured number of times with the configured amount of " -"delay between consecutive retries, allowing to be able to initiate RWW, " -"whenever the response headers are received for the request that was allowed " -"to go to the Origin." -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:183 -msgid "More details are available at" -msgstr "" - -#: ../../../admin-guide/plugins/collapsed_forwarding.en.rst:185 -msgid "" -"https://docs.trafficserver.apache.org/en/6.0.x/admin/http-proxy-caching.en." -"html#reducing-origin-server-requests-avoiding-the-thundering-herd" -msgstr "" diff --git a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/index.en.po b/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/index.en.po index c583db958c2..7c0801616f8 100644 --- a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/index.en.po +++ b/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/index.en.po @@ -262,16 +262,6 @@ msgstr "" msgid "Implements the memcache protocol for cache contents." msgstr "" -#: ../../../admin-guide/plugins/index.en.rst:171 -msgid ":doc:`Metalink `" -msgstr "" - -#: ../../../admin-guide/plugins/index.en.rst:171 -msgid "" -"Implements the Metalink download description format in order to try not to " -"download the same file twice." -msgstr "" - #: ../../../admin-guide/plugins/index.en.rst:174 msgid ":doc:`MP4 `" msgstr "" @@ -337,13 +327,3 @@ msgid "" "Allows HTTP clients to debug the operation of the Traffic Server cache " "using the X-Debug header." msgstr "" - -#: ../../../admin-guide/plugins/index.en.rst:202 -msgid ":doc:`Collapsed-Forwarding `" -msgstr "" - -#: ../../../admin-guide/plugins/index.en.rst:201 -msgid "" -"Allows to Collapse multiple Concurrent requests by downloading once from " -"the Origin and serving all clients in parallel." -msgstr "" diff --git a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/metalink.en.po b/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/metalink.en.po deleted file mode 100644 index ef942cd11c7..00000000000 --- a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/metalink.en.po +++ /dev/null @@ -1,169 +0,0 @@ -# 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. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: Apache Traffic Server 6.2\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-01-15 00:13+0900\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.2.0\n" - -#: ../../../admin-guide/plugins/metalink.en.rst:21 -msgid "Metalink Plugin" -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:23 -msgid "" -"The `Metalink` plugin implements the Metalink_ download description format " -"in order to try not to download the same file twice. This improves cache " -"efficiency and speeds up users' downloads." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:27 -msgid "" -"It takes standard headers and knowledge about objects in the cache and " -"potentially rewrites those headers so that a client will use a URL that's " -"already cached instead of one that isn't. The headers are specified in RFC " -"6249 (Metalink/HTTP: Mirrors and Hashes) and RFC 3230 (Instance Digests in " -"HTTP) and are sent by various download redirectors or content distribution " -"networks." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:34 -msgid "" -"A lot of download sites distribute the same files from many different " -"mirrors and users don't know which mirrors are already cached. These sites " -"often present users with a simple download button, but the button doesn't " -"predictably access the same mirror, or a mirror that's already cached. To " -"users it seems like the download works sometimes (takes seconds) and not " -"others (takes hours), which is frustrating." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:41 -msgid "" -"An extreme example of this happens when users share a limited, possibly " -"unreliable internet connection, as is common in parts of Africa for example." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:47 -msgid "How it Works" -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:49 -msgid "" -"When the plugin sees a response with a :mailheader:`Location: ...` header " -"and a :mailheader:`Digest: SHA-256=...` header, it checks if the URL in " -"the :mailheader:`Location` header is already cached. If it isn't, then it " -"tries to find a URL that is cached to use instead. It looks in the cache " -"for some object that matches the digest in the :mailheader:`Digest` header " -"and if it succeeds, then it rewites the :mailheader:`Location` header with " -"that object's URL." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:57 -msgid "" -"This way a client should get sent to a URL that's already cached and won't " -"download the file again." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:62 -msgid "Installation" -msgstr "インストール" - -#: ../../../admin-guide/plugins/metalink.en.rst:64 -msgid "" -"The `Metalink` plugin is a :term:`global plugin`. Enable it by adding " -"``metalink.so`` to your :file:`plugin.config` file. There are no options." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:70 -msgid "Implementation Status" -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:72 -msgid "" -"The plugin implements the :c:data:`TS_HTTP_SEND_RESPONSE_HDR_HOOK` hook to " -"check and potentially rewrite the :mailheader:`Location` and :mailheader:" -"`Digest` headers after responses are cached. It doesn't do it before " -"they're cached because the contents of the cache can change after responses " -"are cached. It uses :c:func:`TSCacheRead` to check if the URL in the :" -"mailheader:`Location` header is already cached. In future, the plugin " -"should also check if the URL is fresh or not." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:81 -msgid "" -"The plugin implements the :c:data:`TS_HTTP_READ_RESPONSE_HDR_HOOK` hook " -"and :ref:`a null transformation ` to compute the SHA-256 digest for content as it's added to " -"the cache. It uses SHA256_Init(), SHA256_Update(), and SHA256_Final() from " -"OpenSSL to compute the digest, then it uses :c:func:`TSCacheWrite` to " -"associate the digest with the request URL. This adds a new cache object " -"where the key is the digest and the object is the request URL." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:90 -msgid "" -"To check if the cache already contains content that matches a digest, the " -"plugin must call :c:func:`TSCacheRead` with the digest as the key, read the " -"URL stored in the resultant object, and then call :c:func:`TSCacheRead` " -"again with this URL as the key. This is probably inefficient and should be " -"improved." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:96 -msgid "" -"An early version of the plugin scanned :mailheader:`Link: <...>; " -"rel=duplicate` headers. If the URL in the :mailheader:`Location: ...` " -"header wasn't already cached, it scanned :mailheader:`Link: <...>; " -"rel=duplicate` headers for a URL that was. The :mailheader:`Digest: " -"SHA-256=...` header is superior because it will find content that already " -"exists in the cache in every case that a :mailheader:`Link: <...>; " -"rel=duplicate` header would, plus in cases where the URL is not listed " -"among the :mailheader:`Link: <...>; rel=duplicate` headers, maybe because " -"the content was downloaded from a URL not participating in the content " -"distribution network, or maybe because there are too many mirrors to list " -"in :mailheader:`Link: <...>; rel=duplicate` headers." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:109 -msgid "" -"The :mailheader:`Digest: SHA-256=...` header is also more efficient than :" -"mailheader:`Link: <...>; rel=duplicate` headers because it involves a " -"constant number of cache lookups. RFC 6249 requires a :mailheader:`Digest: " -"SHA-256=...` header or :mailheader:`Link: <...>; rel=duplicate` headers " -"MUST be ignored:" -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:115 -msgid "" -"If Instance Digests are not provided by the Metalink servers, the :" -"mailheader:`Link` header fields pertaining to this specification MUST be " -"ignored." -msgstr "" - -#: ../../../admin-guide/plugins/metalink.en.rst:119 -msgid "" -"Metalinks contain whole file hashes as described in Section 6, and MUST " -"include SHA-256, as specified in [FIPS-180-3]." -msgstr "" diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index af5695581b4..65a41b04fe9 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -27,7 +27,6 @@ add_subdirectory(compress) add_subdirectory(conf_remap) add_subdirectory(escalate) add_subdirectory(esi) - add_subdirectory(generator) add_subdirectory(header_rewrite) add_subdirectory(libloader) @@ -36,12 +35,19 @@ add_subdirectory(prefetch) add_subdirectory(regex_remap) add_subdirectory(regex_revalidate) add_subdirectory(remap_purge) +add_subdirectory(remap_stats) add_subdirectory(s3_auth) add_subdirectory(server_push_preload) +add_subdirectory(statichit) add_subdirectory(stats_over_http) add_subdirectory(tcpinfo) +add_subdirectory(traffic_dump) add_subdirectory(xdebug) +if(NOT OPENSSL_IS_BORINGSSL) + add_subdirectory(ja3_fingerprint) +endif() + if(ENABLE_LUAJIT) add_subdirectory(lua) endif() diff --git a/plugins/Makefile.am b/plugins/Makefile.am index fd9d430cc3d..57013f8f8e0 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -42,6 +42,9 @@ include header_rewrite/Makefile.inc if BUILD_HEALTHCHECK_PLUGIN include healthchecks/Makefile.inc endif +if BUILD_JA3_PLUGIN +include ja3_fingerprint/Makefile.inc +endif include libloader/Makefile.inc if HAS_LUAJIT include lua/Makefile.inc @@ -51,10 +54,16 @@ include prefetch/Makefile.inc include regex_remap/Makefile.inc include regex_revalidate/Makefile.inc include remap_purge/Makefile.inc +include remap_stats/Makefile.inc include s3_auth/Makefile.inc include server_push_preload/Makefile.inc +include statichit/Makefile.inc include stats_over_http/Makefile.inc include tcpinfo/Makefile.inc +include traffic_dump/Makefile.inc +if BUILD_IMAGE_MAGICK_PLUGINS +include webp_transform/Makefile.inc +endif include xdebug/Makefile.inc if BUILD_EXPERIMENTAL_PLUGINS @@ -62,13 +71,11 @@ if BUILD_EXPERIMENTAL_PLUGINS include experimental/access_control/Makefile.inc include experimental/cache_fill/Makefile.inc include experimental/cert_reporting_tool/Makefile.inc -include experimental/collapsed_forwarding/Makefile.inc include experimental/cookie_remap/Makefile.inc include experimental/custom_redirect/Makefile.inc include experimental/fq_pacing/Makefile.inc include experimental/geoip_acl/Makefile.inc include experimental/header_freq/Makefile.inc -include experimental/parent_select/Makefile.inc include experimental/hook-trace/Makefile.inc include experimental/http_stats/Makefile.inc include experimental/icap/Makefile.inc @@ -88,25 +95,17 @@ endif include experimental/memcache/Makefile.inc include experimental/memory_profile/Makefile.inc -include experimental/metalink/Makefile.inc include experimental/money_trace/Makefile.inc include experimental/mp4/Makefile.inc include experimental/rate_limit/Makefile.inc include experimental/redo_cache_lookup/Makefile.inc -include experimental/remap_stats/Makefile.inc include experimental/slice/Makefile.inc include experimental/sslheaders/Makefile.inc -include experimental/statichit/Makefile.inc include experimental/stream_editor/Makefile.inc include experimental/system_stats/Makefile.inc -include experimental/traffic_dump/Makefile.inc include experimental/tls_bridge/Makefile.inc include experimental/url_sig/Makefile.inc -if BUILD_JA3_PLUGIN -include experimental/ja3_fingerprint/Makefile.inc -endif - if BUILD_URI_SIGNING_PLUGIN include experimental/uri_signing/Makefile.inc endif @@ -124,7 +123,6 @@ include experimental/cache_key_genid/Makefile.inc endif if BUILD_IMAGE_MAGICK_PLUGINS -include experimental/webp_transform/Makefile.inc include experimental/magick/Makefile.inc endif diff --git a/plugins/experimental/CMakeLists.txt b/plugins/experimental/CMakeLists.txt index 5cddd5b1dca..9e5cfc25b9d 100644 --- a/plugins/experimental/CMakeLists.txt +++ b/plugins/experimental/CMakeLists.txt @@ -18,7 +18,6 @@ add_subdirectory(access_control) add_subdirectory(cache_fill) add_subdirectory(cert_reporting_tool) -add_subdirectory(collapsed_forwarding) add_subdirectory(cookie_remap) add_subdirectory(custom_redirect) add_subdirectory(fq_pacing) @@ -27,20 +26,12 @@ add_subdirectory(hook-trace) add_subdirectory(http_stats) add_subdirectory(icap) add_subdirectory(inliner) -if(NOT OPENSSL_IS_BORINGSSL) - add_subdirectory(ja3_fingerprint) -endif() add_subdirectory(maxmind_acl) add_subdirectory(memory_profile) -add_subdirectory(metalink) add_subdirectory(money_trace) add_subdirectory(mp4) -add_subdirectory(parent_select) add_subdirectory(redo_cache_lookup) -add_subdirectory(remap_stats) add_subdirectory(slice) -add_subdirectory(statichit) add_subdirectory(stream_editor) add_subdirectory(system_stats) add_subdirectory(tls_bridge) -add_subdirectory(traffic_dump) diff --git a/plugins/experimental/collapsed_forwarding/CMakeLists.txt b/plugins/experimental/collapsed_forwarding/CMakeLists.txt deleted file mode 100644 index 57828632f98..00000000000 --- a/plugins/experimental/collapsed_forwarding/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -####################### -# -# 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. -# -####################### - -add_atsplugin(collapsed_forwarding collapsed_forwarding.cc) diff --git a/plugins/experimental/collapsed_forwarding/Makefile.inc b/plugins/experimental/collapsed_forwarding/Makefile.inc deleted file mode 100644 index a54547887f3..00000000000 --- a/plugins/experimental/collapsed_forwarding/Makefile.inc +++ /dev/null @@ -1,20 +0,0 @@ -# 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. - -pkglib_LTLIBRARIES += experimental/collapsed_forwarding/collapsed_forwarding.la - -experimental_collapsed_forwarding_collapsed_forwarding_la_SOURCES = \ - experimental/collapsed_forwarding/collapsed_forwarding.cc diff --git a/plugins/experimental/collapsed_forwarding/README b/plugins/experimental/collapsed_forwarding/README deleted file mode 100644 index ca0a0025972..00000000000 --- a/plugins/experimental/collapsed_forwarding/README +++ /dev/null @@ -1,37 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// collapsed_forwarding:: -// -// ATS plugin to allow collapsed forwarding of concurrent requests for the same -// object. This plugin is based on open_write_fail_action feature, which detects -// cache open write failure on a cache miss and returns a 502 error along with a -// special @-header indicating the reason for 502 error. The plugin acts on the -// error by using an internal redirect follow back to itself, essentially blocking -// the request until a response arrives, at which point, relies on read-while-writer -// feature to start downloading the object to all waiting clients. The following -// config parameters are assumed to be set for this plugin to work: -//////////////////////////////////////////////////////////////////////////////////// -// proxy.config.http.cache.open_write_fail_action 1 ///////////////////////// -// proxy.config.cache.enable_read_while_writer 1 ///////////////////////// -// proxy.config.http.number_of_redirections 10 ///////////////////////// -// proxy.config.http.redirect_use_orig_cache_key 1 ///////////////////////// -// proxy.config.http.background_fill_active_timeout 0 ///////////////////////// -// proxy.config.http.background_fill_completed_threshold 0 ///////////////////////// -//////////////////////////////////////////////////////////////////////////////////// -// Additionally, given that collapsed forwarding works based on cache write -// lock failure detection, the plugin requires cache to be enabled and ready. -// On a restart, Traffic Server typically takes a few seconds to initialize -// the cache depending on the cache size and number of dirents. While the -// cache is not ready yet, collapsed forwarding can not detect the write lock -// contention and so can not work. The setting proxy.config.http.wait_for_cache -// may be enabled which allows blocking incoming connections from being -// accepted until cache is ready. - -More details are available at - -https://docs.trafficserver.apache.org/en/latest/admin-guide/configuration/cache-basics.en.html#reducing-origin-server-requests-avoiding-the-thundering-herd - -Configuration: - - Add @plugin=collapsed_forwarding.so to your remap.config rules. The plugin optionally -accepts a --delay= parameter and a --retries= parameter that can help tune -the total number of retries and the delay between consecutive retries. diff --git a/plugins/experimental/collapsed_forwarding/collapsed_forwarding.cc b/plugins/experimental/collapsed_forwarding/collapsed_forwarding.cc deleted file mode 100644 index b5063e90ad8..00000000000 --- a/plugins/experimental/collapsed_forwarding/collapsed_forwarding.cc +++ /dev/null @@ -1,379 +0,0 @@ -/** @file - - @section license License - - 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. -*/ - -//////////////////////////////////////////////////////////////////////////////// -// collapsed_forwarding:: -// -// ATS plugin to allow collapsed forwarding of concurrent requests for the same -// object. This plugin is based on open_write_fail_action feature, which detects -// cache open write failure on a cache miss and returns a 502 error along with a -// special @-header indicating the reason for 502 error. The plugin acts on the -// error by using an internal redirect follow back to itself, essentially blocking -// the request until a response arrives, at which point, relies on read-while-writer -// feature to start downloading the object to all waiting clients. The following -// config parameters are assumed to be set for this plugin to work: -//////////////////////////////////////////////////////////////////////////////////// -// proxy.config.http.cache.open_write_fail_action 1 ///////////////////////// -// proxy.config.cache.enable_read_while_writer 1 ///////////////////////// -// proxy.config.http.number_of_redirections 10 ///////////////////////// -// proxy.config.http.redirect_use_orig_cache_key 1 ///////////////////////// -// proxy.config.http.background_fill_active_timeout 0 ///////////////////////// -// proxy.config.http.background_fill_completed_threshold 0 ///////////////////////// -//////////////////////////////////////////////////////////////////////////////////// -// Additionally, given that collapsed forwarding works based on cache write -// lock failure detection, the plugin requires cache to be enabled and ready. -// On a restart, Traffic Server typically takes a few seconds to initialize -// the cache depending on the cache size and number of dirents. While the -// cache is not ready yet, collapsed forwarding can not detect the write lock -// contention and so can not work. The setting proxy.config.http.wait_for_cache -// may be enabled which allows blocking incoming connections from being -// accepted until cache is ready. -//////////////////////////////////////////////////////////////////////////////////// -// This plugin currently supports only per-remap mode activation. -//////////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const char *DEBUG_TAG = (char *)"collapsed_forwarding"; - -static const char *LOCATION_HEADER = "Location"; -static const char *REDIRECT_REASON = "See Other"; -static const char *ATS_INTERNAL_MESSAGE = "@Ats-Internal"; - -static int OPEN_WRITE_FAIL_MAX_REQ_DELAY_RETRIES = 5; -static int OPEN_WRITE_FAIL_REQ_DELAY_TIMEOUT = 500; - -static bool global_init = false; - -using RequestData = struct _RequestData { - TSHttpTxn txnp; - int wl_retry; // write lock failure retry count - std::string req_url; -}; - -static int -add_redirect_header(TSMBuffer &bufp, TSMLoc &hdr_loc, const std::string &location) -{ - // This is needed in case the response already contains a Location header - TSMLoc field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, LOCATION_HEADER, strlen(LOCATION_HEADER)); - - if (field_loc == TS_NULL_MLOC) { - TSMimeHdrFieldCreateNamed(bufp, hdr_loc, LOCATION_HEADER, strlen(LOCATION_HEADER), &field_loc); - } - - if (TS_SUCCESS == TSMimeHdrFieldValueStringSet(bufp, hdr_loc, field_loc, -1, location.c_str(), location.size())) { - TSDebug(DEBUG_TAG, "Adding Location header %s", LOCATION_HEADER); - TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc); - } - - TSHandleMLocRelease(bufp, hdr_loc, field_loc); - - TSHttpHdrStatusSet(bufp, hdr_loc, TS_HTTP_STATUS_SEE_OTHER); - TSHttpHdrReasonSet(bufp, hdr_loc, REDIRECT_REASON, strlen(REDIRECT_REASON)); - return TS_SUCCESS; -} - -static bool -check_internal_message_hdr(TSHttpTxn &txnp) -{ - TSMBuffer bufp; - TSMLoc hdr_loc; - bool found = false; - - if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { - TSError("check_internal_message_hdr: couldn't retrieve client response header"); - return false; - } - - TSMLoc header_loc = TSMimeHdrFieldFind(bufp, hdr_loc, ATS_INTERNAL_MESSAGE, strlen(ATS_INTERNAL_MESSAGE)); - if (header_loc) { - found = true; - // found the header, remove it now.. - TSMimeHdrFieldDestroy(bufp, hdr_loc, header_loc); - TSHandleMLocRelease(bufp, hdr_loc, header_loc); - } - - TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); - - return found; -} - -static int -on_OS_DNS(const RequestData *req, TSHttpTxn &txnp) -{ - if (req->wl_retry > 0) { - TSDebug(DEBUG_TAG, "OS_DNS request delayed %d times, block origin req for url: %s", req->wl_retry, req->req_url.c_str()); - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); - return TS_SUCCESS; - } - - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; -} - -static int -on_send_request_header(const RequestData *req, TSHttpTxn &txnp) -{ - if (req->wl_retry > 0) { - TSDebug(DEBUG_TAG, "Send_Req request delayed %d times, block origin req for url: %s", req->wl_retry, req->req_url.c_str()); - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); - return TS_SUCCESS; - } - - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; -} - -static int -on_read_response_header(TSHttpTxn &txnp) -{ - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; -} - -static int -on_immediate(RequestData *req, TSCont &contp) -{ - if (!req) { - TSError("%s: invalid req_data", DEBUG_TAG); - return TS_SUCCESS; - } - - TSDebug(DEBUG_TAG, "continuation delayed, scheduling now..for url: %s", req->req_url.c_str()); - - // add retry_done header to prevent looping - TSMBuffer bufp; - TSMLoc hdr_loc; - if (TSHttpTxnClientRespGet(req->txnp, &bufp, &hdr_loc) != TS_SUCCESS) { - TSError("plugin=%s, level=error, error_code=could_not_retrieve_client_response_header for url %s", DEBUG_TAG, - req->req_url.c_str()); - TSHttpTxnReenable(req->txnp, TS_EVENT_HTTP_ERROR); - return TS_SUCCESS; - } - - add_redirect_header(bufp, hdr_loc, req->req_url); - TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); - TSHttpTxnReenable(req->txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; -} - -static int -on_send_response_header(RequestData *req, TSHttpTxn &txnp, TSCont &contp) -{ - TSMBuffer bufp; - TSMLoc hdr_loc; - if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { - TSError("plugin=%s, level=error, error_code=could_not_retrieve_client_response_header", DEBUG_TAG); - return TS_SUCCESS; - } - - TSHttpStatus status = TSHttpHdrStatusGet(bufp, hdr_loc); - TSDebug(DEBUG_TAG, "Response code: %d", status); - - if ((status == TS_HTTP_STATUS_BAD_GATEWAY) || (status == TS_HTTP_STATUS_SEE_OTHER) || - status == TS_HTTP_STATUS_INTERNAL_SERVER_ERROR) { - bool is_internal_message_hdr = check_internal_message_hdr(txnp); - bool delay_request = - is_internal_message_hdr || ((req->wl_retry > 0) && (req->wl_retry < OPEN_WRITE_FAIL_MAX_REQ_DELAY_RETRIES)); - - if (delay_request) { - req->wl_retry++; - TSDebug(DEBUG_TAG, "delaying request, url@%p: {{%s}} on retry: %d time", txnp, req->req_url.c_str(), req->wl_retry); - TSContScheduleOnPool(contp, OPEN_WRITE_FAIL_REQ_DELAY_TIMEOUT, TS_THREAD_POOL_TASK); - TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); - return TS_SUCCESS; - } - } - - if (req->wl_retry > 0) { - TSDebug(DEBUG_TAG, "request delayed, but unsuccessful, url@%p: {{%s}} on retry: %d time", txnp, req->req_url.c_str(), - req->wl_retry); - req->wl_retry = 0; - } - - TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; -} - -static int -on_txn_close(RequestData *req, TSHttpTxn &txnp, TSCont &contp) -{ - // done..cleanup - delete req; - TSContDestroy(contp); - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; -} - -static int collapsed_cont(TSCont contp, TSEvent event, void *edata); - -void -setup_transaction_cont(TSHttpTxn rh) -{ - TSCont cont = TSContCreate(collapsed_cont, TSMutexCreate()); - - RequestData *req_data = new RequestData(); - - req_data->txnp = rh; - req_data->wl_retry = 0; - - int url_len = 0; - char *url = TSHttpTxnEffectiveUrlStringGet(rh, &url_len); - req_data->req_url.assign(url, url_len); - - TSfree(url); - TSContDataSet(cont, req_data); - - TSHttpTxnHookAdd(rh, TS_HTTP_SEND_REQUEST_HDR_HOOK, cont); - TSHttpTxnHookAdd(rh, TS_HTTP_SEND_RESPONSE_HDR_HOOK, cont); - TSHttpTxnHookAdd(rh, TS_HTTP_READ_RESPONSE_HDR_HOOK, cont); - TSHttpTxnHookAdd(rh, TS_HTTP_OS_DNS_HOOK, cont); - TSHttpTxnHookAdd(rh, TS_HTTP_TXN_CLOSE_HOOK, cont); -} - -static int -collapsed_cont(TSCont contp, TSEvent event, void *edata) -{ - TSHttpTxn txnp = static_cast(edata); - RequestData *my_req = static_cast(TSContDataGet(contp)); - - switch (event) { - case TS_EVENT_HTTP_READ_REQUEST_HDR: - // Create per transaction state - setup_transaction_cont(txnp); - break; - - case TS_EVENT_HTTP_OS_DNS: { - return on_OS_DNS(my_req, txnp); - } - - case TS_EVENT_HTTP_SEND_REQUEST_HDR: { - return on_send_request_header(my_req, txnp); - } - - case TS_EVENT_HTTP_READ_RESPONSE_HDR: { - return on_read_response_header(txnp); - } - case TS_EVENT_IMMEDIATE: - case TS_EVENT_TIMEOUT: { - return on_immediate(my_req, contp); - } - case TS_EVENT_HTTP_SEND_RESPONSE_HDR: { - return on_send_response_header(my_req, txnp, contp); - } - case TS_EVENT_HTTP_TXN_CLOSE: { - return on_txn_close(my_req, txnp, contp); - } - default: { - TSDebug(DEBUG_TAG, "Unexpected event: %d", event); - break; - } - } - - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; -} - -void -process_args(int argc, const char **argv) -{ - // basic argv processing.. - for (int i = 1; i < argc; ++i) { - if (strncmp(argv[i], "--delay=", 8) == 0) { - OPEN_WRITE_FAIL_REQ_DELAY_TIMEOUT = atoi(const_cast(argv[i] + 8)); - } else if (strncmp(argv[i], "--retries=", 10) == 0) { - OPEN_WRITE_FAIL_MAX_REQ_DELAY_RETRIES = atoi(const_cast(argv[i] + 10)); - } - } -} - -/* - * Initialize globally - */ -void -TSPluginInit(int argc, const char *argv[]) -{ - TSPluginRegistrationInfo info; - - info.plugin_name = const_cast(DEBUG_TAG); - info.vendor_name = (char *)"Apache Software Foundation"; - info.support_email = (char *)"dev@trafficserver.apache.org"; - - if (TS_SUCCESS != TSPluginRegister(&info)) { - TSError("[%s] Plugin registration failed", DEBUG_TAG); - } - - process_args(argc, argv); - - TSCont cont = TSContCreate(collapsed_cont, TSMutexCreate()); - - TSDebug(DEBUG_TAG, "Global Initialized"); - // Set up the per transaction state in the READ_REQUEST event - TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont); - - global_init = true; -} - -TSReturnCode -TSRemapInit(TSRemapInterface * /* api_info */, char * /* errbuf */, int /* errbuf_size */) -{ - if (global_init) { - TSError("Cannot initialize %s as both global and remap plugin", DEBUG_TAG); - return TS_ERROR; - } else { - TSDebug(DEBUG_TAG, "plugin is successfully initialized for remap"); - return TS_SUCCESS; - } -} - -TSReturnCode -TSRemapNewInstance(int argc, char *argv[], void ** /* ih */, char * /* errbuf */, int /* errbuf_size */) -{ - process_args(argc - 1, const_cast(argv + 1)); - return TS_SUCCESS; -} - -TSRemapStatus -TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo *rri) -{ - setup_transaction_cont(rh); - - return TSREMAP_NO_REMAP; -} - -void -TSRemapDeleteInstance(void *ih) -{ - // To resolve run time error -} diff --git a/plugins/experimental/ja3_fingerprint/Makefile.inc b/plugins/experimental/ja3_fingerprint/Makefile.inc deleted file mode 100644 index b29be9f7d59..00000000000 --- a/plugins/experimental/ja3_fingerprint/Makefile.inc +++ /dev/null @@ -1,19 +0,0 @@ -# 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. - -pkglib_LTLIBRARIES += experimental/ja3_fingerprint/ja3_fingerprint.la - -experimental_ja3_fingerprint_ja3_fingerprint_la_SOURCES = experimental/ja3_fingerprint/ja3_fingerprint.cc diff --git a/plugins/experimental/metalink/CMakeLists.txt b/plugins/experimental/metalink/CMakeLists.txt deleted file mode 100644 index ad047f18565..00000000000 --- a/plugins/experimental/metalink/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -####################### -# -# 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. -# -####################### - -add_atsplugin(metalink metalink.cc) - -target_link_libraries(metalink PRIVATE OpenSSL::SSL) diff --git a/plugins/experimental/metalink/README b/plugins/experimental/metalink/README deleted file mode 100644 index 8ab54b30a63..00000000000 --- a/plugins/experimental/metalink/README +++ /dev/null @@ -1,78 +0,0 @@ - - MMeettaalliinnkk - - Try not to download the same file twice. Improve cache efficiency - and speed up downloads. - - Take standard headers and knowledge about objects in the cache and - potentially rewrite those headers so that a client will use a URL - that's already cached instead of one that isn't. The headers are - specified in [RFC 6249] (Metalink/HTTP: Mirrors and Hashes) and - [RFC 3230] (Instance Digests in HTTP) and are sent by various - download redirectors or content distribution networks. - - -11.. WWhhoo CCaarreess?? - - More important than saving a little bandwidth, this saves users - from frustration. - - A lot of download sites distribute the same files from many - different mirrors and users don't know which mirrors are already - cached. These sites often present users with a simple download - button, but the button doesn't predictably access the same mirror, - or a mirror that's already cached. To users it seems like the - download works sometimes (takes seconds) and not others (takes - hours), which is frustrating. - - An extreme example of this happens when users share a limited, - possibly unreliable internet connection, as is common in parts of - Africa for example. - - [How to cache openSUSE repositories with Squid] is another, - different example of a use case where picking a URL that's already - cached is valuable. - - -22.. WWhhaatt iitt DDooeess - - When it sees a response with a "Location: ..." header and a - "Digest: SHA-256=..." header, it checks if the URL in the Location - header is already cached. If it isn't, then it tries to find a URL - that is cached to use instead. It looks in the cache for some - object that matches the digest in the Digest header and if it - succeeds, then it rewrites the Location header with that object's - URL. - - This way a client should get sent to a URL that's already cached - and won't download the file again. - - -33.. HHooww ttoo UUssee iitt - - Just build the plugin and add it to your plugin.config file. - - The code is distributed along with recent versions of Traffic - Server, in the plugins/experimental/metalink directory. To build - it, pass the --enable-experimental-plugins option to the configure - script when you build Traffic Server: - -
$ ./configure --enable-experimental-plugins
- - When you're done building Traffic Server, add "metalink.so" to your - plugin.config file to start using the plugin. - - -44.. RReeaadd MMoorree - - More details are on the [wiki page] in the Traffic Server wiki. - - - [RFC 6249] http://tools.ietf.org/html/rfc6249 - - [RFC 3230] http://tools.ietf.org/html/rfc3230 - - [How to cache openSUSE repositories with Squid] - http://wiki.jessen.ch/index/How_to_cache_openSUSE_repositories_with_Squid - - [wiki page] https://cwiki.apache.org/confluence/display/TS/Metalink diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc deleted file mode 100644 index b8eae9a8cb5..00000000000 --- a/plugins/experimental/metalink/metalink.cc +++ /dev/null @@ -1,904 +0,0 @@ -/** @file - * - * Try not to download the same file twice. Improve cache efficiency - * and speed up downloads. - * - * @section license License - * - * 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. */ - -#include - -#include - -#include "ts/ts.h" - -/* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null - * transformation. Compute the SHA-256 digest of the content, write - * it to the cache and store the request URL at that key. - * - * Implement TS_HTTP_SEND_RESPONSE_HDR_HOOK to check the Location and - * Digest headers. Use TSCacheRead() to check if the URL in the - * Location header is already cached. If not, potentially rewrite - * that header. Do this after responses are cached because the cache - * will change. - * - * More details are on the [wiki page] in the Traffic Server wiki. - * - * [wiki page] https://cwiki.apache.org/confluence/display/TS/Metalink */ - -/* TSCacheWrite() and TSVConnWrite() data: Write the digest to the - * cache and store the request URL at that key */ - -struct WriteData { - TSHttpTxn txnp; - - TSCacheKey key; - - TSVConn connp; - TSIOBuffer cache_bufp; -}; - -/* TSTransformCreate() data: Compute the SHA-256 digest of the content */ - -struct TransformData { - TSHttpTxn txnp; - - /* Null transformation */ - TSIOBuffer output_bufp; - TSVIO output_viop; - - /* Message digest handle */ - SHA256_CTX c; -}; - -/* TSCacheRead() and TSVConnRead() data: Check the Location and Digest - * headers */ - -struct SendData { - TSHttpTxn txnp; - - TSMBuffer resp_bufp; - TSMLoc hdr_loc; - - /* Location header */ - TSMLoc location_loc; - - /* Cache key */ - TSMLoc url_loc; - TSCacheKey key; - - /* Digest header */ - TSMLoc digest_loc; - - /* Digest header field value index */ - int idx; - - TSVConn connp; - TSIOBuffer cache_bufp; - - const char *value; - int64_t length; -}; - -/* Implement TS_HTTP_READ_RESPONSE_HDR_HOOK to implement a null - * transformation */ - -/* Write the digest to the cache and store the request URL at that key */ - -static int -cache_open_write(TSCont contp, void *edata) -{ - TSMBuffer req_bufp; - - TSMLoc hdr_loc; - TSMLoc url_loc; - - char *value; - int length; - - WriteData *data = static_cast(TSContDataGet(contp)); - data->connp = static_cast(edata); - - TSCacheKeyDestroy(data->key); - - if (TSHttpTxnClientReqGet(data->txnp, &req_bufp, &hdr_loc) != TS_SUCCESS) { - TSError("[metalink] Couldn't retrieve client request header"); - - TSContDestroy(contp); - - TSfree(data); - - return 0; - } - - if (TSHttpHdrUrlGet(req_bufp, hdr_loc, &url_loc) != TS_SUCCESS) { - TSContDestroy(contp); - - TSfree(data); - - TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, hdr_loc); - - return 0; - } - - /* Allocation! Must free! */ - value = TSUrlStringGet(req_bufp, url_loc, &length); - if (!value) { - TSContDestroy(contp); - - TSfree(data); - - TSHandleMLocRelease(req_bufp, hdr_loc, url_loc); - TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, hdr_loc); - - return 0; - } - - TSHandleMLocRelease(req_bufp, hdr_loc, url_loc); - TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, hdr_loc); - - /* Store the request URL */ - - data->cache_bufp = TSIOBufferCreate(); - TSIOBufferReader readerp = TSIOBufferReaderAlloc(data->cache_bufp); - - int nbytes = TSIOBufferWrite(data->cache_bufp, value, length); - - TSfree(value); - - /* Reentrant! Reuse the TSCacheWrite() continuation. */ - TSVConnWrite(data->connp, contp, readerp, nbytes); - - return 0; -} - -/* Do nothing */ - -static int -cache_open_write_failed(TSCont contp, void * /* edata ATS_UNUSED */) -{ - WriteData *data = static_cast(TSContDataGet(contp)); - TSContDestroy(contp); - - TSCacheKeyDestroy(data->key); - TSfree(data); - - return 0; -} - -static int -write_vconn_write_complete(TSCont contp, void * /* edata ATS_UNUSED */) -{ - WriteData *data = static_cast(TSContDataGet(contp)); - TSContDestroy(contp); - - /* The object is not committed to the cache until the VConnection is - * closed. When all the data has been transferred, the user (contp) - * must do a TSVConnClose() */ - TSVConnClose(data->connp); - - TSIOBufferDestroy(data->cache_bufp); - TSfree(data); - - return 0; -} - -/* TSCacheWrite() and TSVConnWrite() handler: Write the digest to the - * cache and store the request URL at that key */ - -static int -write_handler(TSCont contp, TSEvent event, void *edata) -{ - switch (event) { - case TS_EVENT_CACHE_OPEN_WRITE: - return cache_open_write(contp, edata); - - case TS_EVENT_CACHE_OPEN_WRITE_FAILED: - return cache_open_write_failed(contp, edata); - - case TS_EVENT_VCONN_WRITE_COMPLETE: - return write_vconn_write_complete(contp, edata); - - default: - TSAssert(!"Unexpected event"); - } - - return 0; -} - -/* Copy content from the input buffer to the output buffer without - * modification and feed it through the message digest at the same - * time. - * - * 1. Check if we are "closed" before doing anything else to avoid - * errors. - * - * 2. Then deal with any input that's available now. - * - * 3. Check if the input is complete after dealing with any - * available input in case it was the last of it. If it is - * complete, tell downstream, thank upstream, and finish - * computing the digest. Otherwise either wait for more input - * or abort if upstream is "closed". - * - * The handler is guaranteed to get called at least once, even if the - * response is 304 Not Modified, so we are guaranteed an opportunity - * to clean up e.g. data that we allocated when we called - * TSTransformCreate(). - * - * TS_EVENT_VCONN_WRITE_READY and TS_EVENT_VCONN_WRITE_COMPLETE events - * are sent from downstream, e.g. by - * TransformTerminus::handle_event(). TS_EVENT_IMMEDIATE events are - * sent by INKVConnInternal::do_io_write(), - * INKVConnInternal::do_io_close(), and INKVConnInternal::reenable() - * which are called from upstream, e.g. by - * TransformVConnection::do_io_write(), - * TransformVConnection::do_io_close(), and - * HttpTunnel::producer_handler(). - * - * Clean up the output buffer on TS_EVENT_VCONN_WRITE_COMPLETE and not - * before. We are guaranteed a TS_EVENT_VCONN_WRITE_COMPLETE event - * *unless* we are "closed". In that case we instead get a - * TS_EVENT_IMMEDIATE event where TSVConnClosedGet() is one. We'll - * only ever get one event where TSVConnClosedGet() is one and it will - * be our last, so we *must* check for this case and clean up then - * too. Because we'll only ever get one such event and it will be our - * last, there's no risk of double freeing. - * - * The response headers get sent when TSVConnWrite() gets called and - * not before. (We could potentially edit them until then.) - * - * The events say nothing about the state of the input. Gather this - * instead from TSVConnClosedGet(), TSVIOReaderGet(), and - * TSVIONTodoGet() and handle the end of the input independently from - * the TS_EVENT_VCONN_WRITE_COMPLETE event from downstream. - * - * When TSVConnClosedGet() is one, *we* are "closed". We *must* check - * for this case, if only to clean up allocated data. Some state is - * already inconsistent. (This happens when the response is 304 Not - * Modified or when the client or origin disconnect before the message - * is complete.) - * - * When TSVIOReaderGet() is NULL, upstream is "closed". In that case - * it's clearly an error to call TSIOBufferReaderAvail(), it's also an - * error at that point to send any events upstream with TSContCall(). - * (This happens when the content length is zero or when we get the - * final chunk of a chunked response.) - * - * The input is complete only when TSVIONTodoGet() is zero. (Don't - * update the downstream nbytes otherwise!) Update the downstream - * nbytes when the input is complete in case the response is chunked - * (in which case nbytes is unknown until then). Downstream will - * (normally) send the TS_EVENT_VCONN_WRITE_COMPLETE event (and the - * final chunk if the response is chunked) when ndone equals nbytes - * and not before. - * - * Send our own TS_EVENT_VCONN_WRITE_COMPLETE event upstream when the - * input is complete otherwise HttpSM::update_stats() won't get called - * and the transaction won't get logged. (If there are upstream - * transformations they won't get a chance to clean up otherwise!) - * - * Summary of the cases each event can fall into: - * - * Closed *We* are "closed". Clean up allocated data. - * │ - * ├ Start First (and last) time the handler was called. - * │ (This happens when the response is 304 Not - * │ Modified.) - * │ - * └ Not start (This happens when the client or origin disconnect - * before the message is complete.) - * - * Start First time the handler was called. Initialize - * │ data here because we can't call TSVConnWrite() - * │ before TS_HTTP_RESPONSE_TRANSFORM_HOOK. - * │ - * ├ Content length - * │ - * └ Chunked response - * - * Upstream closed - * (This happens when the content length is zero or - * when we get the final chunk of a chunked - * response.) - * - * Available input - * - * Input complete - * │ - * ├ Deja vu There might be multiple TS_EVENT_IMMEDIATE events - * │ between the end of the input and the - * │ TS_EVENT_VCONN_WRITE_COMPLETE event from - * │ downstream. - * │ - * └ Not deja vu - * Tell downstream and thank upstream. - * - * Downstream complete - * Clean up the output buffer. */ - -static int -vconn_write_ready(TSCont contp, void * /* edata ATS_UNUSED */) -{ - const char *value; - int64_t length; - - char digest[32]; /* SHA-256 */ - - TransformData *transform_data = static_cast(TSContDataGet(contp)); - - /* Check if we are "closed" before doing anything else to avoid - * errors. We *must* check for this case, if only to clean up - * allocated data. Some state is already inconsistent. (This - * happens if the response is 304 Not Modified or if the client or - * origin disconnect before the message is complete.) */ - int closed = TSVConnClosedGet(contp); - if (closed) { - TSContDestroy(contp); - - /* Avoid failed assert "sdk_sanity_check_iocore_structure(bufp) == - * TS_SUCCESS" in TSIOBufferDestroy() if the response is 304 Not - * Modified */ - if (transform_data->output_bufp) { - TSIOBufferDestroy(transform_data->output_bufp); - } - - TSfree(transform_data); - - return 0; - } - - TSVIO input_viop = TSVConnWriteVIOGet(contp); - - /* Initialize data here because we can't call TSVConnWrite() before - * TS_HTTP_RESPONSE_TRANSFORM_HOOK */ - if (!transform_data->output_bufp) { - TSVConn output_connp = TSTransformOutputVConnGet(contp); - - transform_data->output_bufp = TSIOBufferCreate(); - TSIOBufferReader readerp = TSIOBufferReaderAlloc(transform_data->output_bufp); - - /* Determines the Content-Length header (or a chunked response) */ - - /* Reentrant! Avoid failed assert "nbytes >= 0" if the response - * is chunked. */ - int nbytes = TSVIONBytesGet(input_viop); - transform_data->output_viop = TSVConnWrite(output_connp, contp, readerp, nbytes < 0 ? INT64_MAX : nbytes); - - SHA256_Init(&transform_data->c); - } - - /* Then deal with any input that's available now. Avoid failed - * assert "sdk_sanity_check_iocore_structure(readerp) == TS_SUCCESS" - * in TSIOBufferReaderAvail() if the content length is zero or when - * we get the final chunk of a chunked response. */ - TSIOBufferReader readerp = TSVIOReaderGet(input_viop); - if (readerp) { - int avail = TSIOBufferReaderAvail(readerp); - if (avail) { - TSIOBufferCopy(transform_data->output_bufp, readerp, avail, 0); - - /* Feed content to the message digest */ - TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp); - while (blockp) { - /* No allocation? */ - value = TSIOBufferBlockReadStart(blockp, readerp, &length); - SHA256_Update(&transform_data->c, value, length); - - blockp = TSIOBufferBlockNext(blockp); - } - - TSIOBufferReaderConsume(readerp, avail); - - /* Call TSVIONDoneSet() for TSVIONTodoGet() condition */ - int ndone = TSVIONDoneGet(input_viop); - TSVIONDoneSet(input_viop, ndone + avail); - } - } - - /* Check if the input is complete after dealing with any available - * input in case it was the last of it */ - int ntodo = TSVIONTodoGet(input_viop); - if (ntodo) { - TSVIOReenable(transform_data->output_viop); - - TSContCall(TSVIOContGet(input_viop), TS_EVENT_VCONN_WRITE_READY, input_viop); - - /* Don't finish computing the digest (and tell downstream and thank - * upstream) more than once! There might be multiple - * TS_EVENT_IMMEDIATE events between the end of the input and the - * TS_EVENT_VCONN_WRITE_COMPLETE event from downstream, e.g. - * INKVConnInternal::reenable() is called by - * HttpTunnel::producer_handler() when more input is available and - * TransformVConnection::do_io_shutdown() is called by - * HttpSM::tunnel_handler_transform_write() when we send our own - * TS_EVENT_VCONN_WRITE_COMPLETE event upstream. */ - } else if (transform_data->txnp) { - int ndone = TSVIONDoneGet(input_viop); - TSVIONBytesSet(transform_data->output_viop, ndone); - - TSVIOReenable(transform_data->output_viop); - - /* Avoid failed assert "c->alive == true" in TSContCall() if the - * content length is zero or when we get the final chunk of a - * chunked response */ - if (readerp) { - TSContCall(TSVIOContGet(input_viop), TS_EVENT_VCONN_WRITE_COMPLETE, input_viop); - } - - /* Write the digest to the cache */ - - SHA256_Final(reinterpret_cast(digest), &transform_data->c); - - WriteData *write_data = static_cast(TSmalloc(sizeof(WriteData))); - write_data->txnp = transform_data->txnp; - - /* Don't finish computing the digest more than once! */ - transform_data->txnp = nullptr; - - write_data->key = TSCacheKeyCreate(); - if (TSCacheKeyDigestSet(write_data->key, digest, sizeof(digest)) != TS_SUCCESS) { - TSCacheKeyDestroy(write_data->key); - TSfree(write_data); - - return 0; - } - - /* Can't reuse the TSTransformCreate() continuation because we - * don't know whether to destroy it in - * cache_open_write()/cache_open_write_failed() */ - contp = TSContCreate(write_handler, nullptr); - TSContDataSet(contp, write_data); - - /* Reentrant! */ - TSCacheWrite(contp, write_data->key); - } - - return 0; -} - -/* TSTransformCreate() handler: Compute the SHA-256 digest of the - * content */ - -static int -transform_handler(TSCont contp, TSEvent event, void *edata) -{ - switch (event) { - case TS_EVENT_IMMEDIATE: - case TS_EVENT_VCONN_WRITE_READY: - return vconn_write_ready(contp, edata); - - case TS_EVENT_VCONN_WRITE_COMPLETE: - TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1); - break; - default: - TSAssert(!"Unexpected event"); - } - - return 0; -} - -/* Compute the SHA-256 digest of the content, write it to the cache - * and store the request URL at that key */ - -static int -http_read_response_hdr(TSCont /* contp ATS_UNUSED */, void *edata) -{ - TransformData *data = static_cast(TSmalloc(sizeof(TransformData))); - data->txnp = static_cast(edata); - - /* Can't initialize data here because we can't call TSVConnWrite() - * before TS_HTTP_RESPONSE_TRANSFORM_HOOK */ - data->output_bufp = nullptr; - - TSVConn connp = TSTransformCreate(transform_handler, data->txnp); - TSContDataSet(connp, data); - - TSHttpTxnHookAdd(data->txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - - return 0; -} - -/* Implement TS_HTTP_SEND_RESPONSE_HDR_HOOK to check the Location and - * Digest headers */ - -/* Read the URL stored at the digest */ - -static int -cache_open_read(TSCont contp, void *edata) -{ - SendData *data = static_cast(TSContDataGet(contp)); - data->connp = static_cast(edata); - - data->cache_bufp = TSIOBufferCreate(); - - /* Reentrant! Reuse the TSCacheRead() continuation. */ - TSVConnRead(data->connp, contp, data->cache_bufp, INT64_MAX); - - return 0; -} - -/* Do nothing, just reenable the response */ - -static int -cache_open_read_failed(TSCont contp, void * /* edata ATS_UNUSED */) -{ - SendData *data = static_cast(TSContDataGet(contp)); - TSContDestroy(contp); - - TSCacheKeyDestroy(data->key); - - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc); - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->location_loc); - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - TSfree(data); - - return 0; -} - -/* TSCacheRead() handler: Check if the URL stored at the digest is - * cached */ - -static int -rewrite_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */) -{ - SendData *data = static_cast(TSContDataGet(contp)); - TSContDestroy(contp); - - TSCacheKeyDestroy(data->key); - - switch (event) { - /* Yes: Rewrite the Location header and reenable the response */ - case TS_EVENT_CACHE_OPEN_READ: - - TSMimeHdrFieldValuesClear(data->resp_bufp, data->hdr_loc, data->location_loc); - TSMimeHdrFieldValueStringInsert(data->resp_bufp, data->hdr_loc, data->location_loc, -1, data->value, data->length); - - break; - - /* No: Do nothing, just reenable the response */ - case TS_EVENT_CACHE_OPEN_READ_FAILED: - break; - - default: - TSAssert(!"Unexpected event"); - } - - TSIOBufferDestroy(data->cache_bufp); - - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->location_loc); - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - TSfree(data); - - return 0; -} - -/* Read the URL stored at the digest */ - -static int -vconn_read_ready(TSCont contp, void * /* edata ATS_UNUSED */) -{ - SendData *data = static_cast(TSContDataGet(contp)); - TSContDestroy(contp); - - TSVConnClose(data->connp); - - TSIOBufferReader readerp = TSIOBufferReaderAlloc(data->cache_bufp); - - TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp); - - /* No allocation, freed with data->cache_bufp? */ - const char *value = data->value = TSIOBufferBlockReadStart(blockp, readerp, &data->length); - - /* The start pointer is both an input and an output parameter. - * After a successful parse the start pointer equals the end - * pointer. */ - if (TSUrlParse(data->resp_bufp, data->url_loc, &value, value + data->length) != TS_PARSE_DONE) { - TSIOBufferDestroy(data->cache_bufp); - - TSCacheKeyDestroy(data->key); - - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc); - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->location_loc); - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - TSfree(data); - - return 0; - } - - if (TSCacheKeyDigestFromUrlSet(data->key, data->url_loc) != TS_SUCCESS) { - TSIOBufferDestroy(data->cache_bufp); - - TSCacheKeyDestroy(data->key); - - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc); - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->location_loc); - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - TSfree(data); - - return 0; - } - - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc); - - /* Check if the URL stored at the digest is cached */ - - contp = TSContCreate(rewrite_handler, nullptr); - TSContDataSet(contp, data); - - /* Reentrant! (Particularly in case of a cache miss.) - * rewrite_handler() will clean up the TSVConnRead() buffer so be - * sure to close this virtual connection or CacheVC::openReadMain() - * will continue operating on it! */ - TSCacheRead(contp, data->key); - - return 0; -} - -/* TSCacheRead() and TSVConnRead() handler: Check if the digest - * already exists in the cache */ - -static int -digest_handler(TSCont contp, TSEvent event, void *edata) -{ - switch (event) { - /* Yes: Read the URL stored at that key */ - case TS_EVENT_CACHE_OPEN_READ: - return cache_open_read(contp, edata); - - /* No: Do nothing, just reenable the response */ - case TS_EVENT_CACHE_OPEN_READ_FAILED: - return cache_open_read_failed(contp, edata); - - case TS_EVENT_VCONN_READ_READY: - return vconn_read_ready(contp, edata); - - default: - TSAssert(!"Unexpected event"); - } - - return 0; -} - -/* TSCacheRead() handler: Check if the Location URL is already cached */ - -static int -location_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */) -{ - const char *value; - int length; - - char digest[33]; /* ats_base64_decode_dstlen() */ - - SendData *data = static_cast(TSContDataGet(contp)); - TSContDestroy(contp); - - switch (event) { - /* Yes: Do nothing, just reenable the response */ - case TS_EVENT_CACHE_OPEN_READ: - break; - - /* No: Check if the digest already exists in the cache */ - case TS_EVENT_CACHE_OPEN_READ_FAILED: - - /* No allocation, freed with data->resp_bufp? */ - value = TSMimeHdrFieldValueStringGet(data->resp_bufp, data->hdr_loc, data->digest_loc, data->idx, &length); - if (TSBase64Decode(value + 8, length - 8, reinterpret_cast(digest), sizeof(digest), nullptr) != TS_SUCCESS || - TSCacheKeyDigestSet(data->key, digest, 32 /* SHA-256 */) != TS_SUCCESS) { - break; - } - - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->digest_loc); - - /* Check if the digest already exists in the cache */ - - contp = TSContCreate(digest_handler, nullptr); - TSContDataSet(contp, data); - - /* Reentrant! */ - TSCacheRead(contp, data->key); - - return 0; - - default: - TSAssert(!"Unexpected event"); - } - - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->digest_loc); - - TSCacheKeyDestroy(data->key); - - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc); - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->location_loc); - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - TSfree(data); - - return 0; -} - -/* Use TSCacheRead() to check if the URL in the Location header is - * already cached. If not, potentially rewrite that header. Do this - * after responses are cached because the cache will change. */ - -static int -http_send_response_hdr(TSCont contp, void *edata) -{ - const char *value; - int length; - - SendData *data = static_cast(TSmalloc(sizeof(SendData))); - data->txnp = static_cast(edata); - - if (TSHttpTxnClientRespGet(data->txnp, &data->resp_bufp, &data->hdr_loc) != TS_SUCCESS) { - TSError("[metalink] Couldn't retrieve client response header"); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - TSfree(data); - - return 0; - } - - /* If Instance Digests are not provided by the Metalink servers, the - * Link header fields pertaining to this specification MUST be - * ignored */ - - /* Metalinks contain whole file hashes as described in Section 6, - * and MUST include SHA-256, as specified in [FIPS-180-3] */ - - /* Assumption: We want to minimize cache reads, so check first that - * - * 1. the response has a Location header and - * - * 2. the response has a Digest header. - * - * Then scan if the URL or digest already exist in the cache. */ - - /* If the response has a Location header */ - data->location_loc = TSMimeHdrFieldFind(data->resp_bufp, data->hdr_loc, TS_MIME_FIELD_LOCATION, TS_MIME_LEN_LOCATION); - if (!data->location_loc) { - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - TSfree(data); - - return 0; - } - - TSUrlCreate(data->resp_bufp, &data->url_loc); - - /* If we can't parse or lookup the Location URL, should we still - * check if the response has a Digest header? No: Can't parse or - * lookup the URL in the Location header is an error. */ - - /* No allocation, freed with data->resp_bufp? */ - value = TSMimeHdrFieldValueStringGet(data->resp_bufp, data->hdr_loc, data->location_loc, -1, &length); - if (TSUrlParse(data->resp_bufp, data->url_loc, &value, value + length) != TS_PARSE_DONE) { - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc); - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->location_loc); - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - TSfree(data); - - return 0; - } - - data->key = TSCacheKeyCreate(); - if (TSCacheKeyDigestFromUrlSet(data->key, data->url_loc) != TS_SUCCESS) { - TSCacheKeyDestroy(data->key); - - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc); - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->location_loc); - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - TSfree(data); - - return 0; - } - - /* ... and a Digest header */ - data->digest_loc = TSMimeHdrFieldFind(data->resp_bufp, data->hdr_loc, "Digest", 6); - while (data->digest_loc) { - int count = TSMimeHdrFieldValuesCount(data->resp_bufp, data->hdr_loc, data->digest_loc); - for (data->idx = 0; data->idx < count; data->idx += 1) { - /* No allocation, freed with data->resp_bufp? */ - value = TSMimeHdrFieldValueStringGet(data->resp_bufp, data->hdr_loc, data->digest_loc, data->idx, &length); - if (length < 8 + 44 /* 32 bytes, Base64 */ || strncasecmp(value, "SHA-256=", 8)) { - continue; - } - - /* Check if the Location URL is already cached */ - - contp = TSContCreate(location_handler, nullptr); - TSContDataSet(contp, data); - - /* Reentrant! */ - TSCacheRead(contp, data->key); - - return 0; - } - - TSMLoc next_loc = TSMimeHdrFieldNextDup(data->resp_bufp, data->hdr_loc, data->digest_loc); - - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->digest_loc); - - data->digest_loc = next_loc; - } - - /* Didn't find a Digest header, just reenable the response */ - - TSCacheKeyDestroy(data->key); - - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->url_loc); - TSHandleMLocRelease(data->resp_bufp, data->hdr_loc, data->location_loc); - TSHandleMLocRelease(data->resp_bufp, TS_NULL_MLOC, data->hdr_loc); - - TSHttpTxnReenable(data->txnp, TS_EVENT_HTTP_CONTINUE); - TSfree(data); - - return 0; -} - -static int -handler(TSCont contp, TSEvent event, void *edata) -{ - switch (event) { - case TS_EVENT_HTTP_READ_RESPONSE_HDR: - return http_read_response_hdr(contp, edata); - - case TS_EVENT_HTTP_SEND_RESPONSE_HDR: - return http_send_response_hdr(contp, edata); - - default: - TSAssert(!"Unexpected event"); - } - - return 0; -} - -void -TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */[]) -{ - TSPluginRegistrationInfo info; - - info.plugin_name = (char *)"metalink"; - info.vendor_name = (char *)"Apache Software Foundation"; - info.support_email = (char *)"dev@trafficserver.apache.org"; - - if (TSPluginRegister(&info) != TS_SUCCESS) { - TSError("[metalink] Plugin registration failed"); - } - - TSCont contp = TSContCreate(handler, nullptr); - - TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, contp); - TSHttpHookAdd(TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp); -} diff --git a/plugins/experimental/metalink/test/chunkedEncoding b/plugins/experimental/metalink/test/chunkedEncoding deleted file mode 100755 index e2c26139a51..00000000000 --- a/plugins/experimental/metalink/test/chunkedEncoding +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.web import http -from twisted.internet import error, protocol, reactor, tcp - -print '''1..1 chunkedEncoding -# The proxy forwards the final chunk at the end of a chunked response''' - - -def callback(): - print 'not ok 1 - No final chunk yet' - - reactor.stop() - - -reactor.callLater(2, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.write('chunkedEncoding') - - # If the proxy reads the final chunk before it sends the - # response headers, it may send a Content-Length header vs. a - # chunked response - reactor.callLater(1, ctx.finish) - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - Did the proxy crash? (The client connection closed.)' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleHeader(ctx, k, v): - if k.lower() == 'content-length': - print 'not ok 1 - Got a Content-Length header vs. a chunked response' - - # No hope of a final chunk now - reactor.stop() - - # Avoid calling undefined handleResponse() at the end of the - # message (if the proxy sent a Content-Length header vs. a chunked - # response). (Override connectionLost() when the proxy crashes or - # we stop the reactor.) - # - # Data that was already received will get processed (the end of - # the headers), then shutdown events will fire (connections will - # get closed), and then finally the reactor will grind to a halt. - def handleResponseEnd(ctx): - pass - - def handleResponsePart(ctx, data): - if data.endswith('0\r\n\r\n'): - print 'ok 1 - Got the final chunk' - - reactor.stop() - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/chunkedEncodingDisconnect b/plugins/experimental/metalink/test/chunkedEncodingDisconnect deleted file mode 100755 index 0fa3bc193bf..00000000000 --- a/plugins/experimental/metalink/test/chunkedEncodingDisconnect +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 chunkedEncodingDisconnect -# The proxy closes the client connection and doesn't send a final -# chunk if the origin disconnects without sending one''' - - -def callback(): - print 'not ok 1 - The client was left hanging' - - reactor.stop() - - -reactor.callLater(2, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.write('chunkedEncodingDisconnect') - - # If the origin disconnects before the proxy sends the - # response headers, the proxy may send a Content-Length header - # vs. a chunked response - reactor.callLater(1, ctx.transport.loseConnection) - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'ok 1 - The client connection closed' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleHeader(ctx, k, v): - if k.lower() == 'content-length': - print 'not ok 1 - Got a Content-Length header vs. a chunked response' - - # Who cares what happens now? - reactor.stop() - - # Avoid calling undefined handleResponse() at the end of the - # message (if the proxy sent a Content-Length header vs. a chunked - # response). (Override connectionLost() when the proxy closes the - # client connection or we stop the reactor.) - def handleResponseEnd(ctx): - pass - - def handleResponsePart(ctx, data): - if data.endswith('0\r\n\r\n'): - print 'not ok 1 - Got a final chunk' - - # Who cares what happens now? - reactor.stop() - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/clientDisconnect b/plugins/experimental/metalink/test/clientDisconnect deleted file mode 100755 index af2258a5735..00000000000 --- a/plugins/experimental/metalink/test/clientDisconnect +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 clientDissconnect -# The proxy doesn't crash if the client disconnects prematurely''' - - -def callback(): - print 'not ok 1 - Why didn\'t the test finish yet?' - - reactor.stop() - - -reactor.callLater(3, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.write('clientDisconnect') - - # The proxy crashes only after the response is complete - def callback(): - try: - ctx.finish() - - except RuntimeError: - pass - - # Open another connection - class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - print 'not ok 1 - Did the proxy crash? (Can\'t open another connection to it.)' - - reactor.stop() - - class protocol(protocol.Protocol): - def connectionMade(ctx): - print 'ok 1 - The proxy didn\'t crash (opened another connection to it)' - - reactor.stop() - - reactor.callLater(1, tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect) - - reactor.callLater(1, callback) - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(protocol.Protocol): - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - # Disconnect after the proxy sends the response headers - reactor.callLater(1, ctx.transport.loseConnection) - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/contentLength b/plugins/experimental/metalink/test/contentLength deleted file mode 100755 index f3bab947f80..00000000000 --- a/plugins/experimental/metalink/test/contentLength +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 contentLength -# The proxy forwards the Content-Length header to the client''' - - -def callback(): - print 'not ok 1 - Why didn\'t the test finish yet?' - - reactor.stop() - - -reactor.callLater(1, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.setHeader('Content-Length', 13) - ctx.write('contentLength') - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - Did the proxy crash? (The client connection closed.)' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleEndHeaders(ctx): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - No Content-Length header' - - def handleHeader(ctx, k, v): - if k.lower() == 'content-length': - if v != '13': - print 'not', - - print 'ok 1 - Content-Length header' - - reactor.stop() - - # Avoid calling undefined handleResponse() at the end of the - # message. (Override connectionLost() when the proxy crashes or - # we stop the reactor.) - # - # Data that was already received will get processed (the end of - # the headers), then shutdown events will fire (connections will - # get closed), and then finally the reactor will grind to a halt. - def handleResponseEnd(ctx): - pass - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/contentLengthDisconnect b/plugins/experimental/metalink/test/contentLengthDisconnect deleted file mode 100755 index cb39cd36997..00000000000 --- a/plugins/experimental/metalink/test/contentLengthDisconnect +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..2 contentLengthDisconnect -# The proxy closes the client connection if the origin disconnects -# prematurely''' - - -def callback(): - print 'not ok 2 - The client was left hanging' - - reactor.stop() - - -reactor.callLater(2, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.setHeader('Content-Length', 24) - ctx.write('contentLengthDisconnect') - - # If the origin disconnects before the proxy sends the - # response headers, the proxy may send the wrong - # Content-Length header - reactor.callLater(1, ctx.transport.loseConnection) - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'ok 2 - The client connection closed' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleHeader(ctx, k, v): - if k.lower() == 'content-length': - if v != '24': - print 'not', - - # Who cares what happens now? - reactor.stop() - - print 'ok 1 - Content-Length header' - - # Avoid calling undefined handleResponse() at the end of the - # message (if the proxy sent the wrong Content-Length header). - # (Override connectionLost() when the proxy closes the client - # connection or we stop the reactor.) - def handleResponseEnd(ctx): - pass - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect b/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect deleted file mode 100755 index 8db9e4e0712..00000000000 --- a/plugins/experimental/metalink/test/finalChunkedEncodingDisconnect +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 finalChunkEncodingDisconnect -# The proxy forwards the final chunk even if the origin disconnects -# immediately afterward''' - - -def callback(): - print 'not ok 1 - No final chunk yet' - - reactor.stop() - - -reactor.callLater(2, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.write('finalChunkedEncodingDisconnect') - - # If the proxy reads the final chunk before it sends the - # response headers, it may send a Content-Length header vs. a - # chunked response - def callback(): - try: - ctx.finish() - - except RuntimeError: - print 'not ok 1 - Did the proxy crash? (The origin connection closed.)' - - reactor.stop() - - else: - ctx.transport.loseConnection() - - reactor.callLater(1, callback) - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - Did the proxy crash? (The client connection closed.)' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleHeader(ctx, k, v): - if k.lower() == 'content-length': - print 'not ok 1 - Got a Content-Length header vs. a chunked response' - - # No hope of a final chunk now - reactor.stop() - - # Avoid calling undefined handleResponse() at the end of the - # message (if the proxy sent a Content-Length header vs. a chunked - # response). (Override connectionLost() when the proxy crashes or - # we stop the reactor.) - # - # Data that was already received will get processed (the end of - # the headers), then shutdown events will fire (connections will - # get closed), and then finally the reactor will grind to a halt. - def handleResponseEnd(ctx): - pass - - def handleResponsePart(ctx, data): - if data.endswith('0\r\n\r\n'): - print 'ok 1 - Got the final chunk' - - reactor.stop() - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/headers b/plugins/experimental/metalink/test/headers deleted file mode 100755 index b6451e46a9b..00000000000 --- a/plugins/experimental/metalink/test/headers +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 headers -# The response isn't held up until the origin starts sending content''' - - -def callback(): - print 'not ok 1 - No response yet' - - reactor.stop() - - -reactor.callLater(1, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.write('') - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - Did the proxy crash? (The client connection closed.)' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleStatus(ctx, version, status, message): - print 'ok 1 - Got the response status' - - reactor.stop() - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/http09 b/plugins/experimental/metalink/test/http09 deleted file mode 100755 index 0e7e0ef42e3..00000000000 --- a/plugins/experimental/metalink/test/http09 +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python - -# 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. - -# http://www.w3.org/Protocols/HTTP/AsImplemented -# -# The proxy crashes only after the response is complete. It closes -# the client connection whether it crashes or not because an HTTP/0.9 -# response is complete only after the origin closes its connection, -# and then the proxy normally does the same thing to the client -# connection (although it upgrades the response to HTTP/1.1). So the -# only way to check that the proxy didn't crash is to open another -# connection. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 http09 -# The proxy doesn't crash on an HTTP/0.9 response''' - - -def callback(): - print 'not ok 1 - Why didn\'t the test finish yet?' - - reactor.stop() - - -reactor.callLater(2, callback) - - -class factory(protocol.Factory): - class protocol(protocol.Protocol): - def connectionMade(ctx): - ctx.transport.write('http09\r\n') - - # The proxy crashes only after the response is complete - ctx.transport.loseConnection() - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(protocol.Protocol): - def connectionLost(ctx, reason): - - # Open another connection - class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - print 'not ok 1 - Did the proxy crash? (Can\'t open another connection to it.)' - - reactor.stop() - - class protocol(protocol.Protocol): - def connectionMade(ctx): - print 'ok 1 - The proxy didn\'t crash (opened another connection to it)' - - reactor.stop() - - reactor.callLater(1, tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect) - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/location b/plugins/experimental/metalink/test/location deleted file mode 100755 index 4a0b7704e1f..00000000000 --- a/plugins/experimental/metalink/test/location +++ /dev/null @@ -1,136 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..2 location -# The proxy rewrites the Location header if the file is already cached''' - - -def callback(): - print 'not ok 1 - Why didn\'t the test finish yet?' - - reactor.stop() - - -reactor.callLater(1, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - if target == '/location': - - # Satisfy every case of - # proxy.config.http.cache.required_headers - ctx.setHeader('Cache-Control', 'max-age=1') - - ctx.write('location') - ctx.finish() - - else: - - ctx.setHeader('Digest', 'SHA-256=5urqGOiF4QeIKbVt80iWvlq1FDno8LoAyxYkssVywQ4=') - ctx.setHeader('Location', 'http://example.com') - ctx.finish() - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - Did the proxy crash? (The client connection closed.)' - - # Get a response with a Location and a Digest header and check - # that the Location header is not rewritten. Then get the same - # response after caching a matching file from a different URL and - # check that this time the header is rewritten. - def connectionMade(ctx): - ctx.transport.write( - 'GET {0}:{1} HTTP/1.1\r\n\r\nGET {0}:{1}/location HTTP/1.1\r\n\r\nGET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleResponsePart(ctx, data): - try: - h, r = data.split('0\r\n\r\n', 1) - - except ValueError: - pass - - else: - - ctx.firstLine = True - ctx.setLineMode(r) - - def handleStatus(ctx, version, status, message): - def handleHeader(k, v): - if k.lower() == 'location': - if v != 'http://example.com': - print 'not', - - print 'ok 1 - Before' - - ctx.handleHeader = handleHeader - - def handleStatus(version, status, message): - del ctx.handleHeader - - def handleStatus(version, status, message): - def handleHeader(k, v): - if k.lower() == 'location': - if v != 'http://{0}:{1}/location'.format(*origin.socket.getsockname()): - print 'not', - - print 'ok 2 - After' - - reactor.stop() - - ctx.handleHeader = handleHeader - - ctx.handleStatus = handleStatus - - ctx.handleStatus = handleStatus - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/longer b/plugins/experimental/metalink/test/longer deleted file mode 100755 index d7e48f36f93..00000000000 --- a/plugins/experimental/metalink/test/longer +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python - -# 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. - -# Unlike the contentLength test, don't stop the reactor at the end of -# the headers. Give the proxy time to choke. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 longer -# The proxy doesn't choke if the origin sends more content than it -# advertised''' - - -def callback(): - print 'not ok 1 - No Content-Length header' - - reactor.stop() - - -reactor.callLater(1, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.setHeader('Content-Length', 1) - ctx.write('longer') - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - Did the proxy crash? (The client connection closed.)' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleHeader(ctx, k, v): - if k.lower() == 'content-length': - if v != '1': - print 'not', - - print 'ok 1 - Content-Length header' - - reactor.stop() - - # Avoid calling undefined handleResponse() at the end of the - # message. (Override connectionLost() when the proxy crashes or - # we stop the reactor.) - # - # Data that was already received will get processed (the end of - # the headers), then shutdown events will fire (connections will - # get closed), and then finally the reactor will grind to a halt. - def handleResponseEnd(ctx): - pass - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/notCacheable b/plugins/experimental/metalink/test/notCacheable deleted file mode 100755 index 217d44dab65..00000000000 --- a/plugins/experimental/metalink/test/notCacheable +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 notCacheable -# The digest of a file that wasn't cacheable doesn't crash the proxy''' - - -def callback(): - print 'not ok 1 - Why didn\'t the test finish yet?' - - reactor.stop() - - -reactor.callLater(1, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - if target == '/notCacheable': - - ctx.write('notCacheable') - ctx.finish() - - else: - - ctx.setHeader('Digest', 'SHA-256=BSg5n9c6XBC3jySKsXViB71jhPIoRo3AbCC/gtNlt6k=') - ctx.setHeader('Location', 'http://example.com') - ctx.finish() - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - Did the proxy crash? (The client connection closed.)' - - def connectionMade(ctx): - - # A cache MUST NOT store a response to any request, unless: The - # request method is understood by the cache and defined as being - # cacheable, - ctx.transport.write( - 'NOTCACHEABLE {0}:{1}/notCacheable HTTP/1.1\r\n\r\nGET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleResponsePart(ctx, data): - try: - h, r = data.split('0\r\n\r\n', 1) - - except ValueError: - pass - - else: - - ctx.firstLine = True - ctx.setLineMode(r) - - def handleStatus(ctx, version, status, message): - def handleStatus(version, status, message): - print 'ok 1 - The proxy didn\'t crash (got a response status)' - - reactor.stop() - - ctx.handleStatus = handleStatus - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/notModified b/plugins/experimental/metalink/test/notModified deleted file mode 100755 index 2d78433dfd9..00000000000 --- a/plugins/experimental/metalink/test/notModified +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..2 notModified -# The proxy doesn't crash on a 304 Not Modified response''' - - -def callback(): - print 'ok 2 - The proxy didn\'t crash (the client connection didn\'t close yet)' - - reactor.stop() - - -reactor.callLater(1, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.setResponseCode(304) - ctx.finish() - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - Did the proxy crash? (The client connection closed.)' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleStatus(ctx, version, status, message): - if status != '304': - print 'not', - - print 'ok 1 - 304 Not Modified response status' - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/pipeliningDisconnect b/plugins/experimental/metalink/test/pipeliningDisconnect deleted file mode 100755 index 4943d197879..00000000000 --- a/plugins/experimental/metalink/test/pipeliningDisconnect +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 pipeliningDisconnect -# The proxy doesn't crash if INKVConnInternal::do_io_close() gets -# called after a message is already complete''' - - -def callback(): - print 'ok 1 - Did the connection close before the proxy made the second request?' - - reactor.stop() - - -reactor.callLater(2, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.write('pipeliningDisconnect') - ctx.finish() - - # Open another connection - class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - print 'not ok 1 - Did the proxy crash? (Can\'t open another connection to it.)' - - reactor.stop() - - class protocol(protocol.Protocol): - def connectionMade(ctx): - print 'ok 1 - The proxy didn\'t crash (opened another connection to it)' - - reactor.stop() - - reactor.callLater(1, tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect) - - ctx.channel.requestFactory = requestFactory - - ctx.client = None - ctx.clientproto = version - - ctx.write('pipeliningDisconnect') - ctx.finish() - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(protocol.Protocol): - def connectionMade(ctx): - - # Somehow these magic words frequently cause - # INKVConnInternal::do_io_close() to get called after a message - # is already complete - ctx.transport.write( - 'GET {0}:{1}/pipeliningDisconnect0 HTTP/1.1\r\n\r\nGET {0}:{1}/pipeliningDisconnect1 HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - ctx.transport.loseConnection() - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect b/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect deleted file mode 100755 index f75aeaf7b39..00000000000 --- a/plugins/experimental/metalink/test/shortChunkedEncodingDisconnect +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 shortChunkedEncodingDisconnect -# The proxy closes the client connection and doesn't send a final -# chunk if the origin disconnects without sending one, before the -# proxy sends the response headers''' - - -def callback(): - print 'not ok 1 - The client was left hanging' - - reactor.stop() - - -reactor.callLater(1, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.write('shortChunkedEncodingDisconnect') - - # Disconnect before the proxy sends the response headers - ctx.transport.loseConnection() - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'ok 1 - The client connection closed' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleHeader(ctx, k, v): - if k.lower() == 'content-length': - print 'not ok 1 - Got a Content-Length header vs. a chunked response' - - # Who cares what happens now? - reactor.stop() - - # Avoid calling undefined handleResponse() at the end of the - # message (if the proxy sent a Content-Length header vs. a chunked - # response). (Override connectionLost() when the proxy closes the - # client connection or we stop the reactor.) - def handleResponseEnd(ctx): - pass - - def handleResponsePart(ctx, data): - if data.endswith('0\r\n\r\n'): - print 'not ok 1 - Got a final chunk' - - # Who cares what happens now? - reactor.stop() - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/shortClientDisconnect b/plugins/experimental/metalink/test/shortClientDisconnect deleted file mode 100755 index d78e411eeb7..00000000000 --- a/plugins/experimental/metalink/test/shortClientDisconnect +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 shortClientDisconnect -# The proxy doesn't crash if the client disconnects before the proxy -# sends the response headers''' - - -def callback(): - print 'not ok 1 - Why didn\'t the test finish yet?' - - reactor.stop() - - -reactor.callLater(3, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.write('shortClientDisconnect0') - - def callback(): - ctx.write('shortClientDisconnect1') - - # Open another connection - class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - print 'not ok 1 - Did the proxy crash? (Can\'t open another connection to it.)' - - reactor.stop() - - class protocol(protocol.Protocol): - def connectionMade(ctx): - print 'ok 1 - The proxy didn\'t crash (opened another connection to it)' - - reactor.stop() - - reactor.callLater(1, tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect) - - reactor.callLater(1, callback) - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(protocol.Protocol): - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - # Disconnect before the proxy sends the response headers - ctx.transport.loseConnection() - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/shortContentLengthDisconnect b/plugins/experimental/metalink/test/shortContentLengthDisconnect deleted file mode 100755 index b508d805f19..00000000000 --- a/plugins/experimental/metalink/test/shortContentLengthDisconnect +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..2 shortContentLengthDisconnect -# The proxy sends the right Content-Length header and closes the -# client connection if the origin disconnects before the proxy sends -# the response headers''' - - -def callback(): - print 'not ok 2 - The client was left hanging' - - reactor.stop() - - -reactor.callLater(1, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.setHeader('Content-Length', 29) - ctx.write('shortContentLengthDisconnect') - - # Disconnect before the proxy sends the response headers - ctx.transport.loseConnection() - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'ok 2 - The client connection closed' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleHeader(ctx, k, v): - if k.lower() == 'content-length': - if v != '29': - print 'not', - - # Who cares what happens now? - reactor.stop() - - print 'ok 1 - Content-Length header' - - # Avoid calling undefined handleResponse() at the end of the - # message (if the proxy sent the wrong Content-Length header). - # (Override connectionLost() when the proxy closes the client - # connection or we stop the reactor.) - def handleResponseEnd(ctx): - pass - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/metalink/test/zero b/plugins/experimental/metalink/test/zero deleted file mode 100755 index 18a98c807a4..00000000000 --- a/plugins/experimental/metalink/test/zero +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python - -# 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. - -from twisted.internet import error, protocol, reactor, tcp -from twisted.web import http - -print '''1..1 zero -# The proxy doesn't crash if the Content-Length is zero''' - - -def callback(): - print 'not ok 1 - Why didn\'t the test finish yet?' - - reactor.stop() - - -reactor.callLater(1, callback) - - -class factory(http.HTTPFactory): - class protocol(http.HTTPChannel): - class requestFactory(http.Request): - def requestReceived(ctx, method, target, version): - - ctx.client = None - ctx.clientproto = version - - ctx.setHeader('Content-Length', 0) - ctx.finish() - - -origin = tcp.Port(0, factory()) -origin.startListening() - -print '# Listening on {0}:{1}'.format(*origin.socket.getsockname()) - - -class factory(protocol.ClientFactory): - def clientConnectionFailed(ctx, connector, reason): - - print 'Bail out!' - reason.printTraceback() - - reactor.stop() - - class protocol(http.HTTPClient): - def connectionLost(ctx, reason): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - Did the proxy crash? (The client connection closed.)' - - def connectionMade(ctx): - ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname())) - - def handleEndHeaders(ctx): - try: - reactor.stop() - - except error.ReactorNotRunning: - pass - - else: - print 'not ok 1 - No Content-Length header' - - def handleHeader(ctx, k, v): - if k.lower() == 'content-length': - if v != '0': - print 'not', - - print 'ok 1 - Content-Length header' - - reactor.stop() - - -tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect() - -reactor.run() diff --git a/plugins/experimental/parent_select/CMakeLists.txt b/plugins/experimental/parent_select/CMakeLists.txt deleted file mode 100644 index 66e3c248645..00000000000 --- a/plugins/experimental/parent_select/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -####################### -# -# 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. -# -####################### - -add_atsplugin(parent_select - consistenthash.cc - consistenthash_config.cc - healthstatus.cc - parent_select.cc - strategy.cc -) - -target_link_libraries(parent_select PRIVATE yaml-cpp::yaml-cpp) diff --git a/plugins/experimental/parent_select/Makefile.inc b/plugins/experimental/parent_select/Makefile.inc deleted file mode 100644 index 41e1a5f1de1..00000000000 --- a/plugins/experimental/parent_select/Makefile.inc +++ /dev/null @@ -1,29 +0,0 @@ -# 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. - -pkglib_LTLIBRARIES += experimental/parent_select/parent_select.la - -experimental_parent_select_parent_select_la_SOURCES = \ - experimental/parent_select/strategy.cc \ - experimental/parent_select/healthstatus.cc \ - experimental/parent_select/consistenthash.cc \ - experimental/parent_select/consistenthash_config.cc \ - experimental/parent_select/parent_select.cc - -experimental_parent_select_parent_select_la_LDFLAGS = \ - $(AM_LDFLAGS) - -AM_CPPFLAGS += @YAMLCPP_INCLUDES@ $(TS_INCLUDES) diff --git a/plugins/experimental/parent_select/consistenthash.cc b/plugins/experimental/parent_select/consistenthash.cc deleted file mode 100644 index a154ddc60b1..00000000000 --- a/plugins/experimental/parent_select/consistenthash.cc +++ /dev/null @@ -1,581 +0,0 @@ -/* - * 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. - */ - -#include "strategy.h" -#include "consistenthash.h" -#include "util.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "tscore/HashSip.h" -#include "tscore/ConsistentHash.h" -#include "tscore/ink_assert.h" -#include "ts/ts.h" -#include "ts/remap.h" -#include "ts/parentselectdefs.h" - -namespace -{ -const char *PLNHParentResultStr[] = {"PARENT_UNDEFINED", "PARENT_DIRECT", "PARENT_SPECIFIED", "PARENT_AGENT", "PARENT_FAIL"}; - -// hash_key strings. -constexpr std::string_view hash_key_url = "url"; -constexpr std::string_view hash_key_hostname = "hostname"; -constexpr std::string_view hash_key_path = "path"; -constexpr std::string_view hash_key_path_query = "path+query"; -constexpr std::string_view hash_key_path_fragment = "path+fragment"; -constexpr std::string_view hash_key_cache = "cache_key"; - -static bool -isWrapped(std::vector &wrap_around, uint32_t groups) -{ - bool all_wrapped = true; - for (uint32_t c = 0; c < groups; c++) { - if (wrap_around[c] == false) { - all_wrapped = false; - } - } - return all_wrapped; -} - -void -chTxnToStatusTxn(PLNextHopConsistentHashTxn *txn, PLStatusTxn *statusTxn) -{ - statusTxn->result = txn->result; - statusTxn->retry = txn->retry; -} - -} // namespace - -std::shared_ptr -PLNextHopConsistentHash::chashLookup(const std::shared_ptr &ring, uint32_t cur_ring, - PLNextHopConsistentHashTxn *state, bool *wrapped, uint64_t sm_id, TSMBuffer reqp, TSMLoc url, - TSMLoc parent_selection_url) -{ - uint64_t hash_key = 0; - ATSHash64Sip24 hash; - PLHostRecord *host_rec = nullptr; - ATSConsistentHashIter *iter = &state->chashIter[cur_ring]; - - if (state->chash_init[cur_ring] == false) { - hash_key = getHashKey(sm_id, reqp, url, parent_selection_url, &hash); - host_rec = static_cast(ring->lookup_by_hashval(hash_key, iter, wrapped)); - state->chash_init[cur_ring] = true; - } else { - host_rec = static_cast(ring->lookup(nullptr, iter, wrapped, &hash)); - } - bool wrap_around = *wrapped; - *wrapped = (state->mapWrapped[cur_ring] && *wrapped) ? true : false; - if (!state->mapWrapped[cur_ring] && wrap_around) { - state->mapWrapped[cur_ring] = true; - } - - if (host_rec == nullptr) { - return nullptr; - } else { - std::shared_ptr h = host_groups[host_rec->group_index][host_rec->host_index]; - return h; - } -} - -PLNextHopConsistentHash::~PLNextHopConsistentHash() -{ - PL_NH_Debug(PL_NH_DEBUG_TAG, "destructor called for strategy named: %s", strategy_name.c_str()); -} - -#define PLUGIN_NAME "pparent_select" - -PLNextHopConsistentHash::PLNextHopConsistentHash(const std::string_view name, const YAML::Node &n) - : PLNextHopSelectionStrategy(name, n) -{ - TSDebug("pparent_select", "PLNextHopConsistentHash constructor calling."); - - ATSHash64Sip24 hash; - - try { - if (n["hash_key"]) { - auto hash_key_val = n["hash_key"].Scalar(); - if (hash_key_val == hash_key_url) { - hash_key = PL_NH_URL_HASH_KEY; - } else if (hash_key_val == hash_key_hostname) { - hash_key = PL_NH_HOSTNAME_HASH_KEY; - } else if (hash_key_val == hash_key_path) { - hash_key = PL_NH_PATH_HASH_KEY; - } else if (hash_key_val == hash_key_path_query) { - hash_key = PL_NH_PATH_QUERY_HASH_KEY; - } else if (hash_key_val == hash_key_path_fragment) { - hash_key = PL_NH_PATH_FRAGMENT_HASH_KEY; - } else if (hash_key_val == hash_key_cache) { - hash_key = PL_NH_CACHE_HASH_KEY; - } else { - hash_key = PL_NH_PATH_HASH_KEY; - PL_NH_Note("Invalid 'hash_key' value, '%s', for the strategy named '%s', using default '%s'.", hash_key_val.c_str(), - strategy_name.c_str(), hash_key_path.data()); - } - } - } catch (std::exception &ex) { - throw std::invalid_argument("Error parsing the strategy named '" + strategy_name + "' due to '" + ex.what() + - "', this strategy will be ignored."); - } - - // load up the hash rings. - for (uint32_t i = 0; i < groups; i++) { - std::shared_ptr hash_ring = std::make_shared(); - for (uint32_t j = 0; j < host_groups[i].size(); j++) { - // ATSConsistentHash needs the raw pointer. - PLHostRecord *p = host_groups[i][j].get(); - // need to copy the 'hash_string' or 'hostname' cstring to 'name' for insertion into ATSConsistentHash. - if (!p->hash_string.empty()) { - p->name = const_cast(p->hash_string.c_str()); - } else { - p->name = const_cast(p->hostname.c_str()); - } - p->group_index = host_groups[i][j]->group_index; - p->host_index = host_groups[i][j]->host_index; - hash_ring->insert(p, p->weight, &hash); - PL_NH_Debug(PL_NH_DEBUG_TAG, "Loading hash rings - ring: %d, host record: %d, name: %s, hostname: %s, strategy: %s", i, j, - p->name, p->hostname.c_str(), strategy_name.c_str()); - } - hash.clear(); - rings.push_back(hash_ring); - } - - if (ring_mode == PL_NH_PEERING_RING) { - if (groups == 1) { - if (!go_direct) { - throw std::invalid_argument("ring mode '" + std::string(peering_rings) + - "' go_direct must be true when there is only one host group"); - } - } else if (groups != 2) { - throw std::invalid_argument( - "ring mode '" + std::string(peering_rings) + - "' requires two host groups (peering group and an upstream group), or a single peering group with go_direct"); - } - } -} - -// returns a hash key calculated from the request and 'hash_key' configuration -// parameter. -uint64_t -PLNextHopConsistentHash::getHashKey(uint64_t sm_id, TSMBuffer reqp, TSMLoc url, TSMLoc parent_selection_url, ATSHash64 *h) -{ - int len = 0; - const char *url_string_ref = nullptr; - - // calculate a hash using the selected config. - switch (hash_key) { - case PL_NH_URL_HASH_KEY: - url_string_ref = TSUrlStringGet(reqp, url, &len); - if (url_string_ref && len > 0) { - h->update(url_string_ref, len); - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] url hash string: %s", sm_id, url_string_ref); - } - break; - // hostname hash - case PL_NH_HOSTNAME_HASH_KEY: - url_string_ref = TSUrlHostGet(reqp, url, &len); - if (url_string_ref && len > 0) { - h->update(url_string_ref, len); - } - break; - // path + query string - case PL_NH_PATH_QUERY_HASH_KEY: - url_string_ref = TSUrlPathGet(reqp, url, &len); - h->update("/", 1); - if (url_string_ref && len > 0) { - h->update(url_string_ref, len); - } - url_string_ref = TSUrlHttpQueryGet(reqp, url, &len); - if (url_string_ref && len > 0) { - h->update("?", 1); - h->update(url_string_ref, len); - } - break; - // path + fragment hash - case PL_NH_PATH_FRAGMENT_HASH_KEY: - url_string_ref = TSUrlPathGet(reqp, url, &len); - h->update("/", 1); - if (url_string_ref && len > 0) { - h->update(url_string_ref, len); - } - url_string_ref = TSUrlHttpFragmentGet(reqp, url, &len); - if (url_string_ref && len > 0) { - h->update("?", 1); - h->update(url_string_ref, len); - } - break; - // use the cache key created by the cache-key plugin. - case PL_NH_CACHE_HASH_KEY: - if (parent_selection_url != TS_NULL_MLOC) { - url_string_ref = TSUrlStringGet(reqp, parent_selection_url, &len); - if (url_string_ref && len > 0) { - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] using parent selection over-ride string:'%.*s'.", sm_id, len, url_string_ref); - h->update(url_string_ref, len); - } - } else { - url_string_ref = TSUrlPathGet(reqp, url, &len); - h->update("/", 1); - if (url_string_ref && len > 0) { - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] the parent selection over-ride url is not set, using default path: %s.", sm_id, - url_string_ref); - h->update(url_string_ref, len); - } - } - break; - // use the path as the hash, default. - case PL_NH_PATH_HASH_KEY: - default: - url_string_ref = TSUrlPathGet(reqp, url, &len); - h->update("/", 1); - if (url_string_ref && len > 0) { - h->update(url_string_ref, len); - } - break; - } - - h->final(); - return h->get(); -} - -static void -makeNextParentErr(const char **hostname, size_t *hostname_len, in_port_t *port, bool *retry, bool *no_cache) -{ - *hostname = nullptr; - *hostname_len = 0; - *port = 0; - *retry = false; - *no_cache = false; -} - -void * -PLNextHopConsistentHash::newTxn() -{ - return new PLNextHopConsistentHashTxn(); -} - -void -PLNextHopConsistentHash::deleteTxn(void *txn) -{ - delete static_cast(txn); -} - -void -PLNextHopConsistentHash::next(TSHttpTxn txnp, void *strategyTxn, const char **out_hostname, size_t *out_hostname_len, - in_port_t *out_port, bool *out_retry, bool *out_no_cache, time_t now) -{ - // TODO add logic in the strategy to track when someone is retrying, and not give it out to multiple threads at once, to prevent - // thundering retries See github issue #7485 - - PL_NH_Debug(PL_NH_DEBUG_TAG, "nextParent NH plugin calling"); - - uint32_t const NO_RING_USE_POST_REMAP = uint32_t(0) - 1; - - auto state = static_cast(strategyTxn); - - int64_t sm_id = TSHttpTxnIdGet(txnp); - - TSMBuffer reqp; // TODO verify doesn't need freed - - TSMLoc hdr; - ScopedFreeMLoc hdr_cleanup(&reqp, TS_NULL_MLOC, &hdr); - if (TSHttpTxnClientReqGet(txnp, &reqp, &hdr) == TS_ERROR) { - makeNextParentErr(out_hostname, out_hostname_len, out_port, out_retry, out_no_cache); - return; - } - - TSMLoc parent_selection_url = TS_NULL_MLOC; - ScopedFreeMLoc parent_selection_url_cleanup(&reqp, TS_NULL_MLOC, &parent_selection_url); - if (TSUrlCreate(reqp, &parent_selection_url) != TS_SUCCESS) { - PL_NH_Error("nexthop failed to create url for parent_selection_url"); - makeNextParentErr(out_hostname, out_hostname_len, out_port, out_retry, out_no_cache); - return; - } - if (TSHttpTxnParentSelectionUrlGet(txnp, reqp, parent_selection_url) != TS_SUCCESS) { - parent_selection_url = TS_NULL_MLOC; - } - - TSMLoc url; - ScopedFreeMLoc url_cleanup(&reqp, hdr, &url); - if (TSHttpHdrUrlGet(reqp, hdr, &url) != TS_SUCCESS) { - PL_NH_Error("failed to get header url, cannot find next hop"); - makeNextParentErr(out_hostname, out_hostname_len, out_port, out_retry, out_no_cache); - return; - } - - // TODO is it really worth getting the string out to debug print here? - PL_NH_Debug(PL_NH_DEBUG_TAG, "nextParent NH plugin findNextHop got url 'x'"); - - int64_t retry_time = 0; // = sm->t_state.txn_conf->parent_retry_time; - if (TSHttpTxnConfigIntGet(txnp, TS_CONFIG_HTTP_PARENT_PROXY_RETRY_TIME, &retry_time) != TS_SUCCESS) { - // TODO get and cache on init, to prevent potential runtime failure? - PL_NH_Error("failed to get parent retry time, cannot find next hop"); - makeNextParentErr(out_hostname, out_hostname_len, out_port, out_retry, out_no_cache); - return; - } - - time_t _now = now; - bool nextHopRetry = false; - bool wrapped = false; - std::vector wrap_around(groups, false); - uint32_t cur_ring = 0; // there is a hash ring for each host group - uint32_t lookups = 0; - std::shared_ptr pRec = nullptr; - TSHostStatus host_stat = TSHostStatus::TS_HOST_STATUS_INIT; - std::string_view first_call_host; - int first_call_port = 0; - - const bool firstcall = state->line_number == -1 && state->result == PL_NH_PARENT_UNDEFINED; - - // firstcall indicates that this is the first time the state machine has called findNextHop() for this - // particular transaction so, a parent will be looked up using a hash from the request to locate a - // parent on the consistent hash ring. If not first call, then the transaction was unable to use the parent - // returned from the "firstcall" due to some error so, subsequent calls will not search using a hash but, - // will instead just increment the hash table iterator to find the next parent on the ring - if (firstcall) { - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] firstcall, line_number: %d, result: %s", sm_id, state->line_number, - PLNHParentResultStr[state->result]); - state->line_number = distance; - cur_ring = 0; - for (uint32_t i = 0; i < groups; i++) { - state->chash_init[i] = false; - wrap_around[i] = false; - } - } else { - // not first call, save the previously tried parent. - if (state->hostname) { - first_call_host = state->hostname; - first_call_port = state->port; - } - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] not firstcall, line_number: %d, result: %s", sm_id, state->line_number, - PLNHParentResultStr[state->result]); - switch (ring_mode) { - case PL_NH_ALTERNATE_RING: - if (groups > 1) { - cur_ring = (state->last_group + 1) % groups; - } else { - cur_ring = state->last_group; - } - break; - case PL_NH_PEERING_RING: - if (groups == 1) { - state->last_group = cur_ring = NO_RING_USE_POST_REMAP; - } else { - ink_assert(groups == 2); - // look for the next parent on the - // upstream ring. - state->last_group = cur_ring = 1; - } - break; - case PL_NH_EXHAUST_RING: - default: - if (!wrapped) { - cur_ring = state->last_group; - } else if (groups > 1) { - cur_ring = (state->last_group + 1) % groups; - } - break; - } - } - - if (cur_ring != NO_RING_USE_POST_REMAP) { - do { - // all host groups have been searched and there are no available parents found - if (isWrapped(wrap_around, groups)) { - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] No available parents.", sm_id); - pRec = nullptr; - break; - } - - // search for available parent - std::shared_ptr r = rings[cur_ring]; - pRec = chashLookup(r, cur_ring, state, &wrapped, sm_id, reqp, url, parent_selection_url); - wrap_around[cur_ring] = wrapped; - lookups++; - - TSHostStatus hostStatus; - unsigned int hostStatusReasons; - const bool hostExists = - pRec ? (TSHostStatusGet(pRec->hostname.c_str(), pRec->hostname.size(), &hostStatus, &hostStatusReasons) == TS_SUCCESS) : - false; - - // found a parent - if (pRec) { - bool is_self = TSHostnameIsSelf(pRec->hostname.c_str(), pRec->hostname.size()) == TS_SUCCESS; - host_stat = hostExists ? hostStatus : TSHostStatus::TS_HOST_STATUS_UP; - - // if the config ignore_self_detect is set to true and the host is down due to SELF_DETECT reason - // ignore the down status and mark it as available - if ((host_stat == TS_HOST_STATUS_DOWN && is_self && ignore_self_detect)) { - if (hostStatusReasons == TS_HOST_STATUS_SELF_DETECT) { - host_stat = TS_HOST_STATUS_UP; - } - } - - if (firstcall) { - state->first_choice_status = hostExists ? hostStatus : TSHostStatus::TS_HOST_STATUS_UP; - // if peering and the selected host is myself, change rings and search for an upstream parent. - if (ring_mode == PL_NH_PEERING_RING && (pRec->self || is_self)) { - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] peering ring got self %s - searching for upstream parent", sm_id, - pRec->hostname.c_str()); - if (groups == 1) { - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] peering ring got self %s - 1 group, using host from post-remap URL", - sm_id, pRec->hostname.c_str()); - // use host from post-remap URL - cur_ring = NO_RING_USE_POST_REMAP; - pRec = nullptr; - break; - } else { - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] peering ring got self %s - !1 group, searching upstream ring", sm_id, - pRec->hostname.c_str()); - // switch to and search the upstream ring. - cur_ring = 1; - pRec = nullptr; - continue; - } - } - } else { - // not first call, make sure we're not re-using the same parent, search again if we are. - if (first_call_host.size() > 0 && first_call_host == pRec->hostname && first_call_port == pRec->getPort(scheme)) { - pRec = nullptr; - continue; - } - } - // if the parent is not available check to see if the retry window has expired making it available - // for retry. - if (!pRec->available.load() && host_stat == TS_HOST_STATUS_UP) { - _now == 0 ? _now = time(nullptr) : _now = now; - if ((pRec->failedAt.load() + retry_time) < static_cast(_now)) { - nextHopRetry = true; - state->last_parent = pRec->host_index; - state->last_lookup = pRec->group_index; - state->retry = nextHopRetry; - state->result = PL_NH_PARENT_SPECIFIED; - state->no_cache = false; - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] next hop %s is now retryable", sm_id, pRec->hostname.c_str()); - break; - } - } - - // use the available selected parent - if (pRec->available.load() && host_stat == TS_HOST_STATUS_UP) { - break; - } - } - // try other rings per the ring mode - switch (ring_mode) { - case PL_NH_ALTERNATE_RING: - if (pRec && groups > 0) { - cur_ring = (pRec->group_index + 1) % groups; - } else { - cur_ring = 0; - } - break; - case PL_NH_EXHAUST_RING: - default: - if (wrap_around[cur_ring] && groups > 1) { - cur_ring = (cur_ring + 1) % groups; - } - break; - } - - if (pRec) { - // if the selected host is down, search again. - if (!pRec->available || host_stat == TS_HOST_STATUS_DOWN) { - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] hostname: %s, available: %s, host_stat: %d", sm_id, pRec->hostname.c_str(), - pRec->available ? "true" : "false", host_stat); - pRec = nullptr; - continue; - } - } - } while (!pRec); - - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] Initial parent lookups: %d", sm_id, lookups); - } - - // ---------------------------------------------------------------------------------------------------- - // Validate and return the final result. - // ---------------------------------------------------------------------------------------------------- - - if (pRec && host_stat == TS_HOST_STATUS_UP && (pRec->available.load() || state->retry)) { - state->result = PL_NH_PARENT_SPECIFIED; - state->hostname = pRec->hostname.c_str(); - state->hostname_len = pRec->hostname.size(); - state->last_parent = pRec->host_index; - state->last_lookup = state->last_group = cur_ring; - switch (scheme) { - case PL_NH_SCHEME_NONE: - case PL_NH_SCHEME_HTTP: - state->port = pRec->getPort(scheme); - break; - case PL_NH_SCHEME_HTTPS: - state->port = pRec->getPort(scheme); - break; - } - state->retry = nextHopRetry; - // if using a peering ring mode and the parent selected came from the 'peering' group, - // cur_ring == 0, then if the config allows it, set the flag to not cache the result. - state->no_cache = ring_mode == PL_NH_PEERING_RING && !cache_peer_result && cur_ring == 0; - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] setting do not cache response from a peer per config: %s", sm_id, - (state->no_cache) ? "true" : "false"); - ink_assert(state->hostname != nullptr); - ink_assert(state->port != 0); - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] state->result: %s Chosen parent: %s.%d", sm_id, PLNHParentResultStr[state->result], - state->hostname, state->port); - } else { - state->result = go_direct ? PL_NH_PARENT_DIRECT : PL_NH_PARENT_FAIL; - state->retry = false; - state->hostname = nullptr; - state->hostname_len = 0; - state->port = 0; - state->no_cache = false; - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] state->result: %s set hostname null port 0 retry %d", sm_id, - PLNHParentResultStr[state->result], state->retry); - } - - *out_hostname = state->hostname; - *out_hostname_len = state->hostname_len; - *out_port = state->port; - *out_retry = state->retry; - *out_no_cache = state->no_cache; - - return; -} - -void -PLNextHopConsistentHash::mark(TSHttpTxn txnp, void *strategyTxn, const char *hostname, const size_t hostname_len, - const in_port_t port, const PLNHCmd status, const time_t now) -{ - PL_NH_Debug(PL_NH_DEBUG_TAG, "mark calling"); - auto state = static_cast(strategyTxn); - PLStatusTxn statusTxn; - chTxnToStatusTxn(state, &statusTxn); - return passive_health.mark(txnp, &statusTxn, hostname, hostname_len, port, status, now); -} diff --git a/plugins/experimental/parent_select/consistenthash.h b/plugins/experimental/parent_select/consistenthash.h deleted file mode 100644 index 0f3bea8e560..00000000000 --- a/plugins/experimental/parent_select/consistenthash.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include "strategy.h" -#include "healthstatus.h" - -class PLNextHopSelectionStrategy; - -constexpr const unsigned int PL_NH_MAX_GROUP_RINGS = 5; - -enum PLNHHashKeyType { - PL_NH_URL_HASH_KEY = 0, - PL_NH_HOSTNAME_HASH_KEY, - PL_NH_PATH_HASH_KEY, // default, consistent hash uses the request url path - PL_NH_PATH_QUERY_HASH_KEY, - PL_NH_PATH_FRAGMENT_HASH_KEY, - PL_NH_CACHE_HASH_KEY -}; - -// The transaction state needed by PLNextHopConsistentHash about the last parent found, -// which is needed to find the next parent. -// Does not include the data already in ResponseAction. -// -// TODO initialize? zero? -1? -struct PLNextHopConsistentHashTxn { - PLNHParentResultType result = PL_NH_PARENT_UNDEFINED; - bool chash_init[PL_NH_MAX_GROUP_RINGS] = {false}; - TSHostStatus first_choice_status = TSHostStatus::TS_HOST_STATUS_INIT; - int line_number = -1; - uint32_t last_parent; - uint32_t start_parent; - uint32_t last_group; - bool wrap_around; - bool mapWrapped[2]; - int last_lookup; - ATSConsistentHashIter chashIter[PL_NH_MAX_GROUP_RINGS]; - const char *hostname = ""; - size_t hostname_len = 0; - in_port_t port = 0; - bool retry = false; - bool no_cache = false; -}; - -class PLNextHopConsistentHash : public PLNextHopSelectionStrategy -{ - std::vector> rings; - uint64_t getHashKey(uint64_t sm_id, TSMBuffer reqp, TSMLoc url, TSMLoc parent_selection_url, ATSHash64 *h); - - std::shared_ptr chashLookup(const std::shared_ptr &ring, uint32_t cur_ring, - PLNextHopConsistentHashTxn *state, bool *wrapped, uint64_t sm_id, TSMBuffer reqp, - TSMLoc url, TSMLoc parent_selection_url); - -public: - const uint32_t LineNumberPlaceholder = 99999; - - PLNHHashKeyType hash_key = PL_NH_PATH_HASH_KEY; - - PLNextHopConsistentHash() = delete; - PLNextHopConsistentHash(const std::string_view name, const YAML::Node &n); - ~PLNextHopConsistentHash(); - void next(TSHttpTxn txnp, void *strategyTxn, const char **out_hostname, size_t *out_hostname_len, in_port_t *out_port, - bool *out_retry, bool *out_no_cache, time_t now = 0) override; - void mark(TSHttpTxn txnp, void *strategyTxn, const char *hostname, const size_t hostname_len, const in_port_t port, - const PLNHCmd status, const time_t now) override; - void *newTxn() override; - void deleteTxn(void *txn) override; -}; diff --git a/plugins/experimental/parent_select/consistenthash_config.cc b/plugins/experimental/parent_select/consistenthash_config.cc deleted file mode 100644 index 2b854a1d51c..00000000000 --- a/plugins/experimental/parent_select/consistenthash_config.cc +++ /dev/null @@ -1,255 +0,0 @@ -/* - * 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. - */ - -#include "strategy.h" -#include "consistenthash.h" -#include "util.h" -#include "time.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "tscore/HashSip.h" -#include "tscore/ConsistentHash.h" -#include "tscore/ink_assert.h" -#include "ts/ts.h" -#include "ts/remap.h" -#include "ts/parentselectdefs.h" - -#include "consistenthash_config.h" - -namespace -{ -std::mutex strategies_cache_mutex; -std::map strategies_cache; -} // namespace - -void -clearStrategiesCache(void) -{ - std::lock_guard guard(strategies_cache_mutex); - strategies_cache.clear(); -} - -void loadConfigFile(const std::string &fileName, std::stringstream &doc, std::unordered_set &include_once); - -// createStrategy creates and initializes a Consistent Hash strategy from the given YAML node. -// Caller takes ownership of the returned pointer, and must call delete on it. -TSNextHopSelectionStrategy * -createStrategy(const std::string &name, const YAML::Node &node) -{ - TSDebug(PLUGIN_NAME, "createStrategy %s calling.", name.c_str()); - try { - PLNextHopConsistentHash *st = new PLNextHopConsistentHash(name, node); - TSDebug(PLUGIN_NAME, "createStrategy %s succeeded, returning object", name.c_str()); - return st; - } catch (std::exception &ex) { - TSError("[%s] creating strategies '%s' threw '%s', returning nullptr", PLUGIN_NAME, name.c_str(), ex.what()); - return nullptr; - } -} - -// Caller takes ownership of the returned pointers in the map, and must call delete on them. -// TODO change to only call createStrategy for the one we need, for efficiency. -strategies_map -createStrategiesFromFile(const char *file) -{ - TSDebug(PLUGIN_NAME, "createStrategiesFromFile plugin createStrategiesFromFile file '%s'", file); - - { - std::lock_guard guard(strategies_cache_mutex); - auto it = strategies_cache.find(file); - if (it != strategies_cache.end()) { - TSDebug(PLUGIN_NAME, "createStrategiesFromFile file '%s' in cache from previous remap, using cache", file); - return it->second; - } - } - TSDebug(PLUGIN_NAME, "createStrategiesFromFile file '%s' not in cache, loading file", file); - - YAML::Node config; - YAML::Node strategies; - std::stringstream doc; - std::unordered_set include_once; - std::string_view fn = file; - - // strategy policy - constexpr std::string_view consistent_hash = "consistent_hash"; - - const char *basename = fn.substr(fn.find_last_of('/') + 1).data(); - - try { - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s loading ...", basename); - loadConfigFile(fn.data(), doc, include_once); - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s loaded.", basename); - - config = YAML::Load(doc); - - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s yaml loaded.", basename); - - if (config.IsNull()) { - TSDebug(PLUGIN_NAME, "createStrategiesFromFile No NextHop strategy configs were loaded."); - return strategies_map(); - } - - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s checked null.", basename); - - strategies = config["strategies"]; - if (strategies.Type() != YAML::NodeType::Sequence) { - TSError("[%s] malformed %s file, expected a 'strategies' sequence", PLUGIN_NAME, basename); - return strategies_map(); - } - - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s checked strategies member.", basename); - - // std::map> - strategies_map strategiesMap; - for (auto &&strategy : strategies) { - auto name = strategy["strategy"].as(); - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s got strategy %s.", basename, name.c_str()); - auto policy = strategy["policy"]; - if (!policy) { - TSError("[%s] no policy is defined for the strategy named '%s'.", PLUGIN_NAME, name.c_str()); - return strategies_map(); - } - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s got strategy %s checked policy.", basename, name.c_str()); - const auto &policy_value = policy.Scalar(); - if (policy_value != consistent_hash) { - TSError("[%s] strategy named '%s' has unsupported policy '%s'.", PLUGIN_NAME, name.c_str(), policy_value.c_str()); - return strategies_map(); - } - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s got strategy %s creating strategy.", basename, name.c_str()); - TSNextHopSelectionStrategy *tsStrategy = createStrategy(name, strategy); - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s got strategy %s created strategy.", basename, name.c_str()); - if (tsStrategy == nullptr) { - return strategies_map(); - } - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s got strategy %s checked strategy null.", basename, name.c_str()); - strategiesMap.emplace(name, std::unique_ptr(tsStrategy)); - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s got strategy %s emplaced.", basename, name.c_str()); - } - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s returning strategies created.", basename); - - { - std::lock_guard guard(strategies_cache_mutex); - strategies_cache[file] = strategiesMap; - } - - return strategiesMap; - } catch (std::exception &ex) { - TSError("[%s] creating strategies from file %s threw '%s'.", PLUGIN_NAME, file, ex.what()); - } - TSDebug(PLUGIN_NAME, "createStrategiesFromFile filename %s returning error.", basename); - return strategies_map(); -} - -/* - * loads the contents of a file into a std::stringstream document. If the file has a '#include file' - * directive, that 'file' is read into the document beginning at the point where the - * '#include' was found. This allows the 'strategy' and 'hosts' yaml files to be separate. The - * 'strategy' yaml file would then normally have the '#include hosts.yml' in it's beginning. - */ -void -loadConfigFile(std::string const &pathnamein, std::stringstream &doc, std::unordered_set &include_once) -{ - constexpr std::string_view sep = " \t"; - - namespace fs = std::filesystem; - fs::path const pathin(pathnamein); - std::error_code ec; - - // if fileName is a directory, concatenate all '.yaml' files alphanumerically - // into a single document stream. No #include is supported. - if (fs::is_directory(pathin, ec)) { - TSDebug(PLUGIN_NAME, "loading strategy YAML files from the directory %s", pathnamein.c_str()); - - std::vector subpaths; - for (auto const &dirent : fs::directory_iterator(pathin)) { - fs::path const subpath = dirent.path(); - if (fs::is_regular_file(subpath, ec) && !fs::is_empty(subpath, ec)) { - if (".yaml" == subpath.extension()) { - subpaths.push_back(subpath); - } else { - TSDebug(PLUGIN_NAME, "Skipping dirent (not yaml): '%s'", subpath.c_str()); - } - } else { - TSDebug(PLUGIN_NAME, "Skipping dirent (not file/empty): '%s'", subpath.c_str()); - } - } - - // sort the files alphanumerically - std::sort(subpaths.begin(), subpaths.end()); - - for (fs::path const &fpath : subpaths) { - std::ifstream ifs(fpath); - if (ifs.is_open()) { - std::string line; - while (std::getline(ifs, line)) { - doc << line << "\n"; - } - } else { - throw std::invalid_argument("Unable to open and read: '" + fpath.string() + "'"); - } - } - } else if (fs::is_regular_file(pathin, ec) && !fs::is_empty(pathin, ec)) { - std::ifstream ifs(pathin); - if (ifs.is_open()) { - std::string line; - while (std::getline(ifs, line)) { - // include directive ?? - constexpr std::string_view include{"#include"}; - if (0 == line.rfind(include, 0)) { // starts_with - - // forward view to post include token sans trailing white space - std::string_view sv{line}; - sv = sv.substr(include.length()); - sv = sv.substr(sv.find_first_not_of(sep)); - std::string const pathinc(sv.substr(0, sv.find_first_of(sep))); - - if (!pathinc.empty()) { - if (include_once.end() == include_once.find(pathinc)) { - TSDebug(PLUGIN_NAME, "Include directive: '%s'", pathinc.c_str()); - include_once.insert(pathinc); - try { - loadConfigFile(pathinc, doc, include_once); - } catch (std::exception &ex) { - throw std::invalid_argument("Unable to open included file '" + pathinc + "' from '" + pathnamein + "'"); - } - } - } - } else { - doc << line << "\n"; - } - } - } else { - throw std::invalid_argument("Unable to open and read '" + pathnamein + "'"); - } - } -} diff --git a/plugins/experimental/parent_select/consistenthash_config.h b/plugins/experimental/parent_select/consistenthash_config.h deleted file mode 100644 index 5efab7c28b6..00000000000 --- a/plugins/experimental/parent_select/consistenthash_config.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include -#include -#include "ts/parentselectdefs.h" - -class TSNextHopSelectionStrategy; - -using strategies_map = std::map, std::less<>>; - -void clearStrategiesCache(void); -strategies_map createStrategiesFromFile(const char *file); -TSNextHopSelectionStrategy *createStrategy(const std::string &name, const YAML::Node &node); diff --git a/plugins/experimental/parent_select/healthstatus.cc b/plugins/experimental/parent_select/healthstatus.cc deleted file mode 100644 index 4cb73367d74..00000000000 --- a/plugins/experimental/parent_select/healthstatus.cc +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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. - */ - -#include "strategy.h" -#include "consistenthash.h" -#include "util.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "tscore/HashSip.h" -#include "tscore/ConsistentHash.h" -#include "tscore/ink_assert.h" -#include "ts/ts.h" -#include "ts/remap.h" -#include "ts/parentselectdefs.h" - -void -PLNextHopHealthStatus::insert(std::vector> &hosts) -{ - for (auto h : hosts) { - for (auto protocol = h->protocols.begin(); protocol != h->protocols.end(); ++protocol) { - const std::string host_port = h->getHostPort((*protocol)->port); - host_map.emplace(std::make_pair(host_port, h)); - PL_NH_Debug(PL_NH_DEBUG_TAG, "inserting %s into host_map", host_port.c_str()); - } - } -} - -void -PLNextHopHealthStatus::mark(TSHttpTxn txnp, PLStatusTxn *state, const char *hostname, const size_t hostname_len, - const in_port_t port, const PLNHCmd status, const time_t now) -{ - const time_t _now = now == 0 ? time(nullptr) : now; - - const int64_t sm_id = TSHttpTxnIdGet(txnp); - - int64_t fail_threshold; // = sm->t_state.txn_conf->parent_fail_threshold; - if (TSHttpTxnConfigIntGet(txnp, TS_CONFIG_HTTP_PARENT_PROXY_FAIL_THRESHOLD, &fail_threshold) != TS_SUCCESS) { - PL_NH_Error("mark failed to get parent_fail_threshold, cannot mark next hop"); - return; - } - - int64_t retry_time; // = sm->t_state.txn_conf->parent_retry_time; - if (TSHttpTxnConfigIntGet(txnp, TS_CONFIG_HTTP_PARENT_PROXY_RETRY_TIME, &retry_time) != TS_SUCCESS) { - PL_NH_Error("mark failed to get parent_retry_time, cannot mark next hop"); - return; - } - - uint32_t new_fail_count = 0; - - // make sure we're called back with a result structure for a parent - // that is being retried. - if (status == PL_NH_MARK_UP) { - ink_assert(state->retry == true); - } - if (state->result != PL_NH_PARENT_SPECIFIED) { - return; - } - - const std::string host_port = PLHostRecord::makeHostPort(std::string_view(hostname, hostname_len), port); - auto iter = host_map.find(host_port); - if (iter == host_map.end()) { - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRId64 "] no host named %s found in host_map", sm_id, host_port.c_str()); - return; - } - - std::shared_ptr h = iter->second; - - switch (status) { - // Mark the host up. - case PL_NH_MARK_UP: - if (!h->available) { - h->set_available(); - PL_NH_Note("[%" PRId64 "] http parent proxy %s restored", sm_id, hostname); - } - break; - // Mark the host down. - case PL_NH_MARK_DOWN: - if (h->failedAt == 0 || state->retry == true) { - { // lock guard - std::lock_guard guard(h->_mutex); - if (h->failedAt == 0) { - h->failedAt = _now; - if (state->retry == false) { - new_fail_count = h->failCount = 1; - } - } else if (state->retry == true) { - h->failedAt = _now; - } - } // end lock guard - PL_NH_Note("[%" PRId64 "] NextHop %s marked as down %s", sm_id, (state->retry) ? "retry" : "initially", h->hostname.c_str()); - } else { - int old_count = 0; - // if the last failure was outside the retry window, set the failcount to 1 and failedAt to now. - { // lock guard - std::lock_guard lock(h->_mutex); - if ((h->failedAt + retry_time) < static_cast(_now)) { - h->failCount = 1; - h->failedAt = _now; - } else { - old_count = h->failCount = 1; - } - new_fail_count = old_count + 1; - } // end of lock_guard - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRId64 "] Parent fail count increased to %d for %s", sm_id, new_fail_count, - h->hostname.c_str()); - } - - if (new_fail_count >= fail_threshold) { - h->set_unavailable(); - PL_NH_Note("[%" PRId64 "] Failure threshold met failcount:%d >= threshold:%" PRId64 ", http parent proxy %s marked down", - sm_id, new_fail_count, fail_threshold, h->hostname.c_str()); - PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRId64 "] NextHop %s marked unavailable, h->available=%s", sm_id, h->hostname.c_str(), - (h->available) ? "true" : "false"); - } - break; - } -} diff --git a/plugins/experimental/parent_select/healthstatus.h b/plugins/experimental/parent_select/healthstatus.h deleted file mode 100644 index 66d6295cac0..00000000000 --- a/plugins/experimental/parent_select/healthstatus.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include "ts/parentselectdefs.h" - -struct PLHostRecord; - -enum PLNHCmd { PL_NH_MARK_UP, PL_NH_MARK_DOWN }; - -typedef enum { - PL_NH_PARENT_UNDEFINED, - PL_NH_PARENT_DIRECT, - PL_NH_PARENT_SPECIFIED, - PL_NH_PARENT_AGENT, - PL_NH_PARENT_FAIL, -} PLNHParentResultType; - -struct PLStatusTxn { - PLNHParentResultType result = PL_NH_PARENT_UNDEFINED; - bool retry = false; -}; - -class PLNextHopHealthStatus -{ -public: - void insert(std::vector> &hosts); - void mark(TSHttpTxn txn, PLStatusTxn *healthTxn, const char *hostname, const size_t hostname_len, const in_port_t port, - const PLNHCmd status, const time_t now = 0); - PLNextHopHealthStatus(){}; - -private: - std::unordered_map> host_map; -}; diff --git a/plugins/experimental/parent_select/parent_select.cc b/plugins/experimental/parent_select/parent_select.cc deleted file mode 100644 index c929f4993a1..00000000000 --- a/plugins/experimental/parent_select/parent_select.cc +++ /dev/null @@ -1,372 +0,0 @@ -/** @file - - This plugin counts the number of times every header has appeared. - Maintains separate counts for client and origin headers. - - @section license License - - 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ts/ts.h" -#include "ts/remap.h" -#include "ts/parentselectdefs.h" -#include "ts/remap_version.h" - -#include "consistenthash_config.h" -#include "strategy.h" - -// TODO summary: -// - TSRemapInit version check - -namespace -{ -// The strategy and its transaction state. -struct StrategyTxn { - TSNextHopSelectionStrategy *strategy; - void *txn; // void* because the actual type will depend on the strategy. - int request_count; - TSResponseAction prev_ra; -}; - -// mark parents up or down, on failure or successful retry. -void -mark_response(TSHttpTxn txnp, StrategyTxn *strategyTxn, TSHttpStatus status) -{ - TSDebug(PLUGIN_NAME, "mark_response calling with code: %d", status); - - auto strategy = strategyTxn->strategy; - - const bool isFailure = strategy->codeIsFailure(status); - - TSResponseAction ra; - // if the prev_host isn't null, then that was the actual host we tried which needs to be marked down. - if (strategyTxn->prev_ra.hostname_len != 0) { - ra = strategyTxn->prev_ra; - TSDebug(PLUGIN_NAME, "mark_response using prev %.*s:%d", int(ra.hostname_len), ra.hostname, ra.port); - } else { - TSHttpTxnResponseActionGet(txnp, &ra); - TSDebug(PLUGIN_NAME, "mark_response using response_action %.*s:%d", int(ra.hostname_len), ra.hostname, ra.port); - } - - if (isFailure && strategy->onFailureMarkParentDown(status)) { - if (ra.hostname == nullptr) { - TSError( - "[%s] mark_response got a failure, but response_action had no hostname! This shouldn't be possible! Not marking down!", - PLUGIN_NAME); - } else { - TSDebug(PLUGIN_NAME, "mark_response marking %.*s:%d down", int(ra.hostname_len), ra.hostname, ra.port); - strategy->mark(txnp, strategyTxn->txn, ra.hostname, ra.hostname_len, ra.port, PL_NH_MARK_DOWN); - } - } else if (!isFailure && ra.is_retry) { - if (ra.hostname == nullptr) { - TSError( - "[%s] mark_response got a retry success, but response_action had no hostname! This shouldn't be possible! Not marking up!", - PLUGIN_NAME); - } else { - TSDebug(PLUGIN_NAME, "mark_response marking %.*s:%d up", int(ra.hostname_len), ra.hostname, ra.port); - strategy->mark(txnp, strategyTxn->txn, ra.hostname, ra.hostname_len, ra.port, PL_NH_MARK_UP); - } - } -} - -int -handle_read_response(TSHttpTxn txnp, StrategyTxn *strategyTxn) -{ - TSDebug(PLUGIN_NAME, "handle_read_response calling"); - - auto strategy = strategyTxn->strategy; - - TSDebug(PLUGIN_NAME, "handle_read_response got strategy '%s'", strategy->name()); - - TSMBuffer resp; - TSMLoc resp_hdr; - if (TS_SUCCESS != TSHttpTxnServerRespGet(txnp, &resp, &resp_hdr)) { - TSDebug(PLUGIN_NAME, "handle_read_response failed to get resp"); - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; - } - - TSHttpStatus status = TSHttpHdrStatusGet(resp, resp_hdr); - TSDebug(PLUGIN_NAME, "handle_read_response got response code: %d", status); - - mark_response(txnp, strategyTxn, status); - - if (!strategy->codeIsFailure(status)) { - // if it's a success, set the action to not retry - TSResponseAction ra; - // this sets failed=false, responseIsRetryable=false => don't retry, return the success - memset(&ra, 0, sizeof(TSResponseAction)); // because {0} gives a C++ warning. Ugh. - TSDebug(PLUGIN_NAME, "handle_read_response success, setting response_action to not retry"); - TSHttpTxnResponseActionSet(txnp, &ra); - } else { - // We already set the response_action for what to do on failure in send_request. - // (because we don't always get here with responses, like DNS or connection failures) - // But we need to get the action previously set, and update responseIsRetryable, which we couldn't determine before without the - // Status. - TSResponseAction ra; - TSHttpTxnResponseActionGet(txnp, &ra); - ra.responseIsRetryable = strategy->responseIsRetryable(strategyTxn->request_count - 1, status); - - TSHttpTxnResponseActionSet(txnp, &ra); - } - - // un-set the "prev" hackery. That only exists for markdown, which we just did. - // The response_action is now the next thing to try, if this was a failure, - // and should now be considered authoritative for everything. - - memset(&strategyTxn->prev_ra, 0, sizeof(TSResponseAction)); - - TSHandleMLocRelease(resp, TS_NULL_MLOC, resp_hdr); - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; -} - -int -handle_os_dns(TSHttpTxn txnp, StrategyTxn *strategyTxn) -{ - TSDebug(PLUGIN_NAME, "handle_os_dns calling"); - - ++strategyTxn->request_count; - - auto strategy = strategyTxn->strategy; - - TSDebug(PLUGIN_NAME, "handle_os_dns got strategy '%s'", strategy->name()); - - const TSServerState server_state = TSHttpTxnServerStateGet(txnp); - if (server_state == TS_SRVSTATE_CONNECTION_ERROR || server_state == TS_SRVSTATE_INACTIVE_TIMEOUT) { - mark_response(txnp, strategyTxn, STATUS_CONNECTION_FAILURE); - } - - TSDebug(PLUGIN_NAME, "handle_os_dns had no prev, setting new response_action"); - - { - TSResponseAction ra; - TSHttpTxnResponseActionGet(txnp, &ra); - strategyTxn->prev_ra = ra; - } - - TSResponseAction ra; - memset(&ra, 0, sizeof(TSResponseAction)); - strategy->next(txnp, strategyTxn->txn, &ra.hostname, &ra.hostname_len, &ra.port, &ra.is_retry, &ra.no_cache); - - ra.fail = ra.hostname == nullptr; // failed is whether to immediately fail and return the client a 502. In this case: whether or - // not we found another parent. - ra.nextHopExists = ra.hostname_len != 0; - ra.responseIsRetryable = strategy->responseIsRetryable(strategyTxn->request_count - 1, STATUS_CONNECTION_FAILURE); - ra.goDirect = strategy->goDirect(); - ra.parentIsProxy = strategy->parentIsProxy(); - TSDebug(PLUGIN_NAME, "handle_os_dns setting response_action hostname '%.*s' port %d direct %d proxy %d is_retry %d exists %d", - int(ra.hostname_len), ra.hostname, ra.port, ra.goDirect, ra.parentIsProxy, ra.is_retry, ra.nextHopExists); - TSHttpTxnResponseActionSet(txnp, &ra); - - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; -} - -int -handle_txn_close(TSHttpTxn txnp, TSCont contp, StrategyTxn *strategyTxn) -{ - TSDebug(PLUGIN_NAME, "handle_txn_close calling"); - - auto strategy = strategyTxn->strategy; - - if (strategy != nullptr) { - TSContDataSet(contp, nullptr); - strategy->deleteTxn(strategyTxn->txn); - delete strategyTxn; - // we delete the state, and the strategyAndState pointer at the end of the transaction, - // but we DON'T delete the Strategy, which lives as long as the remap. - } - TSContDestroy(contp); - TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); - return TS_SUCCESS; -} - -int -handle_hook(TSCont contp, TSEvent event, void *edata) -{ - TSDebug(PLUGIN_NAME, "handle_hook calling"); - - TSHttpTxn txnp = static_cast(edata); - StrategyTxn *strategyTxn = static_cast(TSContDataGet(contp)); - - TSDebug(PLUGIN_NAME, "handle_hook got strategy '%s'", strategyTxn->strategy->name()); - - switch (event) { - case TS_EVENT_HTTP_READ_RESPONSE_HDR: - return handle_read_response(txnp, strategyTxn); - case TS_EVENT_HTTP_OS_DNS: - return handle_os_dns(txnp, strategyTxn); - case TS_EVENT_HTTP_TXN_CLOSE: - return handle_txn_close(txnp, contp, strategyTxn); - default: - TSError("[%s] handle_hook got unknown event %d - should never happen!", PLUGIN_NAME, event); - return TS_ERROR; - } -} - -} // namespace - -TSReturnCode -TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size) -{ - CHECK_REMAP_API_COMPATIBILITY(api_info, errbuf, errbuf_size); - TSDebug(PLUGIN_NAME, "Remap successfully initialized"); - return TS_SUCCESS; -} - -TSReturnCode -TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuff, int errbuff_size) -{ - TSDebug(PLUGIN_NAME, "TSRemapNewInstance calling"); - - *ih = nullptr; - - for (int i = 0; i < argc; ++i) { - TSDebug(PLUGIN_NAME, "TSRemapNewInstance arg %d '%s'", i, argv[i]); - } - - if (argc < 4) { - TSError("[%s] insufficient number of arguments, %d, expected file and strategy argument.", PLUGIN_NAME, argc); - return TS_ERROR; - } - if (argc > 4) { - TSError("[%s] too many arguments, %d, only expected file and strategy argument.", PLUGIN_NAME, argc); - return TS_ERROR; - } - - const char *remap_from = argv[0]; - const char *remap_to = argv[1]; - std::filesystem::path config_file_path_obj = argv[2]; - const char *strategy_name = argv[3]; - - if (config_file_path_obj.is_relative()) { - config_file_path_obj = std::filesystem::path(TSConfigDirGet()) / config_file_path_obj; - } - - const char *const config_file_path = config_file_path_obj.c_str(); - - TSDebug(PLUGIN_NAME, "%s %s Loading parent selection strategy file %s for strategy %s", remap_from, remap_to, config_file_path, - strategy_name); - auto file_strategies = createStrategiesFromFile(config_file_path); - if (file_strategies.size() == 0) { - TSError("[%s] %s %s Failed to parse configuration file %s", PLUGIN_NAME, remap_from, remap_to, config_file_path); - return TS_ERROR; - } - - TSDebug(PLUGIN_NAME, "'%s' '%s' successfully created strategies in file %s num %d", remap_from, remap_to, config_file_path, - int(file_strategies.size())); - - auto new_strategy = file_strategies.find(strategy_name); - if (new_strategy == file_strategies.end()) { - TSDebug(PLUGIN_NAME, "'%s' '%s' TSRemapNewInstance strategy '%s' not found in file '%s'", remap_from, remap_to, strategy_name, - config_file_path); - return TS_ERROR; - } - - TSDebug(PLUGIN_NAME, "'%s' '%s' TSRemapNewInstance successfully loaded strategy '%s' from '%s'.", remap_from, remap_to, - strategy_name, config_file_path); - - // created a raw pointer _to_ a shared_ptr, because ih needs a raw pointer. - // The raw pointer in ih will be deleted in TSRemapDeleteInstance, - // which will destruct the shared_ptr, - // destroying the strategy if this is the last remap rule using it. - *ih = static_cast(new std::shared_ptr(new_strategy->second)); - - // Associate our config file with remap.config to be able to initiate reloads - TSMgmtString result; - const char *var_name = "proxy.config.url_remap.filename"; - TSMgmtStringGet(var_name, &result); - TSMgmtConfigFileAdd(result, config_file_path); - - return TS_SUCCESS; -} - -TSRemapStatus -TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri) -{ - TSDebug(PLUGIN_NAME, "TSRemapDoRemap calling"); - - auto strategy_ptr = static_cast *>(ih); - auto strategy = strategy_ptr->get(); - - TSDebug(PLUGIN_NAME, "TSRemapDoRemap got strategy '%s'", strategy->name()); - - TSCont cont = TSContCreate(handle_hook, TSMutexCreate()); - - auto strategyTxn = new StrategyTxn(); - strategyTxn->strategy = strategy; - strategyTxn->txn = strategy->newTxn(); - strategyTxn->request_count = 0; - memset(&strategyTxn->prev_ra, 0, sizeof(TSResponseAction)); - TSContDataSet(cont, (void *)strategyTxn); - - TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, cont); - TSHttpTxnHookAdd(txnp, TS_HTTP_OS_DNS_HOOK, cont); - TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, cont); - - TSResponseAction ra; - memset(&ra, 0, sizeof(TSResponseAction)); // because {0} gives a C++ warning. Ugh. - strategy->next(txnp, strategyTxn->txn, &ra.hostname, &ra.hostname_len, &ra.port, &ra.is_retry, &ra.no_cache); - - ra.nextHopExists = ra.hostname != nullptr; - ra.fail = !ra.nextHopExists; - // The action here is used for the very first connection, not any retry. So of course we should try it. - ra.responseIsRetryable = true; - ra.goDirect = strategy->goDirect(); - ra.parentIsProxy = strategy->parentIsProxy(); - - if (ra.fail && !ra.goDirect) { - // TODO make configurable - TSDebug(PLUGIN_NAME, "TSRemapDoRemap strategy '%s' next returned nil, returning 502!", strategy->name()); - TSHttpTxnStatusSet(txnp, TS_HTTP_STATUS_BAD_GATEWAY); - // TODO verify TS_EVENT_HTTP_TXN_CLOSE fires, and if not, free the cont here. - return TSREMAP_DID_REMAP; - } - - TSDebug(PLUGIN_NAME, "TSRemapDoRemap setting response_action hostname '%.*s' port %d direct %d proxy %d", int(ra.hostname_len), - ra.hostname, ra.port, ra.goDirect, ra.parentIsProxy); - TSHttpTxnResponseActionSet(txnp, &ra); - - return TSREMAP_NO_REMAP; -} - -void -TSRemapDeleteInstance(void *ih) -{ - TSDebug(PLUGIN_NAME, "TSRemapDeleteInstance calling"); - auto strategy_ptr = static_cast *>(ih); - delete strategy_ptr; - TSDebug(PLUGIN_NAME, "TSRemapDeleteInstance deleted strategy pointer"); -} - -void -TSRemapPreConfigReload(void) -{ - TSDebug(PLUGIN_NAME, "TSRemapPreConfigReload clearing strategies cache"); - clearStrategiesCache(); -} diff --git a/plugins/experimental/parent_select/strategy.cc b/plugins/experimental/parent_select/strategy.cc deleted file mode 100644 index 385f04c0e2e..00000000000 --- a/plugins/experimental/parent_select/strategy.cc +++ /dev/null @@ -1,393 +0,0 @@ -/* - * 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. - */ - -#include "strategy.h" -#include "consistenthash.h" -#include "util.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "tscore/HashSip.h" -#include "tscore/ConsistentHash.h" -#include "tscore/ink_assert.h" -#include "ts/ts.h" -#include "ts/remap.h" -#include "ts/parentselectdefs.h" - -// -// NextHopSelectionStrategy.cc -// - -// ring mode strings -const std::string_view alternate_rings = "alternate_ring"; -const std::string_view exhaust_rings = "exhaust_ring"; -const std::string_view peering_rings = "peering_ring"; - -// health check strings -const std::string_view active_health_check = "active"; -const std::string_view passive_health_check = "passive"; - -PLNextHopSelectionStrategy::PLNextHopSelectionStrategy(const std::string_view &name, const YAML::Node &n) : strategy_name(name) -{ - PL_NH_Debug(PL_NH_DEBUG_TAG, "PLNextHopSelectionStrategy constructor calling"); - std::string self_host; - bool self_host_used = false; - - try { - // scheme is optional, and strategies with no scheme will match hosts with no scheme - if (n["scheme"]) { - auto scheme_val = n["scheme"].Scalar(); - if (scheme_val == "http") { - scheme = PL_NH_SCHEME_HTTP; - } else if (scheme_val == "https") { - scheme = PL_NH_SCHEME_HTTPS; - } else { - PL_NH_Note("Invalid scheme '%s' for strategy '%s', setting to NONE", scheme_val.c_str(), strategy_name.c_str()); - } - } - - // go_direct config. - if (n["go_direct"]) { - go_direct = n["go_direct"].as(); - } - - // parent_is_proxy config. - if (n["parent_is_proxy"]) { - parent_is_proxy = n["parent_is_proxy"].as(); - } - - // ignore_self_detect - if (n["ignore_self_detect"]) { - ignore_self_detect = n["ignore_self_detect"].as(); - } - - if (n["cache_peer_result"]) { - cache_peer_result = n["cache_peer_result"].as(); - } - - // failover node. - YAML::Node failover_node; - if (n["failover"]) { - failover_node = n["failover"]; - if (failover_node["ring_mode"]) { - auto ring_mode_val = failover_node["ring_mode"].Scalar(); - if (ring_mode_val == alternate_rings) { - ring_mode = PL_NH_ALTERNATE_RING; - } else if (ring_mode_val == exhaust_rings) { - ring_mode = PL_NH_EXHAUST_RING; - } else if (ring_mode_val == peering_rings) { - ring_mode = PL_NH_PEERING_RING; - YAML::Node self_node = failover_node["self"]; - if (self_node) { - self_host = self_node.Scalar(); - PL_NH_Debug(PL_NH_DEBUG_TAG, "%s is self", self_host.c_str()); - } - } else { - ring_mode = PL_NH_ALTERNATE_RING; - PL_NH_Note("Invalid 'ring_mode' value, '%s', for the strategy named '%s', using default '%s'.", ring_mode_val.c_str(), - strategy_name.c_str(), alternate_rings.data()); - } - } - if (failover_node["max_simple_retries"]) { - max_simple_retries = failover_node["max_simple_retries"].as(); - } - - if (failover_node["max_unavailable_retries"]) { - max_unavailable_retries = failover_node["max_unavailable_retries"].as(); - } - - YAML::Node resp_codes_node; - // connection failures are always failure and retryable (pending retries) - resp_codes.add(STATUS_CONNECTION_FAILURE); - if (failover_node["response_codes"]) { - resp_codes_node = failover_node["response_codes"]; - if (resp_codes_node.Type() != YAML::NodeType::Sequence) { - PL_NH_Error("Error in the response_codes definition for the strategy named '%s', skipping response_codes.", - strategy_name.c_str()); - } else { - for (auto &&k : resp_codes_node) { - auto code = k.as(); - if (code > 300 && code < 599) { - resp_codes.add(code); - } else { - PL_NH_Note("Skipping invalid response code '%d' for the strategy named '%s'.", code, strategy_name.c_str()); - } - } - resp_codes.sort(); - } - } - YAML::Node markdown_codes_node; - if (failover_node["markdown_codes"]) { - markdown_codes_node = failover_node["markdown_codes"]; - if (markdown_codes_node.Type() != YAML::NodeType::Sequence) { - PL_NH_Error("Error in the markdown_codes definition for the strategy named '%s', skipping markdown_codes.", - strategy_name.c_str()); - } else { - for (auto &&k : markdown_codes_node) { - auto code = k.as(); - if (code > 300 && code < 599) { - markdown_codes.add(code); - } else { - PL_NH_Note("Skipping invalid markdown response code '%d' for the strategy named '%s'.", code, strategy_name.c_str()); - } - } - markdown_codes.sort(); - } - } - YAML::Node health_check_node; - if (failover_node["health_check"]) { - health_check_node = failover_node["health_check"]; - if (health_check_node.Type() != YAML::NodeType::Sequence) { - PL_NH_Error("Error in the health_check definition for the strategy named '%s', skipping health_checks.", - strategy_name.c_str()); - } else { - for (auto it = health_check_node.begin(); it != health_check_node.end(); ++it) { - auto health_check = it->as(); - if (health_check.compare(active_health_check) == 0) { - health_checks.active = true; - } - if (health_check.compare(passive_health_check) == 0) { - health_checks.passive = true; - } - } - } - } - } - - // parse and load the host data - YAML::Node groups_node; - if (n["groups"]) { - groups_node = n["groups"]; - // a groups list is required. - if (groups_node.Type() != YAML::NodeType::Sequence) { - throw std::invalid_argument("Invalid groups definition, expected a sequence, '" + strategy_name + "' cannot be loaded."); - } else { - uint32_t grp_size = groups_node.size(); - if (grp_size > PL_NH_MAX_GROUP_RINGS) { - PL_NH_Note( - "the groups list exceeds the maximum of %d for the strategy '%s'. Only the first %d groups will be configured.", - PL_NH_MAX_GROUP_RINGS, strategy_name.c_str(), PL_NH_MAX_GROUP_RINGS); - groups = PL_NH_MAX_GROUP_RINGS; - } else { - groups = groups_node.size(); - } - // resize the hosts vector. - host_groups.reserve(groups); - // loop through the groups - for (unsigned int grp = 0; grp < groups; ++grp) { - YAML::Node hosts_list = groups_node[grp]; - - // a list of hosts is required. - if (hosts_list.Type() != YAML::NodeType::Sequence) { - throw std::invalid_argument("Invalid hosts definition, expected a sequence, '" + strategy_name + "' cannot be loaded."); - } else { - // loop through the hosts list. - std::vector> hosts_inner; - - for (unsigned int hst = 0; hst < hosts_list.size(); ++hst) { - std::shared_ptr host_rec = std::make_shared(hosts_list[hst].as()); - host_rec->group_index = grp; - host_rec->host_index = hst; - if (self_host == host_rec->hostname || - TSHostnameIsSelf(host_rec->hostname.c_str(), host_rec->hostname.size()) == TS_SUCCESS) { - if (ring_mode == PL_NH_PEERING_RING && grp != 0) { - throw std::invalid_argument("self host (" + self_host + - ") can only appear in first host group for peering ring mode"); - } - TSHostStatusSet(host_rec->hostname.c_str(), host_rec->hostname.size(), TSHostStatus::TS_HOST_STATUS_DOWN, 0, - static_cast(TS_HOST_STATUS_SELF_DETECT)); - host_rec->self = true; - self_host_used = true; - } - hosts_inner.push_back(std::move(host_rec)); - num_parents++; - } - passive_health.insert(hosts_inner); - host_groups.push_back(std::move(hosts_inner)); - } - } - } - } - if (!self_host.empty() && !self_host_used) { - throw std::invalid_argument("self host (" + self_host + ") does not appear in the first (peer) group"); - } - } catch (std::exception &ex) { - throw std::invalid_argument("Error parsing strategy named '" + strategy_name + "' due to '" + ex.what() + - "', this strategy will be ignored."); - } -} - -bool -PLNextHopSelectionStrategy::nextHopExists(TSHttpTxn txnp) -{ - PL_NH_Debug(PL_NH_DEBUG_TAG, "nhplugin nextHopExists calling"); - - const int64_t sm_id = TSHttpTxnIdGet(txnp); - - for (uint32_t gg = 0; gg < groups; gg++) { - for (auto &hh : host_groups[gg]) { - PLHostRecord *p = hh.get(); - if (p->available) { - PL_NH_Debug(PL_NH_DEBUG_TAG, - "[%" PRIu64 "] found available next hop %.*s (this is NOT necessarily the parent which will be selected, just " - "the first available parent found)", - sm_id, int(p->hostname.size()), p->hostname.c_str()); - return true; - } - } - } - return false; -} - -bool -PLNextHopSelectionStrategy::codeIsFailure(TSHttpStatus response_code) -{ - return this->resp_codes.contains(response_code) || this->markdown_codes.contains(response_code); -} - -bool -PLNextHopSelectionStrategy::responseIsRetryable(unsigned int current_retry_attempts, TSHttpStatus response_code) -{ - return (current_retry_attempts < this->num_parents) && - ((this->resp_codes.contains(response_code) && current_retry_attempts < this->max_simple_retries) || - (this->markdown_codes.contains(response_code) && current_retry_attempts < this->max_unavailable_retries)); -} - -bool -PLNextHopSelectionStrategy::onFailureMarkParentDown(TSHttpStatus response_code) -{ - return this->markdown_codes.contains(response_code); -} - -bool -PLNextHopSelectionStrategy::goDirect() -{ - PL_NH_Debug(PL_NH_DEBUG_TAG, "nhplugin goDirect calling"); - return this->go_direct; -} - -bool -PLNextHopSelectionStrategy::parentIsProxy() -{ - PL_NH_Debug(PL_NH_DEBUG_TAG, "nhplugin parentIsProxy calling"); - return this->parent_is_proxy; -} - -namespace YAML -{ -template <> struct convert { - static bool - decode(const Node &node, PLHostRecord &nh) - { - YAML::Node nd; - bool merge_tag_used = false; - - // check for YAML merge tag. - if (node["<<"]) { - nd = node["<<"]; - merge_tag_used = true; - } else { - nd = node; - } - - // lookup the hostname - if (nd["host"]) { - nh.hostname = nd["host"].Scalar(); - } else { - throw std::invalid_argument("Invalid host definition, missing host name."); - } - - // lookup the port numbers supported by this host. - YAML::Node proto = nd["protocol"]; - - if (proto.Type() != YAML::NodeType::Sequence) { - throw std::invalid_argument("Invalid host protocol definition, expected a sequence."); - } else { - for (auto &&ii : proto) { - const YAML::Node &protocol_node = ii; - std::shared_ptr pr = std::make_shared(protocol_node.as()); - nh.protocols.push_back(std::move(pr)); - } - } - - // get the host's weight - YAML::Node weight; - if (merge_tag_used) { - weight = node["weight"]; - nh.weight = weight.as(); - } else if ((weight = nd["weight"])) { - nh.weight = weight.as(); - } else { - PL_NH_Note("No weight is defined for the host '%s', using default 1.0", nh.hostname.data()); - nh.weight = 1.0; - } - - // get the host's optional hash_string - YAML::Node hash; - if ((hash = nd["hash_string"])) { - nh.hash_string = hash.Scalar(); - } - - return true; - } -}; - -template <> struct convert { - static bool - decode(const Node &node, PLNHProtocol &nh) - { - // scheme is optional, and strategies with no scheme will match hosts with no scheme - if (node["scheme"]) { - const auto scheme_val = node["scheme"].Scalar(); - if (scheme_val == "http") { - nh.scheme = PL_NH_SCHEME_HTTP; - } else if (scheme_val == "https") { - nh.scheme = PL_NH_SCHEME_HTTPS; - } else { - PL_NH_Note("Invalid scheme '%s' for protocol, setting to NONE", scheme_val.c_str()); - } - } - if (node["port"]) { - nh.port = node["port"].as(); - if (nh.port <= 0 || nh.port > 65535) { - throw YAML::ParserException(node["port"].Mark(), "port number must be in (inclusive) range 1 - 65,536"); - } - } else { - throw YAML::ParserException(node["port"].Mark(), - "no port is defined, a port number must be defined within (inclusive) range 1 - 65,536"); - } - if (node["health_check_url"]) { - nh.health_check_url = node["health_check_url"].Scalar(); - } - return true; - } -}; -}; // namespace YAML diff --git a/plugins/experimental/parent_select/strategy.h b/plugins/experimental/parent_select/strategy.h deleted file mode 100644 index aaadfba70ad..00000000000 --- a/plugins/experimental/parent_select/strategy.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tscore/ConsistentHash.h" -#include "ts/ts.h" -#include "ts/parentselectdefs.h" -#include "ts/remap.h" -#include "healthstatus.h" - -// TODO rename, move to respective sub-plugins -#define PLUGIN_NAME "pparent_select" - -constexpr const char *PL_NH_DEBUG_TAG = PLUGIN_NAME; - -// ring mode strings -extern const std::string_view alternate_rings; -extern const std::string_view exhaust_rings; -extern const std::string_view peering_rings; - -// health check strings -extern const std::string_view active_health_check; -extern const std::string_view passive_health_check; - -#define PL_NH_Debug(tag, fmt, ...) TSDebug(tag, "[%s:%d]: " fmt, __FILE__, __LINE__, ##__VA_ARGS__) -#define PL_NH_Error(fmt, ...) TSError("(%s) [%s:%d]: " fmt, PLUGIN_NAME, __FILE__, __LINE__, ##__VA_ARGS__) -#define PL_NH_Note(fmt, ...) TSDebug(PL_NH_DEBUG_TAG, "[%s:%d]: " fmt, __FILE__, __LINE__, ##__VA_ARGS__) - -constexpr const char *policy_strings[] = {"PL_NH_UNDEFINED", "PL_NH_FIRST_LIVE", "PL_NH_RR_STRICT", - "PL_NH_RR_IP", "PL_NH_RR_LATCHED", "PL_NH_CONSISTENT_HASH"}; - -constexpr const TSHttpStatus STATUS_CONNECTION_FAILURE = static_cast(0); - -enum PLNHPolicyType { - PL_NH_UNDEFINED = 0, - PL_NH_FIRST_LIVE, // first available nexthop - PL_NH_RR_STRICT, // strict round robin - PL_NH_RR_IP, // round robin by client ip. - PL_NH_RR_LATCHED, // latched to available next hop. - PL_NH_CONSISTENT_HASH, // consistent hashing strategy. - PL_NH_PLUGIN, // hashing strategy is a plugin -}; - -enum PLNHSchemeType { PL_NH_SCHEME_NONE = 0, PL_NH_SCHEME_HTTP, PL_NH_SCHEME_HTTPS }; - -enum PLNHRingMode { PL_NH_ALTERNATE_RING = 0, PL_NH_EXHAUST_RING, PL_NH_PEERING_RING }; - -// response codes container -struct PLResponseCodes { - PLResponseCodes(){}; - std::vector codes; - void - add(short code) - { - codes.push_back(code); - } - bool - contains(short code) - { - return std::binary_search(codes.begin(), codes.end(), code); - } - void - sort() - { - std::sort(codes.begin(), codes.end()); - } -}; - -struct PLHealthChecks { - bool active = false; - bool passive = false; -}; - -struct PLNHProtocol { - PLNHSchemeType scheme = PL_NH_SCHEME_NONE; - uint32_t port = 0; - std::string health_check_url; -}; - -struct PLHostRecord : ATSConsistentHashNode { - std::mutex _mutex; - std::string hostname; - std::atomic failedAt; - std::atomic failCount; - std::atomic upAt; - float weight; - std::string hash_string; - int host_index; - int group_index; - bool self = false; - std::vector> protocols; - - // construct without locking the _mutex. - PLHostRecord() - { - hostname = ""; - failedAt = 0; - failCount = 0; - upAt = 0; - weight = 0; - hash_string = ""; - host_index = -1; - group_index = -1; - available = true; - } - - // copy constructor to avoid copying the _mutex. - PLHostRecord(const PLHostRecord &o) - { - hostname = o.hostname; - failedAt = o.failedAt.load(); - failCount = o.failCount.load(); - upAt = o.upAt.load(); - weight = o.weight; - hash_string = o.hash_string; - host_index = o.host_index; - group_index = o.group_index; - available = o.available.load(); - protocols = o.protocols; - self = o.self; - } - - // assign without copying the _mutex. - PLHostRecord & - operator=(const PLHostRecord &o) - { - hostname = o.hostname; - failedAt = o.failedAt.load(); - failCount = o.failCount.load(); - upAt = o.upAt.load(); - weight = o.weight; - hash_string = o.hash_string; - host_index = o.host_index; - group_index = o.group_index; - available = o.available.load(); - protocols = o.protocols; - self = o.self; - return *this; - } - - // locks the record when marking this host down. - void - set_unavailable() - { - if (available) { - std::lock_guard lock(_mutex); - failedAt = time(nullptr); - available = false; - } - } - - // locks the record when marking this host up. - void - set_available() - { - if (!available) { - std::lock_guard lock(_mutex); - failedAt = 0; - failCount = 0; - upAt = time(nullptr); - available = true; - } - } - - int - getPort(PLNHSchemeType scheme) const - { - int port = 0; - for (uint32_t i = 0; i < protocols.size(); i++) { - if (protocols[i]->scheme == scheme) { - port = protocols[i]->port; - break; - } - } - return port; - } - - static std::string - makeHostPort(const std::string_view hostname, const in_port_t port) - { - return std::string(hostname) + ":" + std::to_string(port); - } - - std::string - getHostPort(const in_port_t port) const - { - return makeHostPort(this->hostname, port); - } -}; - -class TSNextHopSelectionStrategy -{ -public: - TSNextHopSelectionStrategy(){}; - virtual ~TSNextHopSelectionStrategy(){}; - - virtual const char *name() = 0; - virtual void next(TSHttpTxn txnp, void *strategyTxn, const char **out_hostname, size_t *out_hostname_len, in_port_t *out_port, - bool *out_retry, bool *out_no_cache, time_t now = 0) = 0; - virtual void mark(TSHttpTxn txnp, void *strategyTxn, const char *hostname, const size_t hostname_len, const in_port_t port, - const PLNHCmd status, const time_t now = 0) = 0; - virtual bool nextHopExists(TSHttpTxn txnp) = 0; - virtual bool codeIsFailure(TSHttpStatus response_code) = 0; - virtual bool responseIsRetryable(unsigned int current_retry_attempts, TSHttpStatus response_code) = 0; - virtual bool onFailureMarkParentDown(TSHttpStatus response_code) = 0; - - virtual bool goDirect() = 0; - virtual bool parentIsProxy() = 0; - - virtual void *newTxn() = 0; - virtual void deleteTxn(void *state) = 0; -}; - -class PLNextHopSelectionStrategy : public TSNextHopSelectionStrategy -{ -public: - PLNextHopSelectionStrategy() = delete; - PLNextHopSelectionStrategy(const std::string_view &name, const YAML::Node &n); - virtual ~PLNextHopSelectionStrategy(){}; - - void next(TSHttpTxn txnp, void *strategyTxn, const char **out_hostname, size_t *out_hostname_len, in_port_t *out_port, - bool *out_retry, bool *out_no_cache, time_t now = 0) override = 0; - void mark(TSHttpTxn txnp, void *strategyTxn, const char *hostname, const size_t hostname_len, const in_port_t port, - const PLNHCmd status, const time_t now = 0) override = 0; - bool nextHopExists(TSHttpTxn txnp) override; - bool codeIsFailure(TSHttpStatus response_code) override; - bool responseIsRetryable(unsigned int current_retry_attempts, TSHttpStatus response_code) override; - bool onFailureMarkParentDown(TSHttpStatus response_code) override; - bool goDirect() override; - bool parentIsProxy() override; - const char * - name() override - { - return strategy_name.c_str(); - }; - void *newTxn() override = 0; - void deleteTxn(void *state) override = 0; - -protected: - std::string strategy_name; - bool go_direct = true; - bool parent_is_proxy = true; - bool ignore_self_detect = false; - bool cache_peer_result = true; - PLNHSchemeType scheme = PL_NH_SCHEME_NONE; - PLNHRingMode ring_mode = PL_NH_ALTERNATE_RING; - PLResponseCodes resp_codes; // simple retry codes - PLResponseCodes markdown_codes; // unavailable server retry and markdown codes - - PLHealthChecks health_checks; - PLNextHopHealthStatus passive_health; - std::vector>> host_groups; - uint32_t max_simple_retries = 1; - uint32_t max_unavailable_retries = 1; - uint32_t groups = 0; - uint32_t grp_index = 0; - uint32_t hst_index = 0; - uint32_t num_parents = 0; - uint32_t distance = 0; // index into the strategies list. -}; diff --git a/plugins/experimental/parent_select/util.h b/plugins/experimental/parent_select/util.h deleted file mode 100644 index fa050b009bc..00000000000 --- a/plugins/experimental/parent_select/util.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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. - */ - -#pragma once - -// ScopedFreeMLoc frees the given TSMLoc with TSHandleMLocRelease(buf, parent, *m) when it goes out of scope. -// The lifetime of buf and parent must exceed this. -// The parent must be allocated before this (if it exists). -// The parent may be TS_NULL_MLOC. -// If mloc is set to TS_NULL_MLOC or never allocated, it will not be freed. -struct ScopedFreeMLoc { - ScopedFreeMLoc(TSMBuffer *_buf, TSMLoc _parent, TSMLoc *_mloc) : mloc(_mloc), parent(_parent), buf(_buf){}; - ~ScopedFreeMLoc() - { - if (*mloc != TS_NULL_MLOC) { - TSHandleMLocRelease(*buf, parent, *mloc); - } - }; - -private: - TSMLoc *mloc; - TSMLoc parent; - TSMBuffer *buf; -}; - -// StrVal is a string as returned by TSUrlStringGet and other TS API functions. -// Zeroes on initialization. -struct StrVal { - StrVal() : ptr(nullptr), len(0){}; - char *ptr; - int len; -}; - -// ScopedFreeStrVal frees the ptr in the given Strval when it goes out of scope. -struct ScopedFreeStrVal { - ScopedFreeStrVal(StrVal *_strval) : strval(_strval){}; - ~ScopedFreeStrVal() { TSfree(strval->ptr); }; - -private: - StrVal *strval; -}; diff --git a/plugins/experimental/traffic_dump/Makefile.inc b/plugins/experimental/traffic_dump/Makefile.inc deleted file mode 100644 index ea843bbe8a8..00000000000 --- a/plugins/experimental/traffic_dump/Makefile.inc +++ /dev/null @@ -1,45 +0,0 @@ -# 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. - -pkglib_LTLIBRARIES += experimental/traffic_dump/traffic_dump.la - -experimental_traffic_dump_traffic_dump_la_SOURCES = \ - experimental/traffic_dump/global_variables.h \ - experimental/traffic_dump/json_utils.cc \ - experimental/traffic_dump/json_utils.h \ - experimental/traffic_dump/sensitive_fields.h \ - experimental/traffic_dump/session_data.cc \ - experimental/traffic_dump/session_data.h \ - experimental/traffic_dump/traffic_dump.cc \ - experimental/traffic_dump/transaction_data.cc \ - experimental/traffic_dump/transaction_data.h - -check_PROGRAMS += \ - experimental/traffic_dump/test_traffic_dump - -experimental_traffic_dump_test_traffic_dump_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - -I$(abs_top_srcdir)/plugins/experimental/traffic_dump \ - -I$(abs_top_srcdir)/lib/catch2 - -experimental_traffic_dump_test_traffic_dump_SOURCES = \ - experimental/traffic_dump/unit_tests/unit_test_main.cc \ - experimental/traffic_dump/unit_tests/test_json_utils.cc \ - experimental/traffic_dump/unit_tests/test_sensitive_fields.cc \ - experimental/traffic_dump/json_utils.cc \ - experimental/traffic_dump/sensitive_fields.h - -# vim: ft=make ts=8 sw=8 et: diff --git a/plugins/experimental/ja3_fingerprint/CMakeLists.txt b/plugins/ja3_fingerprint/CMakeLists.txt similarity index 100% rename from plugins/experimental/ja3_fingerprint/CMakeLists.txt rename to plugins/ja3_fingerprint/CMakeLists.txt diff --git a/plugins/experimental/metalink/Makefile.inc b/plugins/ja3_fingerprint/Makefile.inc similarity index 85% rename from plugins/experimental/metalink/Makefile.inc rename to plugins/ja3_fingerprint/Makefile.inc index 98227c8622c..ebdb3e4c381 100644 --- a/plugins/experimental/metalink/Makefile.inc +++ b/plugins/ja3_fingerprint/Makefile.inc @@ -14,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -pkglib_LTLIBRARIES += experimental/metalink/metalink.la +pkglib_LTLIBRARIES += ja3_fingerprint/ja3_fingerprint.la -experimental_metalink_metalink_la_SOURCES = \ - experimental/metalink/metalink.cc +ja3_fingerprint_ja3_fingerprint_la_SOURCES = ja3_fingerprint/ja3_fingerprint.cc diff --git a/plugins/experimental/ja3_fingerprint/README b/plugins/ja3_fingerprint/README similarity index 100% rename from plugins/experimental/ja3_fingerprint/README rename to plugins/ja3_fingerprint/README diff --git a/plugins/experimental/ja3_fingerprint/ja3_fingerprint.cc b/plugins/ja3_fingerprint/ja3_fingerprint.cc similarity index 100% rename from plugins/experimental/ja3_fingerprint/ja3_fingerprint.cc rename to plugins/ja3_fingerprint/ja3_fingerprint.cc diff --git a/plugins/experimental/remap_stats/CMakeLists.txt b/plugins/remap_stats/CMakeLists.txt similarity index 100% rename from plugins/experimental/remap_stats/CMakeLists.txt rename to plugins/remap_stats/CMakeLists.txt diff --git a/plugins/experimental/statichit/Makefile.inc b/plugins/remap_stats/Makefile.inc similarity index 84% rename from plugins/experimental/statichit/Makefile.inc rename to plugins/remap_stats/Makefile.inc index 6e124f09801..c8e5dc31fa8 100644 --- a/plugins/experimental/statichit/Makefile.inc +++ b/plugins/remap_stats/Makefile.inc @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -pkglib_LTLIBRARIES += experimental/statichit/statichit.la +pkglib_LTLIBRARIES += remap_stats/remap_stats.la -experimental_statichit_statichit_la_SOURCES = \ - experimental/statichit/statichit.cc +remap_stats_remap_stats_la_SOURCES = \ + remap_stats/remap_stats.cc diff --git a/plugins/experimental/remap_stats/remap_stats.cc b/plugins/remap_stats/remap_stats.cc similarity index 100% rename from plugins/experimental/remap_stats/remap_stats.cc rename to plugins/remap_stats/remap_stats.cc diff --git a/plugins/experimental/statichit/CMakeLists.txt b/plugins/statichit/CMakeLists.txt similarity index 100% rename from plugins/experimental/statichit/CMakeLists.txt rename to plugins/statichit/CMakeLists.txt diff --git a/plugins/experimental/remap_stats/Makefile.inc b/plugins/statichit/Makefile.inc similarity index 83% rename from plugins/experimental/remap_stats/Makefile.inc rename to plugins/statichit/Makefile.inc index 562876b7acf..bd15b45e286 100644 --- a/plugins/experimental/remap_stats/Makefile.inc +++ b/plugins/statichit/Makefile.inc @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -pkglib_LTLIBRARIES += experimental/remap_stats/remap_stats.la +pkglib_LTLIBRARIES += statichit/statichit.la -experimental_remap_stats_remap_stats_la_SOURCES = \ - experimental/remap_stats/remap_stats.cc +statichit_statichit_la_SOURCES = \ + statichit/statichit.cc diff --git a/plugins/experimental/statichit/README.md b/plugins/statichit/README.md similarity index 100% rename from plugins/experimental/statichit/README.md rename to plugins/statichit/README.md diff --git a/plugins/experimental/statichit/statichit.cc b/plugins/statichit/statichit.cc similarity index 100% rename from plugins/experimental/statichit/statichit.cc rename to plugins/statichit/statichit.cc diff --git a/plugins/experimental/traffic_dump/CMakeLists.txt b/plugins/traffic_dump/CMakeLists.txt similarity index 100% rename from plugins/experimental/traffic_dump/CMakeLists.txt rename to plugins/traffic_dump/CMakeLists.txt diff --git a/plugins/traffic_dump/Makefile.inc b/plugins/traffic_dump/Makefile.inc new file mode 100644 index 00000000000..123b2946d70 --- /dev/null +++ b/plugins/traffic_dump/Makefile.inc @@ -0,0 +1,45 @@ +# 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. + +pkglib_LTLIBRARIES += traffic_dump/traffic_dump.la + +traffic_dump_traffic_dump_la_SOURCES = \ + traffic_dump/global_variables.h \ + traffic_dump/json_utils.cc \ + traffic_dump/json_utils.h \ + traffic_dump/sensitive_fields.h \ + traffic_dump/session_data.cc \ + traffic_dump/session_data.h \ + traffic_dump/traffic_dump.cc \ + traffic_dump/transaction_data.cc \ + traffic_dump/transaction_data.h + +check_PROGRAMS += \ + traffic_dump/test_traffic_dump + +traffic_dump_test_traffic_dump_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(abs_top_srcdir)/plugins/traffic_dump \ + -I$(abs_top_srcdir)/lib/catch2 + +traffic_dump_test_traffic_dump_SOURCES = \ + traffic_dump/unit_tests/unit_test_main.cc \ + traffic_dump/unit_tests/test_json_utils.cc \ + traffic_dump/unit_tests/test_sensitive_fields.cc \ + traffic_dump/json_utils.cc \ + traffic_dump/sensitive_fields.h + +# vim: ft=make ts=8 sw=8 et: diff --git a/plugins/experimental/traffic_dump/README b/plugins/traffic_dump/README similarity index 100% rename from plugins/experimental/traffic_dump/README rename to plugins/traffic_dump/README diff --git a/plugins/experimental/traffic_dump/global_variables.h b/plugins/traffic_dump/global_variables.h similarity index 100% rename from plugins/experimental/traffic_dump/global_variables.h rename to plugins/traffic_dump/global_variables.h diff --git a/plugins/experimental/traffic_dump/json_utils.cc b/plugins/traffic_dump/json_utils.cc similarity index 100% rename from plugins/experimental/traffic_dump/json_utils.cc rename to plugins/traffic_dump/json_utils.cc diff --git a/plugins/experimental/traffic_dump/json_utils.h b/plugins/traffic_dump/json_utils.h similarity index 100% rename from plugins/experimental/traffic_dump/json_utils.h rename to plugins/traffic_dump/json_utils.h diff --git a/plugins/experimental/traffic_dump/post_process.py b/plugins/traffic_dump/post_process.py similarity index 100% rename from plugins/experimental/traffic_dump/post_process.py rename to plugins/traffic_dump/post_process.py diff --git a/plugins/experimental/traffic_dump/sensitive_fields.h b/plugins/traffic_dump/sensitive_fields.h similarity index 100% rename from plugins/experimental/traffic_dump/sensitive_fields.h rename to plugins/traffic_dump/sensitive_fields.h diff --git a/plugins/experimental/traffic_dump/session_data.cc b/plugins/traffic_dump/session_data.cc similarity index 100% rename from plugins/experimental/traffic_dump/session_data.cc rename to plugins/traffic_dump/session_data.cc diff --git a/plugins/experimental/traffic_dump/session_data.h b/plugins/traffic_dump/session_data.h similarity index 100% rename from plugins/experimental/traffic_dump/session_data.h rename to plugins/traffic_dump/session_data.h diff --git a/plugins/experimental/traffic_dump/traffic_dump.cc b/plugins/traffic_dump/traffic_dump.cc similarity index 100% rename from plugins/experimental/traffic_dump/traffic_dump.cc rename to plugins/traffic_dump/traffic_dump.cc diff --git a/plugins/experimental/traffic_dump/transaction_data.cc b/plugins/traffic_dump/transaction_data.cc similarity index 100% rename from plugins/experimental/traffic_dump/transaction_data.cc rename to plugins/traffic_dump/transaction_data.cc diff --git a/plugins/experimental/traffic_dump/transaction_data.h b/plugins/traffic_dump/transaction_data.h similarity index 100% rename from plugins/experimental/traffic_dump/transaction_data.h rename to plugins/traffic_dump/transaction_data.h diff --git a/plugins/experimental/traffic_dump/unit_tests/CMakeLists.txt b/plugins/traffic_dump/unit_tests/CMakeLists.txt similarity index 100% rename from plugins/experimental/traffic_dump/unit_tests/CMakeLists.txt rename to plugins/traffic_dump/unit_tests/CMakeLists.txt diff --git a/plugins/experimental/traffic_dump/unit_tests/test_json_utils.cc b/plugins/traffic_dump/unit_tests/test_json_utils.cc similarity index 100% rename from plugins/experimental/traffic_dump/unit_tests/test_json_utils.cc rename to plugins/traffic_dump/unit_tests/test_json_utils.cc diff --git a/plugins/experimental/traffic_dump/unit_tests/test_sensitive_fields.cc b/plugins/traffic_dump/unit_tests/test_sensitive_fields.cc similarity index 100% rename from plugins/experimental/traffic_dump/unit_tests/test_sensitive_fields.cc rename to plugins/traffic_dump/unit_tests/test_sensitive_fields.cc diff --git a/plugins/experimental/traffic_dump/unit_tests/unit_test_main.cc b/plugins/traffic_dump/unit_tests/unit_test_main.cc similarity index 100% rename from plugins/experimental/traffic_dump/unit_tests/unit_test_main.cc rename to plugins/traffic_dump/unit_tests/unit_test_main.cc diff --git a/plugins/experimental/webp_transform/ImageTransform.cc b/plugins/webp_transform/ImageTransform.cc similarity index 100% rename from plugins/experimental/webp_transform/ImageTransform.cc rename to plugins/webp_transform/ImageTransform.cc diff --git a/plugins/experimental/webp_transform/Makefile.inc b/plugins/webp_transform/Makefile.inc similarity index 66% rename from plugins/experimental/webp_transform/Makefile.inc rename to plugins/webp_transform/Makefile.inc index a2ac4f0ab08..b94059a89bf 100644 --- a/plugins/experimental/webp_transform/Makefile.inc +++ b/plugins/webp_transform/Makefile.inc @@ -15,18 +15,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -experimental_webp_transform_webp_transform_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBMAGICKCPP_CFLAGS) -experimental_webp_transform_webp_transform_la_CXXFLAGS = $(AM_CXXFLAGS) +webp_transform_webp_transform_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBMAGICKCPP_CFLAGS) +webp_transform_webp_transform_la_CXXFLAGS = $(AM_CXXFLAGS) -pkglib_LTLIBRARIES += experimental/webp_transform/webp_transform.la +pkglib_LTLIBRARIES += webp_transform/webp_transform.la -experimental_webp_transform_webp_transform_la_SOURCES = \ - experimental/webp_transform/ImageTransform.cc +webp_transform_webp_transform_la_SOURCES = \ + webp_transform/ImageTransform.cc -experimental_webp_transform_webp_transform_la_LDFLAGS = \ +webp_transform_webp_transform_la_LDFLAGS = \ $(AM_LDFLAGS) \ -L$(top_builddir)/src/tscpp/api -experimental_webp_transform_webp_transform_la_LIBADD = \ +webp_transform_webp_transform_la_LIBADD = \ -ltscppapi \ $(LIBMAGICKCPP_LIBS) diff --git a/plugins/experimental/webp_transform/README b/plugins/webp_transform/README similarity index 100% rename from plugins/experimental/webp_transform/README rename to plugins/webp_transform/README diff --git a/tests/gold_tests/pluginTest/parent_select/body.gold b/tests/gold_tests/pluginTest/parent_select/body.gold deleted file mode 100755 index b220ced9569..00000000000 --- a/tests/gold_tests/pluginTest/parent_select/body.gold +++ /dev/null @@ -1 +0,0 @@ -This is the body. diff --git a/tests/gold_tests/pluginTest/parent_select/parent_select.test.py b/tests/gold_tests/pluginTest/parent_select/parent_select.test.py deleted file mode 100755 index 1903e0722d2..00000000000 --- a/tests/gold_tests/pluginTest/parent_select/parent_select.test.py +++ /dev/null @@ -1,147 +0,0 @@ -''' -''' -# 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. - -Test.Summary = ''' -Basic parent_select plugin test -''' - -Test.SkipUnless( - Condition.PluginExists('parent_select.so'), -) -Test.ContinueOnFail = False - -# Define and populate MicroServer. -# -server = Test.MakeOriginServer("server") -response_header = { - "headers": - "HTTP/1.1 200 OK\r\n" - "Connection: close\r\n" - "Cache-control: max-age=85000\r\n" - "\r\n", - "timestamp": "1469733493.993", - "body": "This is the body.\n" -} -num_objects = 32 -for i in range(num_objects): - request_header = { - "headers": - f"GET /obj{i} HTTP/1.1\r\n" - "Host: does.not.matter\r\n" # But cannot be omitted. - "\r\n", - "timestamp": "1469733493.993", - "body": "" - } - server.addResponse("sessionlog.json", request_header, response_header) - -dns = Test.MakeDNServer("dns") - -# Define next hop trafficserver instances. -# -num_nh = 8 -ts_nh = [] -for i in range(num_nh): - ts = Test.MakeATSProcess(f"ts_nh{i}", use_traffic_out=False, command=f"traffic_server 2>nh_trace{i}.log") - ts.Disk.records_config.update({ - 'proxy.config.diags.debug.enabled': 1, - 'proxy.config.diags.debug.tags': 'http|dns', - 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", - 'proxy.config.dns.resolv_conf': "NULL", - }) - ts.Disk.remap_config.AddLine( - f"map / http://127.0.0.1:{server.Variables.Port}" - ) - ts_nh.append(ts) - -ts = Test.MakeATSProcess("ts") - -ts.Disk.records_config.update({ - 'proxy.config.diags.debug.enabled': 1, - 'proxy.config.diags.debug.tags': 'http|dns|parent|next_hop|host_statuses|hostdb', - 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", # Only nameservers if resolv_conf NULL. - 'proxy.config.dns.resolv_conf': "NULL", # This defaults to /etc/resvolv.conf (OS namesevers) if not NULL. - 'proxy.config.http.cache.http': 0, - 'proxy.config.http.uncacheable_requests_bypass_parent': 0, - 'proxy.config.http.no_dns_just_forward_to_parent': 1, - 'proxy.config.http.parent_proxy.mark_down_hostdb': 0, - 'proxy.config.http.parent_proxy.self_detect': 0, -}) - -ts.Disk.File(ts.Variables.CONFIGDIR + "/strategies.yaml", id="strategies", typename="ats:config") -s = ts.Disk.strategies -s.AddLine("groups:") -s.AddLine(" - &g1") -for i in range(num_nh): - dns.addRecords(records={f"next_hop{i}": ["127.0.0.1"]}) - s.AddLine(f" - host: next_hop{i}") - s.AddLine(f" protocol:") - s.AddLine(f" - scheme: http") - s.AddLine(f" port: {ts_nh[i].Variables.port}") - # The health check URL does not seem to be used currently. - # s.AddLine(f" health_check_url: http://next_hop{i}:{ts_nh[i].Variables.port}") - s.AddLine(f" weight: 1.0") -s.AddLines([ - "strategies:", - " - strategy: the-strategy", - " policy: consistent_hash", - " hash_key: path", - " go_direct: false", - " parent_is_proxy: true", - " ignore_self_detect: true", - " groups:", - " - *g1", - " scheme: http"]) - -# Fallover not currently tested. -# -# s.AddLines([ -# " fallover:", -# " max_simple_retries: 2", -# " ring_mode: exhaust_ring", -# " response_codes:", -# " - 404", -# " health_check:", -# " - passive"]) - -ts.Disk.remap_config.AddLine( - "map http://dummy.com http://not_used @plugin=parent_select.so @pparam=" + - ts.Variables.CONFIGDIR + - "/strategies.yaml @pparam=the-strategy") - -tr = Test.AddTestRun() -tr.Processes.Default.StartBefore(server) -tr.Processes.Default.StartBefore(dns) -for i in range(num_nh): - tr.Processes.Default.StartBefore(ts_nh[i]) -tr.Processes.Default.StartBefore(Test.Processes.ts) -tr.Processes.Default.Command = 'echo start TS, HTTP server, DNS server and next hop TSes' -tr.Processes.Default.ReturnCode = 0 - -for i in range(num_objects): - tr = Test.AddTestRun() - tr.Processes.Default.Command = ( - f'curl --verbose --proxy 127.0.0.1:{ts.Variables.port} http://dummy.com/obj{i}' - ) - tr.Processes.Default.Streams.stdout = "body.gold" - tr.Processes.Default.ReturnCode = 0 - -tr = Test.AddTestRun() -# For some reason, the * won't be expanded when the command is executed, if stdout is not piped through "cat". -tr.Processes.Default.Command = "grep -F '200 OK' nh_trace*.log | cat" -tr.Processes.Default.Streams.stdout = "trace.gold" -tr.Processes.Default.ReturnCode = 0 diff --git a/tests/gold_tests/pluginTest/parent_select/parent_select_optional_scheme_matching.test.py b/tests/gold_tests/pluginTest/parent_select/parent_select_optional_scheme_matching.test.py deleted file mode 100755 index fd0362528d7..00000000000 --- a/tests/gold_tests/pluginTest/parent_select/parent_select_optional_scheme_matching.test.py +++ /dev/null @@ -1,132 +0,0 @@ -''' -''' -# 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. - -Test.Summary = ''' -Basic parent_select plugin test -''' - -Test.SkipUnless( - Condition.PluginExists('parent_select.so'), -) -Test.ContinueOnFail = False - -# Define and populate MicroServer. -# -server = Test.MakeOriginServer("server") -response_header = { - "headers": - "HTTP/1.1 200 OK\r\n" - "Connection: close\r\n" - "Cache-control: max-age=85000\r\n" - "\r\n", - "timestamp": "1469733493.993", - "body": "This is the body.\n" -} -num_objects = 32 -for i in range(num_objects): - request_header = { - "headers": - f"GET /obj{i} HTTP/1.1\r\n" - "Host: does.not.matter\r\n" # But cannot be omitted. - "\r\n", - "timestamp": "1469733493.993", - "body": "" - } - server.addResponse("sessionlog.json", request_header, response_header) - -dns = Test.MakeDNServer("dns") - -# Define next hop trafficserver instances. -# -num_nh = 8 -ts_nh = [] -for i in range(num_nh): - ts = Test.MakeATSProcess(f"ts_nh{i}", use_traffic_out=False, command=f"traffic_server 2>nh_trace{i}.log") - ts.Disk.records_config.update({ - 'proxy.config.diags.debug.enabled': 1, - 'proxy.config.diags.debug.tags': 'http|dns', - 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", - 'proxy.config.dns.resolv_conf': "NULL", - }) - ts.Disk.remap_config.AddLine( - f"map / http://127.0.0.1:{server.Variables.Port}" - ) - ts_nh.append(ts) - -ts = Test.MakeATSProcess("ts") - -ts.Disk.records_config.update({ - 'proxy.config.diags.debug.enabled': 1, - 'proxy.config.diags.debug.tags': 'http|dns|parent|next_hop|host_statuses|hostdb', - 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", # Only nameservers if resolv_conf NULL. - 'proxy.config.dns.resolv_conf': "NULL", # This defaults to /etc/resvolv.conf (OS namesevers) if not NULL. - 'proxy.config.http.cache.http': 0, - 'proxy.config.http.uncacheable_requests_bypass_parent': 0, - 'proxy.config.http.no_dns_just_forward_to_parent': 1, - 'proxy.config.http.parent_proxy.mark_down_hostdb': 0, - 'proxy.config.http.parent_proxy.self_detect': 0, -}) - -ts.Disk.File(ts.Variables.CONFIGDIR + "/strategies.yaml", id="strategies", typename="ats:config") -s = ts.Disk.strategies -s.AddLine("groups:") -s.AddLine(" - &g1") -for i in range(num_nh): - dns.addRecords(records={f"next_hop{i}": ["127.0.0.1"]}) - s.AddLine(f" - host: next_hop{i}") - s.AddLine(f" protocol:") - s.AddLine(f" - port: {ts_nh[i].Variables.port}") - # The health check URL does not seem to be used currently. - # s.AddLine(f" health_check_url: http://next_hop{i}:{ts_nh[i].Variables.port}") - s.AddLine(f" weight: 1.0") -s.AddLines([ - "strategies:", - " - strategy: the-strategy", - " policy: consistent_hash", - " hash_key: path", - " go_direct: false", - " parent_is_proxy: true", - " ignore_self_detect: true", - " groups:", - " - *g1"]) - -ts.Disk.remap_config.AddLine( - "map http://dummy.com http://not_used @plugin=parent_select.so @pparam=strategies.yaml @pparam=the-strategy") - -tr = Test.AddTestRun() -tr.Processes.Default.StartBefore(server) -tr.Processes.Default.StartBefore(dns) -for i in range(num_nh): - tr.Processes.Default.StartBefore(ts_nh[i]) -tr.Processes.Default.StartBefore(Test.Processes.ts) -tr.Processes.Default.Command = 'echo start TS, HTTP server, DNS server and next hop TSes' -tr.Processes.Default.ReturnCode = 0 - -for i in range(num_objects): - tr = Test.AddTestRun() - tr.Processes.Default.Command = ( - f'curl --verbose --proxy 127.0.0.1:{ts.Variables.port} http://dummy.com/obj{i}' - ) - tr.Processes.Default.Streams.stdout = "body.gold" - tr.Processes.Default.ReturnCode = 0 - -tr = Test.AddTestRun() -# For some reason, the * won't be expanded when the command is executed, if stdout is not piped through "cat". -tr.Processes.Default.Command = "grep -F '200 OK' nh_trace*.log | cat" -tr.Processes.Default.Streams.stdout = "trace.gold" -tr.Processes.Default.ReturnCode = 0 diff --git a/tests/gold_tests/pluginTest/parent_select/parent_select_peer.test.py b/tests/gold_tests/pluginTest/parent_select/parent_select_peer.test.py deleted file mode 100644 index fcc8d7594b6..00000000000 --- a/tests/gold_tests/pluginTest/parent_select/parent_select_peer.test.py +++ /dev/null @@ -1,177 +0,0 @@ -''' -''' -# 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. - -Test.Summary = ''' -Test next hop selection using strategies.yaml with consistent hashing, with peering. -''' - -# The tls_conn_timeout test will fail if it runs before this test in CI. Therefore, this test has a zzz -# prefix so it will run last in CI. - -# Define and populate MicroServer. -# -server = Test.MakeOriginServer("server") -response_header = { - "headers": - "HTTP/1.1 200 OK\r\n" - "Connection: close\r\n" - "Cache-control: max-age=85000\r\n" - "\r\n", - "timestamp": "1469733493.993", - "body": "This is the body.\n" -} -num_object = 16 -for i in range(num_object): - request_header = { - "headers": - f"GET /obj{i} HTTP/1.1\r\n" - "Host: does.not.matter\r\n" # But cannot be omitted. - "\r\n", - "timestamp": "1469733493.993", - "body": "" - } - server.addResponse("sessionlog.json", request_header, response_header) - -dns = Test.MakeDNServer("dns") - -# Define upstream trafficserver instances. -# -num_upstream = 6 -ts_upstream = [] -for i in range(num_upstream): - ts = Test.MakeATSProcess(f"ts_upstream{i}") - dns.addRecords(records={f"ts_upstream{i}": ["127.0.0.1"]}) - ts.Disk.records_config.update({ - 'proxy.config.diags.debug.enabled': 1, - 'proxy.config.diags.debug.tags': 'http|dns', - 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", - 'proxy.config.dns.resolv_conf': "NULL", - }) - ts.Disk.remap_config.AddLine( - f"map / http://127.0.0.1:{server.Variables.Port}" - ) - ts_upstream.append(ts) - -# Define peer trafficserver instances. -# -num_peer = 8 -ts_peer = [] -for i in range(num_peer): - ts = Test.MakeATSProcess(f"ts_peer{i}", use_traffic_out=False, command=f"traffic_server 2> trace_peer{i}.log") - ts_peer.append(ts) -for i in range(num_peer): - ts = ts_peer[i] - dns.addRecords(records={f"ts_peer{i}": ["127.0.0.1"]}) - - ts.Disk.records_config.update({ - 'proxy.config.diags.debug.enabled': 1, - 'proxy.config.diags.debug.tags': 'http|dns|parent|next_hop|host_statuses|hostdb|cachekey|pparent_select', - 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", # Only nameservers if resolv_conf NULL. - 'proxy.config.dns.resolv_conf': "NULL", # This defaults to /etc/resvolv.conf (OS namesevers) if not NULL. - 'proxy.config.http.cache.http': 1, - 'proxy.config.http.cache.required_headers': 0, - 'proxy.config.http.uncacheable_requests_bypass_parent': 0, - 'proxy.config.http.no_dns_just_forward_to_parent': 1, - 'proxy.config.http.parent_proxy.mark_down_hostdb': 0, - 'proxy.config.http.parent_proxy.self_detect': 1, - }) - - ts.Disk.File(ts.Variables.CONFIGDIR + "/strategies.yaml", id="strategies", typename="ats:config") - s = ts.Disk.strategies - s.AddLine("groups:") - s.AddLine(" - &peer_group") - for j in range(num_peer): - s.AddLine(f" - host: ts_peer{j}") - s.AddLine(f" protocol:") - s.AddLine(f" - scheme: http") - s.AddLine(f" port: {ts_peer[j].Variables.port}") - # The health check URL does not seem to be used currently. - # s.AddLine(f" health_check_url: http://ts_peer{j}:{ts_peer[j].Variables.port}") - s.AddLine(f" weight: 1.0") - s.AddLine(" - &peer_upstream") - for j in range(num_upstream): - s.AddLine(f" - host: ts_upstream{j}") - s.AddLine(f" protocol:") - s.AddLine(f" - scheme: http") - s.AddLine(f" port: {ts_upstream[j].Variables.port}") - # The health check URL does not seem to be used currently. - # s.AddLine(f" health_check_url: http://ts_upstream{j}:{ts_upstream[j].Variables.port}") - s.AddLine(f" weight: 1.0") - s.AddLines([ - "strategies:", - " - strategy: the-strategy", - " policy: consistent_hash", - " hash_key: cache_key", - " go_direct: false", - " parent_is_proxy: true", - " cache_peer_result: false", - " ignore_self_detect: false", - " groups:", - " - *peer_group", - " - *peer_upstream", - " scheme: http", - " failover:", - " ring_mode: peering_ring", - f" self: ts_peer{i}", - #" max_simple_retries: 2", - #" response_codes:", - #" - 404", - #" health_check:", - #" - passive", - ]) - - suffix = " @plugin=parent_select.so @pparam=strategies.yaml @pparam=the-strategy @plugin=cachekey.so @pparam=--uri-type=remap @pparam=--capture-prefix=/(.*):(.*)/$1/" - ts.Disk.remap_config.AddLines([ - "map http://dummy.com http://not_used" + suffix, - "map http://not_used http://also_not_used" + suffix, - ]) - -tr = Test.AddTestRun() -tr.Processes.Default.StartBefore(server) -tr.Processes.Default.StartBefore(dns) -for i in range(num_peer): - tr.Processes.Default.StartBefore(ts_peer[i]) -for i in range(num_upstream): - tr.Processes.Default.StartBefore(ts_upstream[i]) -tr.Processes.Default.Command = 'echo start peer and upstream TSes, HTTP server and DNS server' -tr.Processes.Default.ReturnCode = 0 - -for i in range(num_object): - tr = Test.AddTestRun() - tr.Processes.Default.Command = ( - f'curl --verbose --proxy 127.0.0.1:{ts_peer[i % num_peer].Variables.port} http://dummy.com/obj{i}' - ) - tr.Processes.Default.Streams.stdout = "peer.body.gold" - tr.Processes.Default.ReturnCode = 0 - -for i in range(num_object): - tr = Test.AddTestRun() - # num_peer must not be a multiple of 3 - tr.Processes.Default.Command = ( - f'curl --verbose --proxy 127.0.0.1:{ts_peer[(i * 3) % num_peer].Variables.port} http://dummy.com/obj{i}' - ) - tr.Processes.Default.Streams.stdout = "peer.body.gold" - tr.Processes.Default.ReturnCode = 0 - -tr = Test.AddTestRun() -tr.Processes.Default.Command = ( - "grep -e '^+++' -e '^[A-Z].*TTP/' -e '^.alts. --' -e 'PARENT_SPECIFIED' trace_peer*.log" - " | sed 's/^.*(pparent_select) [^ ]* //' | sed 's/[.][0-9]*$$//'" -) -tr.Processes.Default.Streams.stdout = "peer.trace.gold" -tr.Processes.Default.ReturnCode = 0 diff --git a/tests/gold_tests/pluginTest/parent_select/parent_select_peer2.test.py b/tests/gold_tests/pluginTest/parent_select/parent_select_peer2.test.py deleted file mode 100644 index 48a6f6078ba..00000000000 --- a/tests/gold_tests/pluginTest/parent_select/parent_select_peer2.test.py +++ /dev/null @@ -1,170 +0,0 @@ -''' -''' -# 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. - -Test.Summary = ''' -Test next hop using strategies.yaml with consistent hashing, with peering, and no upstream group" -''' - -# The tls_conn_timeout test will fail if it runs before this test in CI. Therefore, this test has a zzz -# prefix so it will run last in CI. - -# Define and populate MicroServer. -# -server = Test.MakeOriginServer("server") -response_header = { - "headers": - "HTTP/1.1 200 OK\r\n" - "Connection: close\r\n" - "Cache-control: max-age=85000\r\n" - "\r\n", - "timestamp": "1469733493.993", - "body": "This is the body.\n" -} -num_object = 16 -for i in range(num_object): - request_header = { - "headers": - f"GET /obj{i} HTTP/1.1\r\n" - "Host: does.not.matter\r\n" # But cannot be omitted. - "\r\n", - "timestamp": "1469733493.993", - "body": "" - } - server.addResponse("sessionlog.json", request_header, response_header) - -dns = Test.MakeDNServer("dns") - -# Define upstream trafficserver instances. -# -num_upstream = 6 -ts_upstream = [] -for i in range(num_upstream): - ts = Test.MakeATSProcess(f"ts_upstream{i}") - dns.addRecords(records={f"ts_upstream{i}": ["127.0.0.1"]}) - ts.Disk.records_config.update({ - 'proxy.config.diags.debug.enabled': 1, - 'proxy.config.diags.debug.tags': 'http|dns', - 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", - 'proxy.config.dns.resolv_conf': "NULL", - }) - ts.Disk.remap_config.AddLine( - f"map / http://127.0.0.1:{server.Variables.Port}" - ) - ts_upstream.append(ts) - -# Define peer trafficserver instances. -# -num_peer = 8 -ts_peer = [] -for i in range(num_peer): - ts = Test.MakeATSProcess(f"ts_peer{i}", use_traffic_out=False, command=f"traffic_server 2> trace_peer{i}.log") - ts_peer.append(ts) -for i in range(num_peer): - ts = ts_peer[i] - dns.addRecords(records={f"ts_peer{i}": ["127.0.0.1"]}) - - ts.Disk.records_config.update({ - 'proxy.config.diags.debug.enabled': 1, - 'proxy.config.diags.debug.tags': 'http|dns|parent|next_hop|host_statuses|hostdb|pparent_select', - 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", # Only nameservers if resolv_conf NULL. - 'proxy.config.dns.resolv_conf': "NULL", # This defaults to /etc/resvolv.conf (OS namesevers) if not NULL. - 'proxy.config.http.cache.http': 1, - 'proxy.config.http.cache.required_headers': 0, - 'proxy.config.http.uncacheable_requests_bypass_parent': 0, - 'proxy.config.http.no_dns_just_forward_to_parent': 0, - 'proxy.config.http.parent_proxy.mark_down_hostdb': 0, - 'proxy.config.http.parent_proxy.self_detect': 1, - }) - - ts.Disk.File(ts.Variables.CONFIGDIR + "/strategies.yaml", id="strategies", typename="ats:config") - s = ts.Disk.strategies - s.AddLine("groups:") - s.AddLine(" - &peer_group") - for j in range(num_peer): - s.AddLine(f" - host: ts_peer{j}") - s.AddLine(f" protocol:") - s.AddLine(f" - scheme: http") - s.AddLine(f" port: {ts_peer[j].Variables.port}") - # The health check URL does not seem to be used currently. - # s.AddLine(f" health_check_url: http://ts_peer{j}:{ts_peer[j].Variables.port}") - s.AddLine(f" weight: 1.0") - s.AddLines([ - "strategies:", - " - strategy: the-strategy", - " policy: consistent_hash", - " hash_key: path", - " go_direct: true", - " parent_is_proxy: true", - " cache_peer_result: false", - " ignore_self_detect: false", - " groups:", - " - *peer_group", - " scheme: http", - " failover:", - " ring_mode: peering_ring", - f" self: ts_peer{i}", - #" max_simple_retries: 2", - #" response_codes:", - #" - 404", - #" health_check:", - #" - passive", - ]) - - for i in range(num_upstream): - prefix = f"http://ts_upstream{i}:{ts_upstream[i].Variables.port}/" - ts.Disk.remap_config.AddLine( - f"map {prefix} {prefix} @plugin=parent_select.so @pparam=strategies.yaml @pparam=the-strategy") - -tr = Test.AddTestRun() -tr.Processes.Default.StartBefore(server) -tr.Processes.Default.StartBefore(dns) -for i in range(num_peer): - tr.Processes.Default.StartBefore(ts_peer[i]) -for i in range(num_upstream): - tr.Processes.Default.StartBefore(ts_upstream[i]) -tr.Processes.Default.Command = 'echo start peer and upstream TSes, HTTP server and DNS server' -tr.Processes.Default.ReturnCode = 0 - -for i in range(num_object): - tr = Test.AddTestRun() - tr.Processes.Default.Command = ( - f'curl --verbose --proxy 127.0.0.1:{ts_peer[i % num_peer].Variables.port} http://ts_upstream0:{ts_upstream[0].Variables.port}/obj{i}' - ) - tr.Processes.Default.Streams.stdout = "peer2.body.gold" - tr.Processes.Default.ReturnCode = 0 - -for i in range(num_object): - tr = Test.AddTestRun() - # num_peer must not be a multiple of 3 - tr.Processes.Default.Command = ( - f'curl --verbose --proxy 127.0.0.1:{ts_peer[(i * 3) % num_peer].Variables.port} http://ts_upstream0:{ts_upstream[0].Variables.port}/obj{i}' - ) - tr.Processes.Default.Streams.stdout = "peer2.body.gold" - tr.Processes.Default.ReturnCode = 0 - -normalize_ports = "" -for i in range(num_upstream): - normalize_ports += f" | sed 's/:{ts_upstream[i].Variables.port}/:UP_PORT{i}/'" - -tr = Test.AddTestRun() -tr.Processes.Default.Command = ( - "grep -e '^+++' -e '^[A-Z].*TTP/' -e '^.alts. --' -e 'PARENT_SPECIFIED' trace_peer*.log" - " | sed 's/^.*(pparent_select) [^ ]* //' | sed 's/[.][0-9]*$$//' " + normalize_ports -) -tr.Processes.Default.Streams.stdout = "peer2.trace.gold" -tr.Processes.Default.ReturnCode = 0 diff --git a/tests/gold_tests/pluginTest/parent_select/peer.body.gold b/tests/gold_tests/pluginTest/parent_select/peer.body.gold deleted file mode 100755 index b220ced9569..00000000000 --- a/tests/gold_tests/pluginTest/parent_select/peer.body.gold +++ /dev/null @@ -1 +0,0 @@ -This is the body. diff --git a/tests/gold_tests/pluginTest/parent_select/peer.trace.gold b/tests/gold_tests/pluginTest/parent_select/peer.trace.gold deleted file mode 100644 index 85da7695933..00000000000 --- a/tests/gold_tests/pluginTest/parent_select/peer.trace.gold +++ /dev/null @@ -1,898 +0,0 @@ -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://dummy.com/obj0 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer0.log:+++++++++ Proxy's Request +++++++++ -trace_peer0.log:GET http://not_used/obj0 HTTP/1.1 -trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer0.log:GET http://not_used/obj0 HTTP/1.1 -trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer0.log:GET http://not_used/obj0 HTTP/1.1 -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://not_used/obj7 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer0.log:+++++++++ Proxy's Request +++++++++ -trace_peer0.log:GET http://also_not_used/obj7 HTTP/1.1 -trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer0.log:GET http://also_not_used/obj7 HTTP/1.1 -trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer0.log:GET http://also_not_used/obj7 HTTP/1.1 -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://dummy.com/obj8 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer6 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer0.log:+++++++++ Proxy's Request +++++++++ -trace_peer0.log:GET http://not_used/obj8 HTTP/1.1 -trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer0.log:GET http://not_used/obj8 HTTP/1.1 -trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer0.log:GET http://not_used/obj8 HTTP/1.1 -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://dummy.com/obj0 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer0.log:GET http://not_used/obj0 HTTP/1.1 -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://not_used/obj7 HTTP/1.1 -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer0.log:GET http://also_not_used/obj7 HTTP/1.1 -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://dummy.com/obj8 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer6 -trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer0.log:GET http://not_used/obj8 HTTP/1.1 -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://dummy.com/obj1 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer1.log:+++++++++ Proxy's Request +++++++++ -trace_peer1.log:GET http://not_used/obj1 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer1.log:GET http://not_used/obj1 HTTP/1.1 -trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer1.log:GET http://not_used/obj1 HTTP/1.1 -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://dummy.com/obj9 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer1.log:+++++++++ Proxy's Request +++++++++ -trace_peer1.log:GET http://not_used/obj9 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer1.log:GET http://not_used/obj9 HTTP/1.1 -trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer1.log:GET http://not_used/obj9 HTTP/1.1 -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://not_used/obj10 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer1.log:+++++++++ Proxy's Request +++++++++ -trace_peer1.log:GET http://also_not_used/obj10 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer1.log:GET http://also_not_used/obj10 HTTP/1.1 -trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer1.log:GET http://also_not_used/obj10 HTTP/1.1 -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://dummy.com/obj3 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer1.log:+++++++++ Proxy's Request +++++++++ -trace_peer1.log:GET http://not_used/obj3 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer1.log:GET http://not_used/obj3 HTTP/1.1 -trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer1.log:GET http://not_used/obj3 HTTP/1.1 -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://not_used/obj10 HTTP/1.1 -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -trace_peer1.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer1.log:GET http://also_not_used/obj10 HTTP/1.1 -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://dummy.com/obj11 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer1.log:+++++++++ Proxy's Request +++++++++ -trace_peer1.log:GET http://not_used/obj11 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer1.log:GET http://not_used/obj11 HTTP/1.1 -trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer1.log:GET http://not_used/obj11 HTTP/1.1 -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://dummy.com/obj2 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://not_used/obj2 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://not_used/obj2 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://not_used/obj2 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://not_used/obj3 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://also_not_used/obj3 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://also_not_used/obj3 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://also_not_used/obj3 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://not_used/obj4 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://also_not_used/obj4 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://also_not_used/obj4 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://also_not_used/obj4 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://not_used/obj5 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://also_not_used/obj5 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://also_not_used/obj5 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://also_not_used/obj5 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://not_used/obj6 HTTP/1.1 -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://also_not_used/obj6 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://also_not_used/obj6 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://also_not_used/obj6 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://dummy.com/obj10 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer1 -[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://not_used/obj10 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://not_used/obj10 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://not_used/obj10 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://not_used/obj12 HTTP/1.1 -[6] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -[6] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[6] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://also_not_used/obj12 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://also_not_used/obj12 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://also_not_used/obj12 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://not_used/obj3 HTTP/1.1 -[7] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer2.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer2.log:GET http://also_not_used/obj3 HTTP/1.1 -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://not_used/obj5 HTTP/1.1 -[8] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer2.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer2.log:GET http://also_not_used/obj5 HTTP/1.1 -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://dummy.com/obj6 HTTP/1.1 -[9] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -[9] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[9] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://not_used/obj6 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://not_used/obj6 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://not_used/obj6 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://dummy.com/obj14 HTTP/1.1 -[10] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5 -[10] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[10] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://not_used/obj14 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://not_used/obj14 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://not_used/obj14 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://not_used/obj0 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://also_not_used/obj0 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://also_not_used/obj0 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://also_not_used/obj0 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://dummy.com/obj3 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://not_used/obj3 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://not_used/obj3 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://not_used/obj3 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://dummy.com/obj11 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://not_used/obj11 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://not_used/obj11 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://not_used/obj11 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://not_used/obj13 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://also_not_used/obj13 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://also_not_used/obj13 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://also_not_used/obj13 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://not_used/obj15 HTTP/1.1 -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream1 -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://also_not_used/obj15 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://also_not_used/obj15 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://also_not_used/obj15 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://dummy.com/obj1 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5 -[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://not_used/obj1 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://not_used/obj1 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://not_used/obj1 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://dummy.com/obj9 HTTP/1.1 -[6] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[6] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[6] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://not_used/obj9 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://not_used/obj9 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://not_used/obj9 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://not_used/obj13 HTTP/1.1 -[7] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer3.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer3.log:GET http://also_not_used/obj13 HTTP/1.1 -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://not_used/obj15 HTTP/1.1 -[8] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -trace_peer3.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer3.log:GET http://also_not_used/obj15 HTTP/1.1 -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Incoming Request +++++++++ -trace_peer4.log:GET http://dummy.com/obj4 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer4.log:+++++++++ Proxy's Request +++++++++ -trace_peer4.log:GET http://not_used/obj4 HTTP/1.1 -trace_peer4.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer4.log:GET http://not_used/obj4 HTTP/1.1 -trace_peer4.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer4.log:GET http://not_used/obj4 HTTP/1.1 -trace_peer4.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Incoming Request +++++++++ -trace_peer4.log:GET http://dummy.com/obj12 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer4.log:+++++++++ Proxy's Request +++++++++ -trace_peer4.log:GET http://not_used/obj12 HTTP/1.1 -trace_peer4.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer4.log:GET http://not_used/obj12 HTTP/1.1 -trace_peer4.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer4.log:GET http://not_used/obj12 HTTP/1.1 -trace_peer4.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Incoming Request +++++++++ -trace_peer4.log:GET http://dummy.com/obj4 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -trace_peer4.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer4.log:GET http://not_used/obj4 HTTP/1.1 -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Incoming Request +++++++++ -trace_peer4.log:GET http://dummy.com/obj12 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -trace_peer4.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer4.log:GET http://not_used/obj12 HTTP/1.1 -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://not_used/obj1 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET http://also_not_used/obj1 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET http://also_not_used/obj1 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://also_not_used/obj1 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://dummy.com/obj5 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET http://not_used/obj5 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET http://not_used/obj5 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://not_used/obj5 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://dummy.com/obj13 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET http://not_used/obj13 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET http://not_used/obj13 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://not_used/obj13 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://not_used/obj14 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream1 -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET http://also_not_used/obj14 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET http://also_not_used/obj14 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://also_not_used/obj14 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://not_used/obj1 HTTP/1.1 -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer5.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer5.log:GET http://also_not_used/obj1 HTTP/1.1 -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://dummy.com/obj7 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer0 -[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET http://not_used/obj7 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET http://not_used/obj7 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://not_used/obj7 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://not_used/obj14 HTTP/1.1 -[6] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer5.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer5.log:GET http://also_not_used/obj14 HTTP/1.1 -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://dummy.com/obj15 HTTP/1.1 -[7] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -[7] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[7] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET http://not_used/obj15 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET http://not_used/obj15 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://not_used/obj15 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Incoming Request +++++++++ -trace_peer6.log:GET http://dummy.com/obj6 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer6.log:+++++++++ Proxy's Request +++++++++ -trace_peer6.log:GET http://not_used/obj6 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer6.log:GET http://not_used/obj6 HTTP/1.1 -trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer6.log:GET http://not_used/obj6 HTTP/1.1 -trace_peer6.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Incoming Request +++++++++ -trace_peer6.log:GET http://not_used/obj8 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream3 -trace_peer6.log:+++++++++ Proxy's Request +++++++++ -trace_peer6.log:GET http://also_not_used/obj8 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer6.log:GET http://also_not_used/obj8 HTTP/1.1 -trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer6.log:GET http://also_not_used/obj8 HTTP/1.1 -trace_peer6.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Incoming Request +++++++++ -trace_peer6.log:GET http://dummy.com/obj14 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer6.log:+++++++++ Proxy's Request +++++++++ -trace_peer6.log:GET http://not_used/obj14 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer6.log:GET http://not_used/obj14 HTTP/1.1 -trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer6.log:GET http://not_used/obj14 HTTP/1.1 -trace_peer6.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Incoming Request +++++++++ -trace_peer6.log:GET http://dummy.com/obj2 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer6.log:+++++++++ Proxy's Request +++++++++ -trace_peer6.log:GET http://not_used/obj2 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer6.log:GET http://not_used/obj2 HTTP/1.1 -trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer6.log:GET http://not_used/obj2 HTTP/1.1 -trace_peer6.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Incoming Request +++++++++ -trace_peer6.log:GET http://dummy.com/obj10 HTTP/1.1 -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_peer1 -[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -trace_peer6.log:+++++++++ Proxy's Request +++++++++ -trace_peer6.log:GET http://not_used/obj10 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer6.log:GET http://not_used/obj10 HTTP/1.1 -trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer6.log:GET http://not_used/obj10 HTTP/1.1 -trace_peer6.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://not_used/obj2 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://also_not_used/obj2 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://also_not_used/obj2 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://also_not_used/obj2 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://dummy.com/obj7 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer0 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://not_used/obj7 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://not_used/obj7 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://not_used/obj7 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://not_used/obj9 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://also_not_used/obj9 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://also_not_used/obj9 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://also_not_used/obj9 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://not_used/obj11 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://also_not_used/obj11 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://also_not_used/obj11 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://also_not_used/obj11 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://dummy.com/obj15 HTTP/1.1 -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4 -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://not_used/obj15 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://not_used/obj15 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://not_used/obj15 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://not_used/obj2 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer7.log:GET http://also_not_used/obj2 HTTP/1.1 -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://dummy.com/obj5 HTTP/1.1 -[6] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[6] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[6] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5 -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://not_used/obj5 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://not_used/obj5 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://not_used/obj5 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://not_used/obj9 HTTP/1.1 -[7] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0 -trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer7.log:GET http://also_not_used/obj9 HTTP/1.1 -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://not_used/obj11 HTTP/1.1 -[8] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer7.log:GET http://also_not_used/obj11 HTTP/1.1 -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://dummy.com/obj13 HTTP/1.1 -[9] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -[9] not firstcall, line_number: 0, result: PARENT_SPECIFIED -[9] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2 -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://not_used/obj13 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://not_used/obj13 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://not_used/obj13 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK diff --git a/tests/gold_tests/pluginTest/parent_select/peer2.body.gold b/tests/gold_tests/pluginTest/parent_select/peer2.body.gold deleted file mode 100644 index b220ced9569..00000000000 --- a/tests/gold_tests/pluginTest/parent_select/peer2.body.gold +++ /dev/null @@ -1 +0,0 @@ -This is the body. diff --git a/tests/gold_tests/pluginTest/parent_select/peer2.trace.gold b/tests/gold_tests/pluginTest/parent_select/peer2.trace.gold deleted file mode 100644 index 784cf5ed7d9..00000000000 --- a/tests/gold_tests/pluginTest/parent_select/peer2.trace.gold +++ /dev/null @@ -1,804 +0,0 @@ -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer0.log:+++++++++ Proxy's Request +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1 -trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1 -trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1 -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -trace_peer0.log:+++++++++ Proxy's Request +++++++++ -trace_peer0.log:GET /obj7 HTTP/1.1 -trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer0.log:GET /obj7 HTTP/1.1 -trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer6 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer0.log:+++++++++ Proxy's Request +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1 -trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1 -trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1 -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1 -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Incoming Request +++++++++ -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer6 -trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1 -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer0.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer1.log:+++++++++ Proxy's Request +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer1.log:+++++++++ Proxy's Request +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request +++++++++ -trace_peer1.log:GET /obj10 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer1.log:GET /obj10 HTTP/1.1 -trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer1.log:+++++++++ Proxy's Request +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -trace_peer1.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Incoming Request +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer1.log:+++++++++ Proxy's Request +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -trace_peer1.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer1.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET /obj3 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET /obj3 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET /obj4 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET /obj4 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET /obj5 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET /obj5 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET /obj6 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET /obj6 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer1 -[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET /obj12 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET /obj12 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -trace_peer2.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -trace_peer2.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1 -trace_peer2.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1 -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Incoming Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -[10] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5 -[10] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer2.log:+++++++++ Proxy's Request +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -trace_peer2.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer2.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET /obj0 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET /obj0 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET /obj13 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET /obj13 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET /obj15 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET /obj15 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5 -[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -[6] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[6] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer3.log:+++++++++ Proxy's Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -trace_peer3.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Incoming Request +++++++++ -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -trace_peer3.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer3.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Incoming Request +++++++++ -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer4.log:+++++++++ Proxy's Request +++++++++ -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1 -trace_peer4.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1 -trace_peer4.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1 -trace_peer4.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Incoming Request +++++++++ -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer4.log:+++++++++ Proxy's Request +++++++++ -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1 -trace_peer4.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1 -trace_peer4.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1 -trace_peer4.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Incoming Request +++++++++ -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -trace_peer4.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1 -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Incoming Request +++++++++ -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -trace_peer4.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1 -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer4.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET /obj1 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET /obj1 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET /obj14 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET /obj14 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -trace_peer5.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1 -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer0 -[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -trace_peer5.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Incoming Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -[7] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -[7] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer5.log:+++++++++ Proxy's Request +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -trace_peer5.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer5.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Incoming Request +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1 -[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer6.log:+++++++++ Proxy's Request +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1 -trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1 -trace_peer6.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Incoming Request +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request +++++++++ -trace_peer6.log:GET /obj8 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer6.log:GET /obj8 HTTP/1.1 -trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1 -trace_peer6.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Incoming Request +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5 -[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer6.log:+++++++++ Proxy's Request +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1 -trace_peer6.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Incoming Request +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7 -[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer6.log:+++++++++ Proxy's Request +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -trace_peer6.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Incoming Request +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_peer1 -[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer6.log:+++++++++ Proxy's Request +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1 -trace_peer6.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer6.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET /obj2 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET /obj2 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer0 -[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET /obj9 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET /obj9 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET /obj11 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET /obj11 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -[4] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1 -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -[6] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2 -[6] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1 -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs: -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1 -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Incoming Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -[9] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3 -[9] not firstcall, line_number: 0, result: PARENT_SPECIFIED -trace_peer7.log:+++++++++ Proxy's Request +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Cached Request Hdr +++++++++ -trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1 -trace_peer7.log:+++++++++ Base Header for Building Response +++++++++ -trace_peer7.log:HTTP/1.1 200 OK -trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++ -trace_peer7.log:HTTP/1.1 200 OK diff --git a/tests/gold_tests/pluginTest/parent_select/trace.gold b/tests/gold_tests/pluginTest/parent_select/trace.gold deleted file mode 100755 index 05120d365b0..00000000000 --- a/tests/gold_tests/pluginTest/parent_select/trace.gold +++ /dev/null @@ -1,96 +0,0 @@ -nh_trace0.log:HTTP/1.1 200 OK -nh_trace0.log:HTTP/1.1 200 OK -nh_trace0.log:HTTP/1.1 200 OK -nh_trace0.log:HTTP/1.1 200 OK -nh_trace0.log:HTTP/1.1 200 OK -nh_trace0.log:HTTP/1.1 200 OK -nh_trace0.log:HTTP/1.1 200 OK -nh_trace0.log:HTTP/1.1 200 OK -nh_trace0.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace1.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace2.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace3.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace4.log:HTTP/1.1 200 OK -nh_trace5.log:HTTP/1.1 200 OK -nh_trace5.log:HTTP/1.1 200 OK -nh_trace5.log:HTTP/1.1 200 OK -nh_trace5.log:HTTP/1.1 200 OK -nh_trace5.log:HTTP/1.1 200 OK -nh_trace5.log:HTTP/1.1 200 OK -nh_trace5.log:HTTP/1.1 200 OK -nh_trace5.log:HTTP/1.1 200 OK -nh_trace5.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace6.log:HTTP/1.1 200 OK -nh_trace7.log:HTTP/1.1 200 OK -nh_trace7.log:HTTP/1.1 200 OK -nh_trace7.log:HTTP/1.1 200 OK -nh_trace7.log:HTTP/1.1 200 OK -nh_trace7.log:HTTP/1.1 200 OK -nh_trace7.log:HTTP/1.1 200 OK diff --git a/tools/autopep8.sh b/tools/autopep8.sh index e489627a914..faabe4d9c9e 100755 --- a/tools/autopep8.sh +++ b/tools/autopep8.sh @@ -94,20 +94,6 @@ function main() { $(cat ${files_filtered}) find $(cat ${files_filtered}) -newer ${start_time_file} - # The above will not catch the Python files in the metalink tests because - # they do not have extensions. - metalink_dir=${DIR}/plugins/experimental/metalink/test - autopep8 \ - --ignore-local-config \ - -i \ - -j 0 \ - --exclude "${DIR}/lib/yamlcpp" \ - --max-line-length 132 \ - --aggressive \ - --aggressive \ - --recursive \ - ${metalink_dir} - find ${metalink_dir} -newer ${start_time_file} rm -rf ${tmp_dir} deactivate }