Mercurial > p > roundup > code
comparison roundup/cgi/client.py @ 1946:c538a64b94a7
Refactored CGI file serving so that FileClass contents are...
a) read more cleanly and b) served with reasonable modification dates
and handling of if-modified-since.
File serving also sends a content-length now too.
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Fri, 05 Dec 2003 03:28:38 +0000 |
| parents | 4c850112895b |
| children | d30cd44321f2 |
comparison
equal
deleted
inserted
replaced
| 1945:7e4058dfb29b | 1946:c538a64b94a7 |
|---|---|
| 1 # $Id: client.py,v 1.148 2003-11-21 22:22:32 jlgijsbers Exp $ | 1 # $Id: client.py,v 1.149 2003-12-05 03:28:38 richard Exp $ |
| 2 | 2 |
| 3 __doc__ = """ | 3 __doc__ = """ |
| 4 WWW request handler (also used in the stand-alone server). | 4 WWW request handler (also used in the stand-alone server). |
| 5 """ | 5 """ |
| 6 | 6 |
| 469 raise NotFound, str(designator) | 469 raise NotFound, str(designator) |
| 470 classname, nodeid = m.group(1), m.group(2) | 470 classname, nodeid = m.group(1), m.group(2) |
| 471 if classname != 'file': | 471 if classname != 'file': |
| 472 raise NotFound, designator | 472 raise NotFound, designator |
| 473 | 473 |
| 474 # we just want to serve up the file named | |
| 475 self.opendb('admin') | 474 self.opendb('admin') |
| 476 file = self.db.file | 475 file = self.db.file |
| 477 self.additional_headers['Content-Type'] = file.get(nodeid, 'type') | 476 |
| 478 self.write(file.get(nodeid, 'content')) | 477 mime_type = file.get(nodeid, 'type') |
| 478 content = file.get(nodeid, 'content') | |
| 479 lmt = file.get(nodeid, 'activity').timestamp() | |
| 480 | |
| 481 self._serve_file(lmt, mime_type, content) | |
| 479 | 482 |
| 480 def serve_static_file(self, file): | 483 def serve_static_file(self, file): |
| 484 ''' Serve up the file named from the templates dir | |
| 485 ''' | |
| 486 filename = os.path.join(self.instance.config.TEMPLATES, file) | |
| 487 | |
| 488 # last-modified time | |
| 489 lmt = os.stat(filename)[stat.ST_MTIME] | |
| 490 | |
| 491 # detemine meta-type | |
| 492 file = str(file) | |
| 493 mime_type = mimetypes.guess_type(file)[0] | |
| 494 if not mime_type: | |
| 495 if file.endswith('.css'): | |
| 496 mime_type = 'text/css' | |
| 497 else: | |
| 498 mime_type = 'text/plain' | |
| 499 | |
| 500 # snarf the content | |
| 501 f = open(filename, 'rb') | |
| 502 try: | |
| 503 content = f.read() | |
| 504 finally: | |
| 505 f.close() | |
| 506 | |
| 507 self._serve_file(lmt, mime_type, content) | |
| 508 | |
| 509 def _serve_file(self, last_modified, mime_type, content): | |
| 510 ''' guts of serve_file() and serve_static_file() | |
| 511 ''' | |
| 481 ims = None | 512 ims = None |
| 482 # see if there's an if-modified-since... | 513 # see if there's an if-modified-since... |
| 483 if hasattr(self.request, 'headers'): | 514 if hasattr(self.request, 'headers'): |
| 484 ims = self.request.headers.getheader('if-modified-since') | 515 ims = self.request.headers.getheader('if-modified-since') |
| 485 elif self.env.has_key('HTTP_IF_MODIFIED_SINCE'): | 516 elif self.env.has_key('HTTP_IF_MODIFIED_SINCE'): |
| 486 # cgi will put the header in the env var | 517 # cgi will put the header in the env var |
| 487 ims = self.env['HTTP_IF_MODIFIED_SINCE'] | 518 ims = self.env['HTTP_IF_MODIFIED_SINCE'] |
| 488 filename = os.path.join(self.instance.config.TEMPLATES, file) | |
| 489 lmt = os.stat(filename)[stat.ST_MTIME] | |
| 490 if ims: | 519 if ims: |
| 491 ims = rfc822.parsedate(ims)[:6] | 520 ims = rfc822.parsedate(ims)[:6] |
| 492 lmtt = time.gmtime(lmt)[:6] | 521 lmtt = time.gmtime(lmt)[:6] |
| 493 if lmtt <= ims: | 522 if lmtt <= ims: |
| 494 raise NotModified | 523 raise NotModified |
| 495 | 524 |
| 496 # we just want to serve up the file named | 525 # spit out headers |
| 497 file = str(file) | 526 self.additional_headers['Content-Type'] = mime_type |
| 498 mt = mimetypes.guess_type(file)[0] | 527 self.additional_headers['Content-Length'] = len(content) |
| 499 if not mt: | 528 lmt = rfc822.formatdate(last_modified) |
| 500 if file.endswith('.css'): | 529 self.additional_headers['Last-Modifed'] = lmt |
| 501 mt = 'text/css' | 530 self.write(content) |
| 502 else: | |
| 503 mt = 'text/plain' | |
| 504 self.additional_headers['Content-Type'] = mt | |
| 505 self.additional_headers['Last-Modifed'] = rfc822.formatdate(lmt) | |
| 506 self.write(open(filename, 'rb').read()) | |
| 507 | 531 |
| 508 def renderContext(self): | 532 def renderContext(self): |
| 509 ''' Return a PageTemplate for the named page | 533 ''' Return a PageTemplate for the named page |
| 510 ''' | 534 ''' |
| 511 name = self.classname | 535 name = self.classname |
