def testHeadersAreOptional(self): response = Response(200) response.headers = {} # the default self.task.deliver(response) expected = [ 'HTTP/1.0 200 OK', 'content-length: 0', 'content-type: application/octet-stream', 'server: stub server', '' ] actual = self.task.channel.getvalue().splitlines() self.assertEqual(expected, actual)
def respond(self, request): if request.method != 'POST': raise Response(501) else: response = Response(200) try: response.body = self.serve_xmlrpc(request) except: # Bug in the module. logger.error("Error serving request.") logger.debug(traceback.format_exc()) raise Response(500) else: # Valid XMLRPC response. response.headers = {'Content-Type': 'text/xml'} raise response
def translate(self, path): """Given a URI path, return a corresponding filesystem path. The URI path is taken to be rooted in our application root. If it points to a directory, look for a default resource. If it points to a file, make sure the file exists. This method can raise the following Responses: 301 Moved Permanently 400 Bad Request 403 Forbidden 400 Not Found """ full_path = os.path.join(self.config['root'], path.lstrip('/')) if os.path.isdir(full_path): if not path.endswith('/'): # redirect directory requests to trailing slash new_location = '%s/' % path response = Response(301) response.headers = {'Location': new_location} log(98, "Redirecting to trailing slash: %s" % path) raise response default = '' for name in self.config['defaults']: _path = os.path.join(full_path, name) if os.path.isfile(_path): default = _path break full_path = default if not default: log(94, "No default resource in %s" % path) raise Response(403) else: if not os.path.exists(full_path): log(94, "Not Found: %s" % path) raise Response(404) return full_path
def serve_index(self, request): """Serve a top-level package/module index. """ data = {} data['title'] = "doc537 — a Python documentation server" data['crumbs'] = data['title'] data['nav'] = '' data['callable'] = "<h1>index</h1>" data['content'] = self.getindex() data['version'] = __version__ data['date'] = time.strftime('%B %d, %Y') data['base'] = self.uri_root response = Response(200) response.headers = {'Content-Type': 'text/html'} response.body = TEMPLATE % data raise response
def serve_doc(self, request): """Serve documentation for an object. """ # Translate the URL path to an object path. # ========================================= objpath = request.path want_routine = False if objpath.endswith('.html'): objpath = objpath[:-5] want_routine = True elif objpath.endswith('/'): objpath = objpath.rstrip('/') objnames = [n for n in objpath.split('/') if n] acceptable = string.ascii_letters + string.digits + '_' for name in objnames: # prevent snooping if name[0].isdigit(): raise Response(404) for c in name: if c not in acceptable: raise Response(404) objpath = '.'.join(objnames) # Generate a list of (objpath, object) tuples. # ============================================ objs = [] for i in range(len(objnames)): curpath = '.'.join(objnames[:i + 1]) obj = pydoc.locate(curpath, forceload=True) if obj is None: raise Response(404) objs.append((curpath, obj)) if want_routine and not inspect.isroutine(obj): raise Response(404) elif (not want_routine) and not request.path.endswith('/'): raise Response(302, '', {'Location': request.fullpath + '/'}) # Build a data structure. # ======================= # This will be passed as a string replacement dictionary to TEMPLATE. # By the time we get here, we have objpath, obj, objnames and objs. data = {} data['title'] = objpath data['crumbs'] = self.getcrumbs(objs, obj) data['nav'] = self.getnav(objpath, objs) data['callable'] = self.getcallable(obj, objnames[-1]) data['content'] = self.getcontent(objs, obj) data['version'] = '' if hasattr(obj, '__version__'): data['version'] = obj.__version__ data['date'] = time.strftime('%B %d, %Y') data['base'] = self.uri_root # Send it out. # ============ response = Response(200) response.headers = {'Content-Type': 'text/html'} response.body = TEMPLATE % data raise response