0001"""
0002Takes a response (headers + content) and relocates it, changing domain
0003names and paths.
0004"""
0005import urlparse
0006import re
0007from paste.request import construct_url
0008from paste.response import header_value
0009import fixuplinks
0010
0011def relocate_response(headers, content, base_href, old_href, new_href):
0012 """
0013 Takes headers and content, and replaces all instances of old_href
0014 with new_href. Returns (new_headers, new_content)
0015 """
0016 new_headers = relocate_headers(headers, base_href, old_href, new_href)
0017 new_content = relocate_content(content, base_href, old_href, new_href)
0018 return new_headers, new_content
0019
0020def relocate_headers(headers, base_href, old_href, new_href):
0021 new_headers = []
0022 for name, value in headers:
0023 if name.lower() == 'location':
0024 value = relocate_href(value, base_href, old_href, new_href)
0025 if name.lower() == 'set-cookie':
0026 if 'domain' in value:
0027
0028 old_domain = urlparse.urlsplit(old_href)[1].split(':')[0]
0029 new_domain = urlparse.urlsplit(new_href)[1].split(':')[0]
0030 def repl(match):
0031 return match.group(1)+new_domain
0032 value = re.sub(
0033 r'(domain=[^ ",]*)%s' % re.escape(old_domain),
0034 repl, value)
0035 new_headers.append((name, value))
0036 return new_headers
0037
0038def relocate_content(content, base_href, old_href, new_href):
0039 def sub_link(href):
0040 return relocate_href(href, base_href, old_href, new_href)
0041 return fixuplinks.fixup_text_links(content, sub_link)
0042
0043
0044
0045_domain_no_slash_re = re.compile(r'^[a-z]+://[^/]+$', re.I)
0046
0047def relocate_href(href, base_href, old_href, new_href):
0048 real_href = urlparse.urljoin(base_href, href)
0049 if _domain_no_slash_re.search(real_href):
0050 real_href += '/'
0051 if not real_href.startswith(old_href):
0052 return href
0053 return new_href + real_href[len(old_href):]
0054
0055class RelocateMiddleware(object):
0056
0057 def __init__(self, app, old_href):
0058 self.app = app
0059 if old_href.endswith(':80'):
0060 old_href = old_href[:-3]
0061 self.old_href = old_href
0062
0063 def __call__(self, environ, start_response):
0064 new_href = construct_url(environ, path_info='')
0065 base_href = construct_url(environ)
0066 skipped = []
0067 written = []
0068 stat_headers = []
0069 def repl_start_response(status, headers, exc_info=None):
0070 headers = relocate_headers(headers, base_href, self.old_href, new_href)
0071 content_type = header_value(headers, 'content-type')
0072 if not content_type or not content_type.startswith('text/html'):
0073 skipped.append(True)
0074 return start_response(status, headers, exc_info)
0075 stat_headers[:] = [status, headers]
0076 return written.append
0077 app_iter = self.app(environ, repl_start_response)
0078 if skipped:
0079 return app_iter
0080 start_response(*stat_headers)
0081 try:
0082 for chunk in app_iter:
0083 written.append(chunk)
0084 finally:
0085 if hasattr(app_iter, 'close'):
0086 app_iter.close()
0087 content = ''.join(written)
0088 content = relocate_content(content, base_href, self.old_href, new_href)
0089 return [content]