[form] small api cleanup and refactoring before documenting the form system
"""WSGI request handler for cubicweb:organization: Logilab:copyright: 2008-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"fromcubicwebimportAuthenticationErrorfromcubicweb.webimport(NotFound,Redirect,DirectResponse,StatusResponse,ExplicitLogin)fromcubicweb.web.applicationimportCubicWebPublisherfromcubicweb.wsgi.requestimportCubicWebWsgiRequest# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.htmlSTATUS_CODE_TEXT={100:'CONTINUE',101:'SWITCHING PROTOCOLS',200:'OK',201:'CREATED',202:'ACCEPTED',203:'NON-AUTHORITATIVE INFORMATION',204:'NO CONTENT',205:'RESET CONTENT',206:'PARTIAL CONTENT',300:'MULTIPLE CHOICES',301:'MOVED PERMANENTLY',302:'FOUND',303:'SEE OTHER',304:'NOT MODIFIED',305:'USE PROXY',306:'RESERVED',307:'TEMPORARY REDIRECT',400:'BAD REQUEST',401:'UNAUTHORIZED',402:'PAYMENT REQUIRED',403:'FORBIDDEN',404:'NOT FOUND',405:'METHOD NOT ALLOWED',406:'NOT ACCEPTABLE',407:'PROXY AUTHENTICATION REQUIRED',408:'REQUEST TIMEOUT',409:'CONFLICT',410:'GONE',411:'LENGTH REQUIRED',412:'PRECONDITION FAILED',413:'REQUEST ENTITY TOO LARGE',414:'REQUEST-URI TOO LONG',415:'UNSUPPORTED MEDIA TYPE',416:'REQUESTED RANGE NOT SATISFIABLE',417:'EXPECTATION FAILED',500:'INTERNAL SERVER ERROR',501:'NOT IMPLEMENTED',502:'BAD GATEWAY',503:'SERVICE UNAVAILABLE',504:'GATEWAY TIMEOUT',505:'HTTP VERSION NOT SUPPORTED',}classWSGIResponse(object):"""encapsulates the wsgi response parameters (code, headers and body if there is one) """def__init__(self,code,req,body=None):text=STATUS_CODE_TEXT.get(code,'UNKNOWN STATUS CODE')self.status='%s%s'%(code,text)self.headers=[(str(k),str(v))fork,vinreq.headers_out.items()]ifbody:self.body=[body]else:self.body=[]def__iter__(self):returniter(self.body)classCubicWebWSGIApplication(object):"""This is the wsgi application which will be called by the wsgi server with the WSGI ``environ`` and ``start_response`` parameters. XXX: missing looping tasks and proper repository shutdown when the application is stopped. NOTE: no pyro """def__init__(self,config,debug=None,vreg=None):self.appli=CubicWebPublisher(config,debug=debug,vreg=vreg)self.debugmode=debugself.config=configself.base_url=None# self.base_url = config['base-url'] or config.default_base_url()# assert self.base_url[-1] == '/'# self.https_url = config['https-url']# assert not self.https_url or self.https_url[-1] == '/'self.url_rewriter=self.appli.vreg['components'].select_or_none('urlrewriter')def_render(self,req):"""this function performs the actual rendering XXX missing: https handling, url rewriting, cache management, authentication """ifself.base_urlisNone:self.base_url=self.config._base_url=req.base_url()# XXX https handling needs to be implementedifreq.authmode=='http':# activate realm-based authrealm=self.config['realm']req.set_header('WWW-Authenticate',[('Basic',{'realm':realm})],raw=False)try:self.appli.connect(req)exceptAuthenticationError:returnself.request_auth(req)exceptRedirect,ex:returnself.redirect(req,ex.location)path=req.pathifnotpathorpath=="/":path='view'try:result=self.appli.publish(path,req)exceptDirectResponse,ex:returnWSGIResponse(200,req,ex.response)exceptStatusResponse,ex:returnWSGIResponse(ex.status,req,ex.content)exceptNotFound:result=self.appli.notfound_content(req)returnWSGIResponse(404,req,result)exceptExplicitLogin:# must be before AuthenticationErrorreturnself.request_auth(req)exceptAuthenticationError:ifself.config['auth-mode']=='cookie':# in cookie mode redirecting to the index view is enough :# either anonymous connection is allowed and the page will# be displayed or we'll be redirected to the login formmsg=req._('you have been logged out')# if req.https:# req._base_url = self.base_url# req.https = Falseurl=req.build_url('view',vid='index',__message=msg)returnself.redirect(req,url)else:# in http we have to request auth to flush current http auth# informationreturnself.request_auth(req,loggedout=True)exceptRedirect,ex:returnself.redirect(req,ex.location)ifnotresult:# no result, something went wrong...self.error('no data (%s)',req)# 500 Internal server errorreturnself.redirect(req,req.build_url('error'))returnWSGIResponse(200,req,result)def__call__(self,environ,start_response):"""WSGI protocol entry point"""req=CubicWebWsgiRequest(environ,self.appli.vreg,self.base_url)response=self._render(req)start_response(response.status,response.headers)returnresponse.bodydefredirect(self,req,location):"""convenience function which builds a redirect WSGIResponse"""self.debug('redirecting to %s',location)req.set_header('location',str(location))returnWSGIResponse(303,req)defrequest_auth(self,req,loggedout=False):"""returns the appropriate WSGIResponse to require the user to log in """# if self.https_url and req.base_url() != self.https_url:# return self.redirect(self.https_url + 'login')ifself.config['auth-mode']=='http':code=401# UNAUTHORIZEDelse:code=403# FORBIDDENifloggedout:# if req.https:# req._base_url = self.base_url# req.https = Falsecontent=self.appli.loggedout_content(req)else:content=self.appli.need_login_content(req)returnWSGIResponse(code,req,content)fromloggingimportgetLoggerfromcubicwebimportset_log_methodsset_log_methods(CubicWebWSGIApplication,getLogger('cubicweb.wsgi'))