1
2
3
4
5
6 import sys
7 import StringIO
8 import traceback
9 from urllib import unquote
10
11 from restkit.util import url_encode
12
13 from .. import __version__
14 from ..external import External
15
17 return "-".join([w.lower().capitalize() for w in name.split("-")])
18
20
21 SERVER_VERSION = "couchdbkit/%s" % __version__
22
24 self.line = line
25 self.response_status = 200
26 self.response_headers = {}
27 self.start_response_called = False
28
30 headers = self.parse_headers()
31
32 length = headers.get("CONTENT_LENGTH")
33 if self.line["body"] and self.line["body"] != "undefined":
34 length = len(self.line["body"])
35 body = StringIO.StringIO(self.line["body"])
36
37 else:
38 body = StringIO.StringIO()
39
40
41 script_name, path_info = self.line['path'][:2], self.line['path'][2:]
42 if path_info:
43 path_info = "/%s" % "/".join(path_info)
44 else:
45 path_info = ""
46 script_name = "/%s" % "/".join(script_name)
47
48
49 args = []
50 query_string = None
51 for k, v in self.line["query"].items():
52 if v is None:
53 continue
54 else:
55 args.append((k,v))
56 if args: query_string = url_encode(dict(args))
57
58
59 path = "%s%s" % (path_info, query_string)
60
61
62 if ":" in self.line["headers"]["Host"]:
63 server_address = self.line["headers"]["Host"].split(":")
64 else:
65 server_address = (self.line["headers"]["Host"], 80)
66
67 environ = {
68 "wsgi.url_scheme": 'http',
69 "wsgi.input": body,
70 "wsgi.errors": StringIO.StringIO(),
71 "wsgi.version": (1, 0),
72 "wsgi.multithread": False,
73 "wsgi.multiprocess": True,
74 "wsgi.run_once": False,
75 "SCRIPT_NAME": script_name,
76 "SERVER_SOFTWARE": self.SERVER_VERSION,
77 "COUCHDB_INFO": self.line["info"],
78 "COUCHDB_REQUEST": self.line,
79 "REQUEST_METHOD": self.line["verb"].upper(),
80 "PATH_INFO": unquote(path_info),
81 "QUERY_STRING": query_string,
82 "RAW_URI": path,
83 "CONTENT_TYPE": headers.get('CONTENT-TYPE', ''),
84 "CONTENT_LENGTH": length,
85 "REMOTE_ADDR": self.line['peer'],
86 "REMOTE_PORT": 0,
87 "SERVER_NAME": server_address[0],
88 "SERVER_PORT": int(server_address[1]),
89 "SERVER_PROTOCOL": "HTTP/1.1"
90 }
91
92 for key, value in headers.items():
93 key = 'HTTP_' + key.replace('-', '_')
94 if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
95 environ[key] = value
96
97 return environ
98
100 self.response_status = int(status.split(" ")[0])
101 for name, value in response_headers:
102 name = _normalize_name(name)
103 self.response_headers[name] = value.strip()
104 self.start_response_called = True
105
107 headers = {}
108 for name, value in self.line.get("headers", {}).items():
109 name = name.strip().upper().encode("utf-8")
110 headers[name] = value.strip().encode("utf-8")
111 return headers
112
114
115 - def __init__(self, application, stdin=sys.stdin,
116 stdout=sys.stdout):
117 External.__init__(self, stdin=stdin, stdout=stdout)
118 self.app = application
119
121 try:
122 req = WSGIRequest(line)
123 response = self.app(req.read(), req.start_response)
124 except:
125 self.send_response(500, "".join(traceback.format_exc()),
126 {"Content-Type": "text/plain"})
127 return
128
129 content = "".join(response).encode("utf-8")
130 self.send_response(req.response_status, content, req.response_headers)
131