Code

Handle OPTIONS http request method in wsgi handler, fixes issue2550587.
[roundup.git] / roundup / cgi / wsgi_handler.py
1 # WSGI interface for Roundup Issue Tracker
2 #
3 # This module is free software, you may redistribute it
4 # and/or modify under the same terms as Python.
5 #
7 import os
8 import cgi
9 import weakref
11 import roundup.instance
12 from roundup.cgi import TranslationService
13 from BaseHTTPServer import BaseHTTPRequestHandler, DEFAULT_ERROR_MESSAGE
16 class Writer(object):
17     '''Perform a start_response if need be when we start writing.'''
18     def __init__(self, request):
19         self.request = request #weakref.ref(request)
20     def write(self, data):
21         f = self.request.get_wfile()
22         self.write = f
23         return f(data)
25 class RequestDispatcher(object):
26     def __init__(self, home, debug=False, timing=False, lang=None):
27         assert os.path.isdir(home), '%r is not a directory'%(home,)
28         self.home = home
29         self.debug = debug
30         self.timing = timing
31         if lang:
32             self.translator = TranslationService.get_translation(lang,
33                 tracker_home=home)
34         else:
35             self.translator = None
37     def __call__(self, environ, start_response):
38         """Initialize with `apache.Request` object"""
39         self.environ = environ
40         request = RequestDispatcher(self.home, self.debug, self.timing)
41         request.__start_response = start_response
43         request.wfile = Writer(request)
44         request.__wfile = None
46         if environ ['REQUEST_METHOD'] == 'OPTIONS':
47             code = 501
48             message, explain = BaseHTTPRequestHandler.responses[code]
49             request.start_response([('Content-Type', 'text/html'),
50                 ('Connection', 'close')], code)
51             request.wfile.write(DEFAULT_ERROR_MESSAGE % locals())
52             return []
54         tracker = roundup.instance.open(self.home, not self.debug)
56         # need to strip the leading '/'
57         environ["PATH_INFO"] = environ["PATH_INFO"][1:]
58         if request.timing:
59             environ["CGI_SHOW_TIMING"] = request.timing
61         form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
63         client = tracker.Client(tracker, request, environ, form,
64             request.translator)
65         try:
66             client.main()
67         except roundup.cgi.client.NotFound:
68             request.start_response([('Content-Type', 'text/html')], 404)
69             request.wfile.write('Not found: %s'%client.path)
71         # all body data has been written using wfile
72         return []
74     def start_response(self, headers, response_code):
75         """Set HTTP response code"""
76         description = BaseHTTPRequestHandler.responses[response_code]
77         self.__wfile = self.__start_response('%d %s'%(response_code,
78             description), headers)
80     def get_wfile(self):
81         if self.__wfile is None:
82             raise ValueError, 'start_response() not called'
83         return self.__wfile