<%doc> # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # # # This file is the template for an Apache configuration that serves pkg(5) # repositories. On its own, it can be used to render a fragment that can be # dropped into an Apache conf.d directory, or it can be referenced from # a more complete httpd.conf template via an include directive. # <% import urllib %> RewriteEngine on RewriteLog "${log_dir}/rewrite.log" RewriteLogLevel 0 # We need to allow these as they're encoded in the package/manifest names # when looking up v4 repositories AllowEncodedSlashes On # The default of 500 MaxKeepAliveRequests is too low to be useful. MaxKeepAliveRequests 10000 <%doc> # All of our rules specify the NE flag, 'noescape', that is # we don't want any rewritten URLs being decoded en-route through # the set of RewriteRule directives. # # For all RewriteRule directives below, we allow sroot to specify # a server-root beneath which we should operate. <% repo_prefixes = set() root = context.get("sroot") runtime_dir = context.get("runtime_dir") for pub, repo_path, repo_prefix, writable_root in pubs: repo_prefixes.add(repo_prefix) context.write("# per-repository versions, publishers and status responses\n") for repo_prefix in repo_prefixes: context.write( "RewriteRule ^/%(root)s%(repo_prefix)sversions/0 " "/%(root)sversions/0/index.html [PT,NE]\n" % locals()) context.write("RewriteRule ^/%(root)s%(repo_prefix)spublisher/0 " "/%(root)s%(repo_prefix)spublisher/1/index.html [PT,NE]\n" % locals()) context.write( "RewriteRule ^/%(root)s%(repo_prefix)sstatus/0 " "/%(root)s%(repo_prefix)sstatus/0/index.html [PT,NE]\n" % locals()) %> <%doc> # # Rules to redirect default publisher requests into the publisher-specific # rules below. Publisher and versions responses were handled above. # # Rules to deal with responses for default publishers # <% for pub, repo_path, repo_prefix in default_pubs: if pub == None: continue root = context.get("sroot") # manifest rules need to use %{THE_REQUEST} undecoded # URI from mod_rewrite. However, since %{THE_REQUEST} is the # original request, we can't simply rewrite the URI # here to add the publisher, then let the other manifest rules # pick up the trail, so we need to do more work here, # basically duplicating how we deal with manifest responses # that have got a publisher included in the URI. context.write( "RewriteRule ^/%(root)s%(repo_prefix)smanifest/0/.*$ " "%%{THE_REQUEST} [NE,C]\n" % locals()) context.write("RewriteRule ^GET\ " "/%(root)s%(repo_prefix)smanifest/0/([^@]+)@([^\ ]+)(\ HTTP/1.1)$ " "/%(root)s%(repo_prefix)s%(pub)s/publisher/%(pub)s/pkg/$1/$2 [NE,PT,C]\n" % locals()) context.write( "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/(.*)$ " "%%{DOCUMENT_ROOT}/%(root)s%(repo_prefix)s%(pub)s/$1 [NE,L]\n" % locals()) # file responses require more work, so rewrite to # a URI that will get further rewrites later. context.write("RewriteRule " "^/%(root)s%(repo_prefix)sfile/(.*$) " "/%(root)s%(repo_prefix)s%(pub)s/file/$1 [NE]\n" % locals()) # for catalog parts, we can easily access the file with one # RewriteRule, so do that, then PT to the Alias directive. context.write("RewriteRule " "^/%(root)s%(repo_prefix)scatalog/1/(.*$) " "/%(root)s%(repo_prefix)s%(pub)s/publisher/%(pub)s/catalog/$1 [NE,PT]\n" % locals()) %> # Write per-publisher rules for publisher, version, file and manifest responses % for pub, repo_path, repo_prefix, writable_root in pubs: <%doc> # Point to our local versions/0 response or # publisher-specific publisher/1, response, then stop. # Serve our static versions and publisher responses <% root = context.get("sroot") context.write( "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/versions/0 " "%%{DOCUMENT_ROOT}/%(root)sversions/0/index.html [L,NE]\n" % locals()) context.write( "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/publisher/0 " "%%{DOCUMENT_ROOT}/%(root)s%(repo_prefix)s%(pub)s/publisher/1/index.html [L,NE]\n" % locals()) %><%doc> # Modify the catalog, file and manifest URLs, then 'passthrough' (PT), # letting the Alias directives below serve the file. <% root = context.get("sroot") context.write( "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/catalog/1/(.*)$ " "/%(root)s%(repo_prefix)s%(pub)s/publisher/%(pub)s/catalog/$1 [NE,PT]" % locals()) %><%doc> # file responses are a little tricky - we need to index # the first two characters of the filename and use that # as an index into the directory of filenames. # (omitting sroot and repo_prefix here, for brevity) # eg. the request # http://localhost:10000/pkg5-nightly/file/1/87ad645695abb22b2959f73d22022c5cffeccb13 # gets rewritten as: # http://localhost:10000/pkg5-nightly/publisher/pkg5-nightly/file/87/87ad645695abb22b2959f73d22022c5cffeccb13 <% root = context.get("sroot") context.write( "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/file/1/(..)(.*)$ " "/%(root)s%(repo_prefix)s%(pub)s/publisher/%(pub)s/file/$1/$1$2 [NE,PT]\n" % locals()) %><%doc> # We need to use %THE_REQUEST here to get the undecoded # URI from mod_rewrite. Hang on to your lunch. # We chain the rule that produces THE_REQUEST to the # following rule which picks apart the original http # request to separate the package name from the package # version. # # That is, mod_rewrite sees the pkg client asking for # the initial decoded URI: # '/pkg5-nightly/manifest/0/package/sysrepo@0.5.11,5.11-0.159:20110308T011843Z' # # which comes from the HTTP request: # 'GET /pkg5-nightly/manifest/0/package%2Fsysrepo@0.5.11%2C5.11-0.159%3A20110308T011843Z HTTP/1.1' # # which we eventually rewrite as: # -> '/pkg5-nightly/publisher/pkg5-nightly/pkg/package%2Fsysrepo/0.5.11%2C5.11-0.159%3A20110308T011843Z' <% root = context.get("sroot") context.write( "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/manifest/0/.*$ " "%%{THE_REQUEST} [NE,C]\n" % locals()) context.write("RewriteRule ^GET\ " "/%(root)s%(repo_prefix)s%(pub)s/manifest/0/([^@]+)@([^\ ]+)(\ HTTP/1.1)$ " "/%(root)s%(repo_prefix)s%(pub)s/publisher/%(pub)s/pkg/$1/$2 [NE,PT,C]\n" % locals()) context.write( "RewriteRule ^/%(root)s%(repo_prefix)s%(pub)s/(.*)$ " "%%{DOCUMENT_ROOT}/%(root)s%(repo_prefix)s%(pub)s/$1 [NE,L]\n" % locals()) %> % endfor pub <% paths = set() root = context.get("sroot") for pub, repo_path, repo_prefix, writable_root in pubs: paths.add((repo_path, repo_prefix)) context.write( "Alias /%(root)s%(repo_prefix)s%(pub)s %(repo_path)s\n" % locals()) for repo_path, repo_prefix in paths: context.write("# an alias to serve %(repo_path)s content.\n" "\n" " AllowOverride None\n" " Order allow,deny\n" " Allow from all\n" "\n" % locals()) %> # Our versions response. RewriteRule ^/${sroot}.*[/]?versions/0/?$ %{DOCUMENT_ROOT}/versions/0/index.html [L] # allow for 'OPTIONS * HTTP/1.0' requests RewriteCond %{REQUEST_METHOD} OPTIONS [NC] RewriteRule \* - [L] <% for repo_prefix in repo_prefixes: if root: context.write( "# Since we're running as a fragment within an existing\n" "# web server, we take a portion of the namespace for ourselves\n") context.write( "Alias /%(root)s %(runtime_dir)s/htdocs/%(root)s\n" % locals()) context.write( "\n" " AllowOverride None\n" " Order allow,deny\n" " Allow from all\n" "\n" % locals()) %> # These location matches are based on the final Rewrite paths for file, # manifest, catalog and publisher responses. Header set Cache-Control "must-revalidate, no-transform, max-age=31536000" Header set Content-Type application/data Header set Cache-Control "must-revalidate, no-transform, max-age=31536000" Header set Content-Type text/plain;charset=utf-8 Header set Cache-Control "must-revalidate, no-transform, max-age=86400" Header set Content-Type text/plain;charset=utf-8 Header set Cache-Control no-cache Header set Cache-Control "must-revalidate, no-transform, max-age=31536000" Header set Content-Type application/vnd.pkg5.info