160 https = False |
160 https = False |
161 if origpath.split('/', 2)[1] == 'https': |
161 if origpath.split('/', 2)[1] == 'https': |
162 origpath = origpath[6:] |
162 origpath = origpath[6:] |
163 request.uri = request.uri[6:] |
163 request.uri = request.uri[6:] |
164 https = True |
164 https = True |
165 req = CubicWebTwistedRequestAdapter(request, self.appli.vreg, https) |
|
166 if req.authmode == 'http': |
|
167 # activate realm-based auth |
|
168 realm = self.config['realm'] |
|
169 req.set_header('WWW-Authenticate', [('Basic', {'realm' : realm })], raw=False) |
|
170 try: |
|
171 self.appli.connect(req) |
|
172 except Redirect, ex: |
|
173 return self.redirect(request=req, location=ex.location) |
|
174 if https and req.session.anonymous_session and self.config['https-deny-anonymous']: |
|
175 # don't allow anonymous on https connection |
|
176 return self.request_auth(request=req) |
|
177 if self.url_rewriter is not None: |
165 if self.url_rewriter is not None: |
178 # XXX should occur before authentication? |
166 # XXX should occur before authentication? |
179 try: |
167 path = self.url_rewriter.rewrite(host, origpath, request) |
180 path = self.url_rewriter.rewrite(host, origpath, req) |
|
181 except Redirect, ex: |
|
182 return self.redirect(req, ex.location) |
|
183 request.uri.replace(origpath, path, 1) |
168 request.uri.replace(origpath, path, 1) |
184 else: |
169 else: |
185 path = origpath |
170 path = origpath |
|
171 req = CubicWebTwistedRequestAdapter(request, self.appli.vreg, https) |
186 try: |
172 try: |
187 result = self.appli.publish(path, req) |
173 ### Try to generate the actual request content |
|
174 content = self.appli.handle_request(req, path) |
188 except DirectResponse, ex: |
175 except DirectResponse, ex: |
189 return ex.response |
176 return ex.response |
190 except StatusResponse, ex: |
177 # at last: create twisted object |
191 return HTTPResponse(stream=ex.content, code=ex.status, |
178 return HTTPResponse(code = req.status_out, |
192 twisted_request=req._twreq, |
179 headers = req.headers_out, |
193 headers=req.headers_out) |
180 stream = content, |
194 except AuthenticationError: |
181 twisted_request=req._twreq) |
195 return self.request_auth(request=req) |
|
196 except LogOut, ex: |
|
197 if self.config['auth-mode'] == 'cookie' and ex.url: |
|
198 return self.redirect(request=req, location=ex.url) |
|
199 # in http we have to request auth to flush current http auth |
|
200 # information |
|
201 return self.request_auth(request=req, loggedout=True) |
|
202 except Redirect, ex: |
|
203 return self.redirect(request=req, location=ex.location) |
|
204 # request may be referenced by "onetime callback", so clear its entity |
|
205 # cache to avoid memory usage |
|
206 req.drop_entity_cache() |
|
207 return HTTPResponse(twisted_request=req._twreq, code=http.OK, |
|
208 stream=result, headers=req.headers_out) |
|
209 |
|
210 def redirect(self, request, location): |
|
211 self.debug('redirecting to %s', str(location)) |
|
212 request.headers_out.setHeader('location', str(location)) |
|
213 # 303 See other |
|
214 return HTTPResponse(twisted_request=request._twreq, code=303, |
|
215 headers=request.headers_out) |
|
216 |
|
217 def request_auth(self, request, loggedout=False): |
|
218 if self.https_url and request.base_url() != self.https_url: |
|
219 return self.redirect(request, self.https_url + 'login') |
|
220 if self.config['auth-mode'] == 'http': |
|
221 code = http.UNAUTHORIZED |
|
222 else: |
|
223 code = http.FORBIDDEN |
|
224 if loggedout: |
|
225 if request.https: |
|
226 request._base_url = self.base_url |
|
227 request.https = False |
|
228 content = self.appli.loggedout_content(request) |
|
229 else: |
|
230 content = self.appli.need_login_content(request) |
|
231 return HTTPResponse(twisted_request=request._twreq, |
|
232 stream=content, code=code, |
|
233 headers=request.headers_out) |
|
234 |
182 |
235 # these are overridden by set_log_methods below |
183 # these are overridden by set_log_methods below |
236 # only defining here to prevent pylint from complaining |
184 # only defining here to prevent pylint from complaining |
237 @classmethod |
185 @classmethod |
238 def debug(cls, msg, *a, **kw): |
186 def debug(cls, msg, *a, **kw): |