def test_best_match(): accept = Accept("text/html, foo/bar") assert accept.best_match(["text/html", "foo/bar"]) == "text/html" assert accept.best_match(["foo/bar", "text/html"]) == "foo/bar" assert accept.best_match([("foo/bar", 0.5), "text/html"]) == "text/html" assert accept.best_match([("foo/bar", 0.5), ("text/html", 0.4)]) == "foo/bar" assert_raises(ValueError, accept.best_match, ["text/*"])
def test_best_match(): accept = Accept('text/html, foo/bar') assert accept.best_match(['text/html', 'foo/bar']) == 'text/html' assert accept.best_match(['foo/bar', 'text/html']) == 'foo/bar' assert accept.best_match([('foo/bar', 0.5), 'text/html']) == 'text/html' assert accept.best_match([('foo/bar', 0.5), ('text/html', 0.4)]) == 'foo/bar' assert_raises(ValueError, accept.best_match, ['text/*'])
def test_best_match_with_complex_q(): accept = Accept('text/html, foo/bar;q=0.55, baz/gort;q=0.59') assert accept.best_match(['text/html', 'foo/bar']) == 'text/html' accept = Accept('text/html;q=0.5, foo/bar;q=0.586, baz/gort;q=0.5966') assert "baz/gort;q=0.597" in str(accept) assert "foo/bar;q=0.586" in str(accept) assert "text/html;q=0.5" in str(accept) assert accept.best_match(['text/html', 'baz/gort']) == 'baz/gort'
def test_best_match_with_complex_q(): accept = Accept("text/html, foo/bar;q=0.55, baz/gort;q=0.59") assert accept.best_match(["text/html", "foo/bar"]) == "text/html" accept = Accept("text/html;q=0.5, foo/bar;q=0.586, baz/gort;q=0.5966") assert "baz/gort;q=0.597" in str(accept) assert "foo/bar;q=0.586" in str(accept) assert "text/html;q=0.5" in str(accept) assert accept.best_match(["text/html", "baz/gort"]) == "baz/gort"
def test_best_match(): accept = Accept('Content-Type', 'text/html, foo/bar') assert accept.best_match(['text/html', 'foo/bar']) == 'text/html' assert accept.best_match(['foo/bar', 'text/html']) == 'foo/bar' assert accept.best_match([('foo/bar', 0.5), 'text/html']) == 'text/html' assert accept.best_match([('foo/bar', 0.5), ('text/html', 0.4)]) == 'foo/bar' assert_raises(ValueError, accept.best_match, ['text/*'])
def test_best_match(): accept = Accept('text/html, foo/bar') assert accept.best_match(['text/html', 'foo/bar']) == 'text/html' assert accept.best_match(['foo/bar', 'text/html']) == 'foo/bar' assert accept.best_match([('foo/bar', 0.5), 'text/html']) == 'text/html' assert accept.best_match([('foo/bar', 0.5), ('text/html', 0.4)]) == 'foo/bar' with pytest.raises(ValueError): accept.best_match(['text/*'])
def generate_response(self, environ, start_response): if self.content_length is not None: del self.content_length headerlist = list(self.headerlist) accept_value = environ.get('HTTP_ACCEPT', '') accept = Accept(accept_value) match = accept.best_match(['application/json', 'text/html', 'text/plain'], default_match='text/plain') if match == 'text/html': content_type = 'text/html' body = self.html_body(environ) elif match == 'application/json': content_type = 'application/json' body = self.json_body(environ) else: content_type = 'text/plain' body = self.plain_body(environ) extra_kw = {} if isinstance(body, text_type): extra_kw.update(charset='utf-8') resp = Response(body, status=self.status, headerlist=headerlist, content_type=content_type, **extra_kw ) resp.content_type = content_type return resp(environ, start_response)
def generate_response(self, environ, start_response): if self.content_length is not None: del self.content_length headerlist = list(self.headerlist) accept_value = environ.get('HTTP_ACCEPT', '') accept = Accept(accept_value) match = accept.best_match( ['application/json', 'text/html', 'text/plain'], default_match='text/plain') if match == 'text/html': content_type = 'text/html' body = self.html_body(environ) elif match == 'application/json': content_type = 'application/json' body = self.json_body(environ) else: content_type = 'text/plain' body = self.plain_body(environ) extra_kw = {} if isinstance(body, text_type): extra_kw.update(charset='utf-8') resp = Response(body, status=self.status, headerlist=headerlist, content_type=content_type, **extra_kw) resp.content_type = content_type return resp(environ, start_response)
def concept(request, lccn): concept = get_object_or_404(m.Concept, lccn=lccn) host = request.get_host() accept = Accept('Accept', request.META.get('HTTP_ACCEPT', 'text/html')) best_match = accept.best_match(['text/html', 'application/rdf+xml']) if best_match == 'application/rdf+xml': r = concept_rdf(request, lccn) else: alt_labels = concept.alternate_labels.all().order_by('text') broader = concept.broader.all().order_by('pref_label') extra_broader = concept.extra_broader() narrower = concept.narrower.all().order_by('pref_label') related = concept.related.all().order_by('pref_label') r = render_to_response('concept.html', dictionary=locals(), context_instance=RequestContext(request)) # let downstream caches know that the resonse can vary depending # on the Accept header that the client sent r['Vary'] = 'Accept' return r
def test_best_match_with_one_lower_q(): accept = Accept('text/html, foo/bar;q=0.5') assert accept.best_match(['text/html', 'foo/bar']) == 'text/html' accept = Accept('text/html;q=0.5, foo/bar') assert accept.best_match(['text/html', 'foo/bar']) == 'foo/bar'
def __call__(self, req): """Route a request to an appropriate method of the resource, returning a response. *req* is a :class:`webob.Request` instance (either provided by the caller or created by the :class:`webob.dec.wsgify` decorator). This method will first check the request's HTTP method, mapping it to a local method name using :attr:`methods`. If the request's PATH_INFO ends with an extension registered in :attr:`extensions`, the extension's media type is used; otherwise, this method will try to match the request's Accept header against methods registered in :attr:`media`. If no method can be found, this method raises an exception from :module:`errors`. This method sets :attr:`req`, :attr:`req.response` and :attr:`req.content` before calling the matched method. For example, a request made with the GET method and an Accept header (or PATH_INFO file extension) that matches the "html" handler will be dispatched to a method on the :class:`Resource` named "get_html". These methods take no arguments; the :class:`webob.Request` instance is available in the :attr:`request` attribute. """ log = logger(self) try: httpmethod = req.GET.pop(self.params["method"]) except KeyError: httpmethod = req.method try: httpmethod = self.methods[httpmethod] except KeyError: e = errors.HTTPMethodNotAllowed( "HTTP method '%s' is not supported" % req.method, headers={"Allow": ", ".join(list(self.methods.values()))}) raise e # The first element of PATH_INFO is the same as our prefix. req.path_info_pop() root, ext = os.path.splitext(req.path_info) media = self.extensions.get(ext, None) try: content = req.GET.pop(self.params["content-type"]) except KeyError: content = req.content_type content = Accept("Content-Type", content) if media is None: try: accept = Accept("Accept", req.GET.pop(self.params["accept"])) except KeyError: accept = req.accept if not accept: accept = content else: accept = Accept("Accept", media) req.path_info = root responsetype = accept.best_match(self.media) media = self.media.get(responsetype, None) methodname = "%s_%s" % (httpmethod, media) method = getattr(self, methodname, getattr(self, httpmethod, None)) if not callable(method): e = errors.HTTPUnsupportedMediaType( "Media type %s is not supported for method %s" % (media, req.method)) raise e log.debug("Request PATH: %s", req.path) log.debug("Request PATH_INFO: %s", req.path_info) log.debug("Request HTTP method: %s", httpmethod) log.debug("Request Accept header: %s", accept) log.debug("Request Content-Type header: %s", content) log.debug("Handling request with method %s", methodname) if not hasattr(req, "response"): req.response = Response() self.req = req self.response = req.response self.response.content_type = "" media = self.media.get(content.best_match(self.media), None) handlername = "handle_%s" % media handler = getattr(self, handlername, None) if not hasattr(req, "content"): if not callable(handler): handler = lambda: self.req.params req.content = handler() response = method() if response is None: response = self.response content = getattr(response, "content_type", getattr(self, "response.content_type", None)) if not content: self.response.content_type = responsetype return response
def checkMimetype(acceptHeader): accept = Accept('Accept', acceptHeader) best = accept.best_match(['application/rdf', 'application/rdf+xml', 'text/n3', 'application/xml', 'application/json', 'text/xml', 'application/xhtml+xml']) if best is None: best = "text/html" return best
def test_best_match_with_one_lower_q(): accept = Accept('Content-Type', 'text/html, foo/bar;q=0.5') assert accept.best_match(['text/html', 'foo/bar']) == 'text/html' accept = Accept('Content-Type', 'text/html;q=0.5, foo/bar') assert accept.best_match(['text/html', 'foo/bar']) == 'foo/bar'
class WebController(Controller): """ Web controller. """ __static_body = None __topics = {} # topics are loaded on demand __site = None _d_topics = {} # all topics are loaded once! __main_topic = None def __init__(self, config_file): self.__lang = None self.i18n = None self.direct_obj_ref = None self.cog_exec_env = None self.__env_set = False self.__nsession = False self._begin = None self.__cog_target = None self._cog_raw = None self._cog_ajax = None self._script_name = None self._server_name = None self._url_scheme = None self._environ = None self.__request = None self._session_key = None self.__session = None self._user = None self.__cog_environment = None self.__get_request = None self.cog_ref_obj = {} Controller.__init__(self, config_file) self.cache = Client(self) self.cache.check() def clear(self): self.direct_obj_ref = None self.cog_exec_env = None self.__env_set = False self.__nsession = False self.__cog_target = None self._cog_raw = None self._cog_ajax = None self._environ = None self._user = None self.__request = None self._session_key = None self.__session = None self.__get_request = None self._json_res = {} self.cog_ref_obj = {} Controller.clear(self) @property def env_set(self): return self.__env_set def __rt(self, template_name): """ reads the templates and returns it's content """ params = self.db._cog_params tp = params['templates_path'] return open("%s/%s.html"%(tp, template_name)).read() def __get_tags(self): return self.db.table('collorg.communication.tag').search_links() def __get_important_posts(self): return self.db.table( 'collorg.communication.blog.view.by_post').important() @property def new_session(self): self.__nsession = True self._session_key = uuid.uuid4() return self._session_key def __get_static_body(self): self.db.table('collorg.core.base_table') dt = {} # templates dictionary params = self.db._cog_params html = self.__rt("html") dt['head'] = self.__rt("head") dt['title'] = self.db.name dt['style'] = self.__rt("style") dt['javascript'] = self.__rt("javascript") dt['head'] = dt['head'] % ( self._charset, dt['style'], params['icon'], dt['title'], dt['javascript']) dt['ariadne'] = self.__rt("ariadne") dt['top_search'] = self.__rt("top_search") dt['body'] = self.__rt("body") dt['header'] = self.__rt("header") dt['homepage_link'] = self.__rt("homepage_link") dt['homepage_link'] = "" #dt['homepage_link'] % (self._script_name) dt['search'] = self.__rt("search") dt['login_zone'] = self.__rt("login_zone") dt['header'] %= ( dt['homepage_link'], dt['login_zone']) dt['login_container'] = self.__rt("login_container") dt['body_content'] = self.__rt("body_content") dt['footer'] = self.__rt("footer") dt['collorg_link'] = self.__rt("collorg_link") dt['footer'] %= (dt['collorg_link']) dt['body'] %= ( dt['ariadne'], dt['top_search'], dt['header'], dt['login_container'], dt['body_content'], dt['footer']) dt['debug'] = self.__rt("debug") dt['collorg_link'] = self.__rt("collorg_link") html %= (dt['head'].decode(self._charset), dt['body'].decode(self._charset)) return html def __pfce(self, obj): return html_escape(str(pformat(obj))) def __oid_req(self, **kwargs): """ The controller received a cog_oid. The object representing one and only one elt of the table is instanciated. @returns: the method cog_method applied to this object. @called by: self.__exec """ if not '_cog_fqtn_' in self.__dict__ or not self._cog_fqtn_: obj = self.db.get_elt_by_oid(self._cog_oid_) else: obj = self.db.table(self._cog_fqtn_) obj.cog_oid_.value = self._cog_oid_ obj.get() self.check_action(obj, self._cog_method) self.cog_exec_env = obj.get_environment() if (self._user is None and obj._is_cog_post and obj.visibility_.value == 'public' and self._cog_method == 'w3display'): cache = obj._cog_get_cache('w3display') if cache is not None: return cache return eval("obj.{}(**kwargs)".format(self._cog_method)) def __fqtn_req(self, **kwargs): """ No cog_oid received by the controller but a cog_fqtn. @returns: the method referenced by cog_method applied to the object instantiated without intention (aka the whole table). @called by: self.__exec """ obj = self.db.table(self._cog_fqtn_) self.check_action(obj, self._cog_method) return eval("obj.{}(**kwargs)".format(self._cog_method)) def load_site(self): #XXX REFACTOR path_info = self._path_info if self.direct_obj_ref: path_info = '/' url = "{}{}".format( self._environ['HTTP_HOST'], self._environ.get('SCRIPT_NAME', '')) site = self.db.table("collorg.web.site") if not (url, path_info) in self.__topics: topic, w3display_topic = site.load_topic( url, path_info) if self.__site is None: self.__site = site.get() self.__topics[(url, path_info)] = (w3display_topic, topic) ### self._d_topics = self.__site.load_topics() topic = self.__topics[(url, path_info)][1] self._cog_cmd = self.__topics[(url, path_info)][0] return topic @property def site(self): return self.__site @property def main_topic(self): # Post._w3get_recipient if not self.__main_topic: self.__main_topic = self.__site.load_topic()[0] return self.__main_topic @property def _session(self): return self._session_key @property def user(self): return self._user @property def cog_environment(self): return self.__cog_environment def __dumps_json_res(self): res = {} for key, val in self._json_res.items(): res[key] = {'content':val, 'action':'html'} return json.dumps(res) def __get_query_params(self): qs = {} for query in self.__request.POST, self.__request.GET: for key, val in query.items(): key = key.encode(self._charset) val = val.encode(self._charset) if key[-2:] == '[]': key = key[:-2] if key not in qs: qs[key] = [] qs[key].append(val) else: qs[key] = val return qs def set_ref_obj_oid(self, obj_oid, ref_obj_oid): if obj_oid: self.cache.set_( "ref_obj_oid", self._session_key, (obj_oid, ref_obj_oid)) def set_env(self, env): if not self._session_key: return self.__env_set = True if self.__nsession: self.cache.set_("user", self._session_key, None) self.cache.set_( "creat_date", self._session_key, self._begin) self.cache.set_( "last_access_date", self._session_key, self._begin) def __get_env(self): if self._session_key: self.cache.get_("last_access_date", self._session_key) self.cache.set_( "last_access_date", self._session_key, self._begin) self.get_user() def get_user(self): if self._session_key: user_oid = self.cache.get_("user", self._session_key) if user_oid: self._user = self.db.table( 'collorg.actor.user', cog_oid_ = user_oid).get() else: self.delete_cookie('cog_session') def set_user(self, user_oid = None): self.cache.set_("user", self._session_key, user_oid) def del_user(self, key): self.cache.del_("user", key) def __get_params(self): self._kwargs = self.__get_query_params() self._cog_ajax = self._kwargs.get('cog_ajax') self.__cog_target = self._kwargs.get('cog_target') self._cog_raw = self._kwargs.get('cog_raw', None) self._cog_method = self._kwargs.get('cog_method', None) # cog_method must not contain non-word caracters assert self._cog_method is None or \ re.search('\W', self._cog_method) is None if self._cog_method is not None and self._cog_method[0] == '_': # we never should receive a protected method... self._cog_method = "w3error" self._kwargs['cog_method'] = "w3error" self._kwargs['cog_error'] = "Can't call a protected method!" self._cog_ref_oid = self._kwargs.get('cog_ref_oid', None) self._cog_oid_ = self._kwargs.get('cog_oid_', None) self._session_key = None if 'HTTP_COOKIE' in self._environ: cookie_string = self._environ.get('HTTP_COOKIE') cookie = SimpleCookie() cookie.load(cookie_string) if 'cog_session' in cookie: self._session_key = cookie['cog_session'].value self.__cog_environment = self.__get_env() self._cog_fqtn_ = self._kwargs.get('cog_fqtn_', None) if self._cog_ref_oid and self._cog_ref_oid == self._cog_oid_: self._cog_oid_ = None self._kwargs['cog_controller'] = self self._kwargs['cog_first_call'] = True def __reset(self): """ Some things that are always done first """ self._json_res['#cog_debug_link'] = '' self._json_res['#cog_debug'] = '' self.__get_params() self.db._set_controller(self) #self._cog_cmd = self.__environment def get_page_ref(self, method = None, oid = None): method = method or self._cog_method oid = oid or self._cog_oid_ if oid: ref = oid else: env = self._environ if env and 'QUERY_STRING' in env: ref = md5.new(env['QUERY_STRING']).hexdigest() else: ref = self.__site.cog_oid_.value page_ref = "{}-{}".format(method, ref) return page_ref def __exec(self): """ constructs the call to the template. the template receives depends on the arguments passed. Case of ajax: * one of the three following arguments is expected ** a path (specific wsgi) ** an oid ** a fqtn """ _ = self.i18n.gettext i18n_drag_drop = _( "Drag & drop your links here<br>for future reference") i18n_drop_drag = _( "Drag & drop the link from the cart to \n" "the page/textarea to add a reference.\n" "(write access is mandatory)") if self._cog_oid_: self._cog_cmd = self.__oid_req elif self._cog_fqtn_: self._cog_cmd = self.__fqtn_req elif self._cog_ajax is None and self.direct_obj_ref: self._cog_cmd = self.direct_obj_ref if self._cog_ajax is None: actor = self.db.table('collorg.actor.user') result = self.__static_body.format( self.__site.w3map_link(), _("search"), _("search"), _("by tag"), _("by user"), actor.w3login_link(), _(i18n_drop_drag).decode(self._charset), _(i18n_drag_drop).decode(self._charset)) page = self._cog_cmd(**self._kwargs) if self._cog_raw: return page result %= ( "", #self._json_res['#cog_top_nav_ariadne']), self._unicode(page)) return result # ajax try: result = self._cog_cmd(**self._kwargs) if self._cog_raw: return result duration = datetime.datetime.now() - self._begin except Exception as err: # open("/tmp/cog_error_log", "a+").write("{}\n".format(err)) if self.db._cog_params['debug']: link, error = self.debug(err.__str__) self._json_res['#cog_debug_link'] = link self._json_res['#cog_debug'] = self._unicode(error) return self.__dumps_json_res() if raise_error: raise "Web controller error: {}".format(err) self._json_res['#cog_duration'] = "%s" % (duration) if self._debug: link, debug = self.debug() self._json_res['#cog_debug_link'] = link self._json_res['#cog_debug'] = self._unicode(debug) self._json_res[self.__cog_target] = result return self.__dumps_json_res() def get_cookie(self, key): return self._session_key def delete_cookie(self, key): self.__response.delete_cookie(key) def set_cookie(self, key): value = self.new_session self.__response.set_cookie(key, bytes(value)) return value def process(self, environ, start_response): self._begin = datetime.datetime.now() if self._debug: open("/tmp/cog_sql", "w") try: self.clear() self._environ = environ # open("/tmp/cog_tmp_xxx", "w").write("{}".format(environ)) self._script_name = self._environ.get('SCRIPT_NAME', '') self._server_name = self._environ['HTTP_HOST'] self._url_scheme = self._environ['wsgi.url_scheme'] self._url = "{}://{}{}".format( self._url_scheme, self._server_name, self._script_name) self._path_info = self._environ['PATH_INFO'].lower() alnum = "[a-z0-9]{4}" oid_pattern = '^/{}{}-{}-{}-{}-{}{}{}$'.format(*(alnum,)*8) if re.match(oid_pattern, self._path_info): obj = self.db.get_elt_by_oid(self._path_info[1:]) self.add_json_res({'#page_ref':self.get_page_ref()}) self.direct_obj_ref = obj.w3display self.load_site() self.__request = Request(environ) self.__lang = Accept(str(self.__request.accept_language)) self.i18n = gettext.translation( 'messages', '/usr/share/collorg/locale', [self.__lang.best_match(('en', 'fr', 'fr-FR')) or 'en']) if WebController.__static_body is None: WebController.__tags = self.__get_tags() WebController.__static_body = self.__get_static_body() self.__response = Response() self.__reset() if not(self._cog_method is None and '#page_ref' in self._json_res): self.add_json_res({'#page_ref':self.get_page_ref()}) self.__response.unicode_body = self._unicode(self.__exec()) if(self.__response.content_type != 'text/html' or self.__response.status_int != 200): # Not an HTML response, we don't want to # do anything to it return self.__response(environ, start_response) # Make sure the content isn't gzipped: self.__response.decode_content() return self.__response(environ, start_response) except Exception as err: if self.db._cog_params['debug']: response = Response() response.unicode_body = self._unicode(err) return response(environ, start_response) if raise_error: raise err def debug(self, error = None): output = [] css_style = 'debug hidden toggle' css_error = '' if error: css_style += ' debug_error' css_error = 'debug_error' title = error and "Error" or "debug" link = ( '<span class="link toggle %s" ' 'to_toggle="#cog_debug">%s</span>' % (css_error, title)) if error: output.append('<h2>Error</h2>') output.append('<pre>%s</pre>' % (self.__pfce(error))) output.append("<h2>Traceback</h2>") output.append("<pre>%s</pre>"%( traceback.format_exc())) output.append('<h2>Main variables</h2>') output.append('<pre>') output.append('cog_method = %s\n' % (self._cog_method)) output.append('cog_fqtn_ = %s\n' % (self._cog_fqtn_)) output.append('cog_oid_ = %s\n' % (self._cog_oid_)) output.append('cog_ref_oid = %s\n' % (self._cog_ref_oid)) output.append('</pre>') if error: post_error = self.db.table( 'collorg.application.communication.error') try: post_error.hit( self._cog_fqtn_, self._cog_method, traceback.format_exc()) except Exception, err: sys.stderr.write("Warning! {}\n".format(err)) # open("/tmp/cog_error_log", "a+").write("{}\n".format(err)) output.append('<h2>Query string</h2>') output.append('<pre>qs = %s</pre>' % (self.__pfce(self.__get_request))) output.append('<h2>Command executed</h2>') output.append('<pre>cmd = %s</pre>' %(self.__pfce(self._cog_cmd))) output.append('<h2>Environ</h2>') output.append('<pre>%s</pre>' % (self.__pfce(self._environ))) u_output = [self._unicode(elt) for elt in output] return link, "\n".join(u_output)
def test_best_match_with_one_lower_q(): accept = Accept("text/html, foo/bar;q=0.5") assert accept.best_match(["text/html", "foo/bar"]) == "text/html" accept = Accept("text/html;q=0.5, foo/bar") assert accept.best_match(["text/html", "foo/bar"]) == "foo/bar"