(SCGI) with the ``--scgi`` option.
"""
+import collections as _collections
import logging as _logging
import logging.handlers as _logging_handlers
import math as _math
self._base_url = base_url
self._cache_path = cache_path
self._serve_originals = serve_originals
+ self._text_charset = 'UTF-8'
self._url_regexp = _re.compile('^[a-zA-Z0-9._/-]*$')
self._rows = 3
self._columns = 3
self.header = []
self.footer = []
- def _http_header(self, mime='text/html', status=200):
+ def _get_charset(self, headers):
+ content_type = headers.get('Content-type', '')
+ if 'charset=' in content_type:
+ return content_type.split('charset=', 1)[-1]
+
+ def _http_headers(self, mime='text/html', status=200):
msg = RESPONSES[status]
- header = ['Status: {:d} {}'.format(status, msg)]
+ headers = _collections.OrderedDict()
+ headers['Status'] = '{:d} {}'.format(status, msg)
if mime.startswith('text/'):
- charset = '; charset=UTF-8'
+ charset = '; charset={}'.format(self._text_charset)
else:
charset = ''
- header.append('Content-type: {}{}'.format(mime, charset))
- return '\n'.join(header)
+ headers['Content-type'] = '{}{}'.format(mime, charset)
+ return headers
+
+ def _add_header(self, headers=None, stream=None):
+ if headers and self._write_http_headers:
+ for key, value in headers.items():
+ stream.write(
+ '{}: {}\r\n'.format(key, value).encode('US-ASCII'))
+ stream.write('\r\n'.encode('US-ASCII'))
- def _response(self, header=None, content='<h1>It works!</h1>',
+ def _response(self, headers=None, content='<h1>It works!</h1>',
stream=None):
- if header is None:
- header = self._http_header()
- stream.write(header)
- stream.write('\n\n')
+ if headers is None:
+ headers = self._http_headers()
+ self._add_header(headers=headers, stream=stream)
+ charset = self._get_charset(headers=headers)
+ if charset:
+ content = content.encode(charset)
stream.write(content)
raise ProcessingComplete()
- def _response_stream(self, header=None, content=None, stream=None,
+ def _response_stream(self, headers=None, content=None, stream=None,
chunk_size=1024):
LOG.debug('streaming response')
- if header is None:
- header = self._http_header()
- stream.write(header)
- stream.write('\n\n')
+ if headers is None:
+ headers = self._http_headers()
+ charset = self._get_charset(headers=headers)
+ if charset:
+ raise HTTPError(
+ 500,
+ content='charset {} set for streamed response'.format(charset))
+ self._add_header(headers=headers, stream=stream)
stream.flush() # flush headers
while True:
chunk = content.read(chunk_size)
raise ProcessingComplete()
def _error(self, status=404, content=None, stream=None):
- header = self._http_header(status=status)
+ headers = self._http_headers(status=status)
if content is None:
content = RESPONSES[status]
- self._response(header=header, content=content, stream=stream)
+ self._response(headers=headers, content=content, stream=stream)
def validate_url(self, url, exists=True, directory=False):
LOG.debug('validating {} (exists={}, directory={})'.format(
headers = self._http_headers(mime=mime)
if mime in STREAMING_TYPES:
self._response_stream(
- header=header, content=content, stream=stream)
+ headers=headers, content=content, stream=stream)
content = content.read()
- self._response(header=header, content=content, stream=stream)
+ self._response(headers=headers, content=content, stream=stream)
def page(self, url, page=0, stream=None):
LOG.debug('HTML page {} {}'.format(url, page))