1''' 2''' 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, software 14# distributed under the License is distributed on an "AS IS" BASIS, 15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16# See the License for the specific language governing permissions and 17# limitations under the License. 18 19Test.Summary = ''' 20Basic cache_range_requests plugin test 21''' 22 23# Test description: 24# Preload the cache with the entire asset to be range requested. 25# Reload remap rule with cache_range_requests plugin 26# Request content through the cache_range_requests plugin 27 28Test.SkipUnless( 29 Condition.PluginExists('cache_range_requests.so'), 30 Condition.PluginExists('xdebug.so'), 31) 32Test.ContinueOnFail = False 33Test.testName = "cache_range_requests" 34 35# Define and configure ATS 36ts = Test.MakeATSProcess("ts", command="traffic_server") 37 38# Define and configure origin server 39server = Test.MakeOriginServer("server", lookup_key="{%uuid}") 40 41# default root 42req_chk = {"headers": 43 "GET / HTTP/1.1\r\n" + 44 "Host: www.example.com\r\n" + 45 "uuid: none\r\n" + 46 "\r\n", 47 "timestamp": "1469733493.993", 48 "body": "" 49 } 50 51res_chk = {"headers": 52 "HTTP/1.1 200 OK\r\n" + 53 "Connection: close\r\n" + 54 "\r\n", 55 "timestamp": "1469733493.993", 56 "body": "" 57 } 58 59server.addResponse("sessionlog.json", req_chk, res_chk) 60 61body = "lets go surfin now" 62 63req_full = {"headers": 64 "GET /path HTTP/1.1\r\n" + 65 "Host: www.example.com\r\n" + 66 "Accept: */*\r\n" + 67 "uuid: full\r\n" + 68 "\r\n", 69 "timestamp": "1469733493.993", 70 "body": "" 71 } 72 73res_full = {"headers": 74 "HTTP/1.1 200 OK\r\n" + 75 "Cache-Control: max-age=500\r\n" + 76 "Connection: close\r\n" + 77 'Etag: "path"\r\n' + 78 "\r\n", 79 "timestamp": "1469733493.993", 80 "body": body 81 } 82 83server.addResponse("sessionlog.json", req_full, res_full) 84 85block_bytes = 7 86bodylen = len(body) 87 88inner_str = "7-15" 89 90req_inner = {"headers": 91 "GET /path HTTP/1.1\r\n" + 92 "Host: www.example.com\r\n" + 93 "Accept: */*\r\n" + 94 "Range: bytes={}\r\n".format(inner_str) + 95 "uuid: inner\r\n" + 96 "\r\n", 97 "timestamp": "1469733493.993", 98 "body": "" 99 } 100 101res_inner = {"headers": 102 "HTTP/1.1 206 Partial Content\r\n" + 103 "Accept-Ranges: bytes\r\n" + 104 "Cache-Control: max-age=500\r\n" + 105 "Content-Range: bytes {0}/{1}\r\n".format(inner_str, bodylen) + 106 "Connection: close\r\n" + 107 'Etag: "path"\r\n' + 108 "\r\n", 109 "timestamp": "1469733493.993", 110 "body": body[7:15] 111 } 112 113server.addResponse("sessionlog.json", req_inner, res_inner) 114 115frange_str = "0-" 116 117req_frange = {"headers": 118 "GET /path HTTP/1.1\r\n" + 119 "Host: www.example.com\r\n" + 120 "Accept: */*\r\n" + 121 "Range: bytes={}\r\n".format(frange_str) + 122 "uuid: frange\r\n" + 123 "\r\n", 124 "timestamp": "1469733493.993", 125 "body": "" 126 } 127 128res_frange = {"headers": 129 "HTTP/1.1 206 Partial Content\r\n" + 130 "Accept-Ranges: bytes\r\n" + 131 "Cache-Control: max-age=500\r\n" + 132 "Content-Range: bytes 0-{0}/{0}\r\n".format(bodylen) + 133 "Connection: close\r\n" + 134 'Etag: "path"\r\n' + 135 "\r\n", 136 "timestamp": "1469733493.993", 137 "body": body 138 } 139 140server.addResponse("sessionlog.json", req_frange, res_frange) 141 142last_str = "-5" 143 144req_last = {"headers": 145 "GET /path HTTP/1.1\r\n" + 146 "Host: www.example.com\r\n" + 147 "Accept: */*\r\n" + 148 "Range: bytes={}\r\n".format(last_str) + 149 "uuid: last\r\n" + 150 "\r\n", 151 "timestamp": "1469733493.993", 152 "body": "" 153 } 154 155res_last = {"headers": 156 "HTTP/1.1 206 Partial Content\r\n" + 157 "Accept-Ranges: bytes\r\n" + 158 "Cache-Control: max-age=200\r\n" + 159 "Content-Range: bytes {0}-{1}/{1}\r\n".format(bodylen - 5, bodylen) + 160 "Connection: close\r\n" + 161 'Etag: "path"\r\n' + 162 "\r\n", 163 "timestamp": "1469733493.993", 164 "body": body[-5:] 165 } 166 167server.addResponse("sessionlog.json", req_last, res_last) 168 169pselect_str = "1-10" 170 171req_pselect = {"headers": 172 "GET /path HTTP/1.1\r\n" + 173 "Host: parentselect\r\n" + 174 "Accept: */*\r\n" + 175 "Range: bytes={}\r\n".format(pselect_str) + 176 "uuid: pselect\r\n" + 177 "\r\n", 178 "timestamp": "1469733493.993", 179 "body": "" 180 } 181 182res_pselect = {"headers": 183 "HTTP/1.1 206 Partial Content\r\n" + 184 "Accept-Ranges: bytes\r\n" + 185 "Cache-Control: max-age=200\r\n" + 186 "Content-Range: bytes {}/19\r\n".format(pselect_str) + 187 "Connection: close\r\n" + 188 'Etag: "path"\r\n' + 189 "\r\n", 190 "timestamp": "1469733493.993", 191 "body": body[1:10] 192 } 193 194server.addResponse("sessionlog.json", req_pselect, res_pselect) 195 196req_psd = {"headers": 197 "GET /path HTTP/1.1\r\n" + 198 "Host: psd\r\n" + 199 "Accept: */*\r\n" + 200 "Range: bytes={}\r\n".format(pselect_str) + 201 "uuid: pselect\r\n" + 202 "\r\n", 203 "timestamp": "1469733493.993", 204 "body": "" 205 } 206 207server.addResponse("sessionlog.json", req_psd, res_pselect) 208 209# cache range requests plugin remap 210ts.Disk.remap_config.AddLines([ 211 'map http://www.example.com http://127.0.0.1:{}'.format(server.Variables.Port) + 212 ' @plugin=cache_range_requests.so', 213 214 # parent select cache key option 215 'map http://parentselect http://127.0.0.1:{}'.format(server.Variables.Port) + 216 ' @plugin=cache_range_requests.so @pparam=--ps-cachekey', 217 218 # deprecated 219 'map http://psd http://127.0.0.1:{}'.format(server.Variables.Port) + 220 ' @plugin=cache_range_requests.so @pparam=ps_mode:cache_key_url', 221]) 222 223# cache debug 224ts.Disk.plugin_config.AddLine('xdebug.so') 225 226# minimal configuration 227ts.Disk.records_config.update({ 228 'proxy.config.diags.debug.enabled': 1, 229 'proxy.config.diags.debug.tags': 'cache_range_requests', 230}) 231 232curl_and_args = 'curl -s -D /dev/stdout -o /dev/stderr -x localhost:{} -H "x-debug: x-cache"'.format(ts.Variables.port) 233 234# 0 Test - Fetch whole asset into cache 235tr = Test.AddTestRun("full asset cache miss bypass") 236ps = tr.Processes.Default 237ps.StartBefore(server, ready=When.PortOpen(server.Variables.Port)) 238ps.StartBefore(Test.Processes.ts) 239ps.Command = curl_and_args + ' http://www.example.com/path -H "uuid: full"' 240ps.ReturnCode = 0 241ps.Streams.stderr = "gold/full.stderr.gold" 242tr.StillRunningAfter = ts 243 244# test inner range 245# 1 Test - Fetch range into cache 246tr = Test.AddTestRun("inner range cache miss") 247ps = tr.Processes.Default 248ps.Command = curl_and_args + ' http://www.example.com/path -r {} -H "uuid: inner"'.format(inner_str) 249ps.ReturnCode = 0 250ps.Streams.stderr = "gold/inner.stderr.gold" 251ps.Streams.stdout.Content = Testers.ContainsExpression("X-Cache: miss", "expected cache miss") 252ps.Streams.stdout.Content += Testers.ContainsExpression("Content-Range: bytes 7-15/18", "expected content-range header") 253tr.StillRunningAfter = ts 254 255# 2 Test - Fetch from cache 256tr = Test.AddTestRun("inner range cache hit") 257ps = tr.Processes.Default 258ps.Command = curl_and_args + ' http://www.example.com/path -r {}'.format(inner_str) 259ps.ReturnCode = 0 260ps.Streams.stderr = "gold/inner.stderr.gold" 261ps.Streams.stdout.Content = Testers.ContainsExpression("X-Cache: hit", "expected cache hit") 262ps.Streams.stdout.Content += Testers.ContainsExpression("Content-Range: bytes 7-15/18", "expected content-range header") 263tr.StillRunningAfter = ts 264 265# full range 266 267# 3 Test - 0- request 268tr = Test.AddTestRun("0- request miss") 269ps = tr.Processes.Default 270ps.Command = curl_and_args + ' http://www.example.com/path -r {} -H "uuid: frange"'.format(frange_str) 271ps.ReturnCode = 0 272ps.Streams.stderr = "gold/full.stderr.gold" 273ps.Streams.stdout.Content = Testers.ContainsExpression("X-Cache: miss", "expected cache miss") 274ps.Streams.stdout.Content += Testers.ContainsExpression("Content-Range: bytes 0-18/18", "expected content-range header") 275tr.StillRunningAfter = ts 276 277# 4 Test - 0- request 278tr = Test.AddTestRun("0- request hit") 279ps = tr.Processes.Default 280ps.Command = curl_and_args + ' http://www.example.com/path -r {}'.format(frange_str) 281ps.ReturnCode = 0 282ps.Streams.stderr = "gold/full.stderr.gold" 283ps.Streams.stdout.Content = Testers.ContainsExpression("X-Cache: hit", "expected cache hit") 284ps.Streams.stdout.Content += Testers.ContainsExpression("Content-Range: bytes 0-18/18", "expected content-range header") 285tr.StillRunningAfter = ts 286 287# end range 288 289# 5 Test - -5 request miss 290tr = Test.AddTestRun("-5 request miss") 291ps = tr.Processes.Default 292ps.Command = curl_and_args + ' http://www.example.com/path -r {} -H "uuid: last"'.format(last_str) 293ps.ReturnCode = 0 294ps.Streams.stderr = "gold/last.stderr.gold" 295ps.Streams.stdout.Content = Testers.ContainsExpression("X-Cache: miss", "expected cache miss") 296ps.Streams.stdout.Content += Testers.ContainsExpression("Content-Range: bytes 13-18/18", "expected content-range header") 297tr.StillRunningAfter = ts 298 299# 6 Test - -5 request hit 300tr = Test.AddTestRun("-5 request hit") 301ps = tr.Processes.Default 302ps.Command = curl_and_args + ' http://www.example.com/path -r {}'.format(last_str) 303ps.ReturnCode = 0 304ps.Streams.stderr = "gold/last.stderr.gold" 305ps.Streams.stdout.Content = Testers.ContainsExpression("X-Cache: hit", "expected cache hit") 306ps.Streams.stdout.Content += Testers.ContainsExpression("Content-Range: bytes 13-18/18", "expected content-range header") 307tr.StillRunningAfter = ts 308 309# Ensure 404's aren't getting cached 310 311# 7 Test - 404 312tr = Test.AddTestRun("404 request 1st") 313ps = tr.Processes.Default 314ps.Command = curl_and_args + ' http://www.example.com/404 -r 0-' 315ps.Streams.stdout = "gold/404.stdout.gold" 316ps.Streams.stdout.Content = Testers.ContainsExpression("X-Cache: miss", "expected cache miss") 317tr.StillRunningAfter = ts 318 319# 8 Test - 404 320tr = Test.AddTestRun("404 request 2nd") 321ps = tr.Processes.Default 322ps.Command = curl_and_args + ' http://www.example.com/404 -r 0-' 323ps.Streams.stdout.Content = Testers.ContainsExpression("X-Cache: miss", "expected cache miss") 324ps.Streams.stdout.Content += Testers.ContainsExpression("404 Not Found", "expected 404 response") 325 326tr.StillRunningAfter = ts 327 328curl_and_args = 'curl -s -D /dev/stdout -o /dev/stderr -x localhost:{} -H "x-debug: x-parentselection-key"'.format( 329 ts.Variables.port) 330 331# 9 Test - cache_key_url request 332tr = Test.AddTestRun("cache_key_url request") 333ps = tr.Processes.Default 334ps.Command = curl_and_args + ' http://parentselect/path -r {} -H "uuid: pselect"'.format(pselect_str) 335ps.ReturnCode = 0 336ps.Streams.stdout.Content = Testers.ContainsExpression( 337 "X-ParentSelection-Key: .*-bytes=", 338 "expected bytes in parent selection key", 339) 340tr.StillRunningAfter = ts 341tr.StillRunningAfter = server 342 343# 10 Test - non cache_key_url request ... no X-ParentSelection-Key 344tr = Test.AddTestRun("non cache_key_url request") 345ps = tr.Processes.Default 346ps.Command = curl_and_args + ' http://www.example.com/path -r {} -H "uuid: inner"'.format(inner_str) 347ps.ReturnCode = 0 348ps.Streams.stdout.Content = Testers.ExcludesExpression("X-ParentSelection-Key", "parent select key shouldn't show up") 349tr.StillRunningAfter = ts 350tr.StillRunningAfter = server 351 352# 11 Test - cache_key_url request -- deprecated 353tr = Test.AddTestRun("cache_key_url request - dprecated") 354ps = tr.Processes.Default 355ps.Command = curl_and_args + ' http://psd/path -r {} -H "uuid: pselect"'.format(pselect_str) 356ps.ReturnCode = 0 357ps.Streams.stdout.Content = Testers.ContainsExpression( 358 "X-ParentSelection-Key: .*-bytes=", 359 "expected bytes in parent selection key", 360) 361tr.StillRunningAfter = ts 362tr.StillRunningAfter = server 363