You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jp...@apache.org on 2014/03/29 00:31:31 UTC
[09/13] git commit: TS-2675: metalink: Don't finish computing the
digest more than once and test that the proxy rewrites the Location header if
the file is already cached
TS-2675: metalink: Don't finish computing the digest more than once and test that the proxy rewrites the Location header if the file is already cached
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/f9d74b9f
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/f9d74b9f
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/f9d74b9f
Branch: refs/heads/master
Commit: f9d74b9feefa2f7a4c8d59b6633efe9de8415d50
Parents: ea2f6f3
Author: Jack Bates <ja...@nottheoilrig.com>
Authored: Mon Mar 17 09:19:31 2014 -0700
Committer: James Peach <jp...@apache.org>
Committed: Fri Mar 28 16:23:54 2014 -0700
----------------------------------------------------------------------
plugins/experimental/metalink/metalink.cc | 13 ++-
plugins/experimental/metalink/test/location | 124 +++++++++++++++++++++++
2 files changed, 136 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/f9d74b9f/plugins/experimental/metalink/metalink.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc
index 3ad589d..ae8771c 100644
--- a/plugins/experimental/metalink/metalink.cc
+++ b/plugins/experimental/metalink/metalink.cc
@@ -367,7 +367,15 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
TSContCall(TSVIOContGet(input_viop), TS_EVENT_VCONN_WRITE_READY, input_viop);
- } else {
+ /* 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);
@@ -388,6 +396,9 @@ vconn_write_ready(TSCont contp, void */* edata ATS_UNUSED */)
WriteData *write_data = (WriteData *) TSmalloc(sizeof(WriteData));
write_data->txnp = transform_data->txnp;
+ /* Don't finish computing the digest more than once! */
+ transform_data->txnp = NULL;
+
write_data->key = TSCacheKeyCreate();
if (TSCacheKeyDigestSet(write_data->key, digest, sizeof(digest)) != TS_SUCCESS) {
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/f9d74b9f/plugins/experimental/metalink/test/location
----------------------------------------------------------------------
diff --git a/plugins/experimental/metalink/test/location b/plugins/experimental/metalink/test/location
new file mode 100755
index 0000000..77b601e
--- /dev/null
+++ b/plugins/experimental/metalink/test/location
@@ -0,0 +1,124 @@
+#!/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.
+
+print '''1..2 location
+# The proxy rewrites the Location header if the file is already cached'''
+
+from twisted.internet import error, protocol, reactor, tcp
+from twisted.web import http
+
+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':
+
+ 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.
+ connectionMade = lambda 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, staus, 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()