~ubuntu-branches/ubuntu/jaunty/python-django/jaunty

« back to all changes in this revision

Viewing changes to django/core/servers/basehttp.py

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant, Eddy Mulyono
  • Date: 2008-09-16 12:18:47 UTC
  • mfrom: (1.1.5 upstream) (4.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080916121847-mg225rg5mnsdqzr0
Tags: 1.0-1ubuntu1
* Merge from Debian (LP: #264191), remaining changes:
  - Run test suite on build.

[Eddy Mulyono]
* Update patch to workaround network test case failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
"""
9
9
 
10
10
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
11
 
from types import ListType, StringType
12
 
import os, re, sys, time, urllib
 
11
import mimetypes
 
12
import os
 
13
import re
 
14
import sys
 
15
import urllib
 
16
 
 
17
from django.utils.http import http_date
13
18
 
14
19
__version__ = "0.1"
15
 
__all__ = ['WSGIServer','WSGIRequestHandler','demo_app']
 
20
__all__ = ['WSGIServer','WSGIRequestHandler']
16
21
 
17
22
server_version = "WSGIServer/" + __version__
18
23
sys_version = "Python/" + sys.version.split()[0]
66
71
class Headers(object):
67
72
    """Manage a collection of HTTP response headers"""
68
73
    def __init__(self,headers):
69
 
        if type(headers) is not ListType:
 
74
        if not isinstance(headers, list):
70
75
            raise TypeError("Headers must be a list of name/value tuples")
71
76
        self._headers = headers
72
77
 
208
213
    else:
209
214
        return 'http'
210
215
 
211
 
_hoppish = {
 
216
_hop_headers = {
212
217
    'connection':1, 'keep-alive':1, 'proxy-authenticate':1,
213
218
    'proxy-authorization':1, 'te':1, 'trailers':1, 'transfer-encoding':1,
214
219
    'upgrade':1
215
 
}.has_key
 
220
}
216
221
 
217
222
def is_hop_by_hop(header_name):
218
223
    """Return true if 'header_name' is an HTTP/1.1 "Hop-by-Hop" header"""
219
 
    return _hoppish(header_name.lower())
 
224
    return header_name.lower() in _hop_headers
220
225
 
221
226
class ServerHandler(object):
222
227
    """Manage the invocation of a WSGI application"""
321
326
        """Compute Content-Length or switch to chunked encoding if possible"""
322
327
        try:
323
328
            blocks = len(self.result)
324
 
        except (TypeError,AttributeError,NotImplementedError):
 
329
        except (TypeError, AttributeError, NotImplementedError):
325
330
            pass
326
331
        else:
327
332
            if blocks==1:
334
339
 
335
340
        Subclasses can extend this to add other defaults.
336
341
        """
337
 
        if not self.headers.has_key('Content-Length'):
 
342
        if 'Content-Length' not in self.headers:
338
343
            self.set_content_length()
339
344
 
340
345
    def start_response(self, status, headers,exc_info=None):
350
355
        elif self.headers is not None:
351
356
            raise AssertionError("Headers already set!")
352
357
 
353
 
        assert type(status) is StringType,"Status must be a string"
 
358
        assert isinstance(status, str),"Status must be a string"
354
359
        assert len(status)>=4,"Status must be at least 4 characters"
355
360
        assert int(status[:3]),"Status message must begin w/3-digit code"
356
361
        assert status[3]==" ", "Status message must have a space after code"
357
362
        if __debug__:
358
363
            for name,val in headers:
359
 
                assert type(name) is StringType,"Header names must be strings"
360
 
                assert type(val) is StringType,"Header values must be strings"
 
364
                assert isinstance(name, str),"Header names must be strings"
 
365
                assert isinstance(val, str),"Header values must be strings"
361
366
                assert not is_hop_by_hop(name),"Hop-by-hop headers not allowed"
362
367
        self.status = status
363
368
        self.headers = self.headers_class(headers)
368
373
        if self.origin_server:
369
374
            if self.client_is_modern():
370
375
                self._write('HTTP/%s %s\r\n' % (self.http_version,self.status))
371
 
                if not self.headers.has_key('Date'):
 
376
                if 'Date' not in self.headers:
372
377
                    self._write(
373
 
                        'Date: %s\r\n' % time.asctime(time.gmtime(time.time()))
 
378
                        'Date: %s\r\n' % http_date()
374
379
                    )
375
 
                if self.server_software and not self.headers.has_key('Server'):
 
380
                if self.server_software and 'Server' not in self.headers:
376
381
                    self._write('Server: %s\r\n' % self.server_software)
377
382
        else:
378
383
            self._write('Status: %s\r\n' % self.status)
380
385
    def write(self, data):
381
386
        """'write()' callable as specified by PEP 333"""
382
387
 
383
 
        assert type(data) is StringType,"write() argument must be string"
 
388
        assert isinstance(data, str), "write() argument must be string"
384
389
 
385
390
        if not self.status:
386
391
            raise AssertionError("write() before start_response()")
393
398
            self.bytes_sent += len(data)
394
399
 
395
400
        # XXX check Content-Length and truncate if too many bytes written?
396
 
        self._write(data)
397
 
        self._flush()
 
401
 
 
402
        # If data is too large, socket will choke, so write chunks no larger
 
403
        # than 32MB at a time.
 
404
        length = len(data)
 
405
        if length > 33554432:
 
406
            offset = 0
 
407
            while offset < length:
 
408
                chunk_size = min(33554432, length)
 
409
                self._write(data[offset:offset+chunk_size])
 
410
                self._flush()
 
411
                offset += chunk_size
 
412
        else:
 
413
            self._write(data)
 
414
            self._flush()
398
415
 
399
416
    def sendfile(self):
400
417
        """Platform-specific file transmission
534
551
    def __init__(self, *args, **kwargs):
535
552
        from django.conf import settings
536
553
        self.admin_media_prefix = settings.ADMIN_MEDIA_PREFIX
 
554
        # We set self.path to avoid crashes in log_message() on unsupported
 
555
        # requests (like "OPTIONS").
 
556
        self.path = ''
537
557
        BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
538
558
 
539
559
    def get_environ(self):
630
650
            else:
631
651
                status = '200 OK'
632
652
                headers = {}
 
653
                mime_type = mimetypes.guess_type(file_path)[0]
 
654
                if mime_type:
 
655
                    headers['Content-Type'] = mime_type
633
656
                output = [fp.read()]
634
657
                fp.close()
635
658
        start_response(status, headers.items())