def generate_webmethod_etag(context, item, registration, wrapper): if item is not None: # locate web method's descriptor filter_class = wrapper.__class__ while wrapper.__class__.__module__ == filter_class.__module__: wrapper = wrapper.decorator method_id = [context.user._id, struct.pack('>d', item.modified), struct.pack('>q', hash(tuple(item.__props__.keys()))), context.request.get_lang()] if item.isCollection: # add containment hash containment_hash = hash(tuple(item.containment)) method_id.append(struct.pack('>q', containment_hash)) try: # python 2.6 func_code = wrapper.func.func_code except AttributeError: # python 3 func_code = wrapper.func.__code__ method_id.append(func_code.co_code) method_id.append(struct.pack('>q', hash(func_code.co_varnames))) # exclude None from consts method_id.append(struct.pack('>q', hash(func_code.co_consts[1:]))) if wrapper.template is not None: func_dir = os.path.dirname( sys.modules[wrapper.func.__module__].__file__) template_file = '%s%s%s' % (func_dir, os.path.sep, wrapper.template) method_id.append(misc.generate_file_etag(template_file)) return misc.hash(*method_id).hexdigest()
def normal_template(context, filename, vars): tag = misc.generate_file_etag(filename) src = _get_template_src(filename) # process includes src = preprocessor.expand_includes(src) # extract data from base-template src, data = preprocessor.extract_data(src) if data: for var in data: cache_key = '%s#def%s' % (filename, var) cache_tag, fn = _normal_cache.get(cache_key, (None, None)) if cache_tag != tag: fn = normaltemplate.compile(data[var]) _normal_cache[cache_key] = (tag, fn) vars[var] = fn(vars) # detect super-template super = preprocessor.get_template_path(src) if super is not None: super_path = '%s/%s' % (os.path.dirname(filename), super) tag = misc.generate_file_etag(super_path) cache_tag, super_fn = _normal_cache.get(super_path, (None, None)) if cache_tag != tag: st_src = _get_template_src(super_path) super_fn = normaltemplate.compile(st_src) _normal_cache[super_path] = (tag, super_fn) src = super_fn(vars) fn = normaltemplate.compile(src) else: cache_tag, fn = _normal_cache.get(filename, (None, None)) if cache_tag != tag: # compile fn = normaltemplate.compile(src) _normal_cache[filename] = (tag, fn) context.response.write(fn(vars))
def handle_request(self, rh, raw_request=None): if raw_request is None: raw_request = loads(rh.input_buffer) response = context.response = HttpResponse() request = context.request = HttpRequest(raw_request) item = None registration = None # get sessionid session_id = None cookies_enabled = True path_info = request.serverVariables['PATH_INFO'] #print(path_info) # detect if sessionid is injected in the URL session_match = re.match(self._sid_pattern, path_info) if session_match: path_info = path_info.replace(session_match.group(), '', 1) or '/' request.serverVariables['PATH_INFO'] = path_info session_id = session_match.group(1) cookies_enabled = False # otherwise check cookie elif '_sid' in request.cookies: session_id = request.cookies['_sid'].value cookies_enabled = True try: try: path_tokens = path_info.split('/') if len(path_tokens) > 1: dir_name = path_tokens[1] web_app = pubdirs.dirs.get(dir_name, None) else: web_app = None if web_app is None: # create snapshot txn for reads context._trans = _db.get_transaction(snapshot=True) # try to get the requested object from the db item = _db.get_item(path_info) if item is not None and not item._isDeleted: self._fetch_session(session_id, cookies_enabled) self._dispatch_method(item) else: raise exceptions.NotFound( 'The resource "%s" does not exist' % path_info) else: # request to a published directory self._fetch_session(session_id, cookies_enabled) # remove blank entry & app name to get the requested path dir_path = '/'.join(path_tokens[2:]) registration = web_app.get_registration( dir_path, request.serverVariables['REQUEST_METHOD'], request.serverVariables['HTTP_USER_AGENT'], request.get_lang()) if not registration: raise exceptions.NotFound( 'The resource "%s" does not exist' % path_info) # apply pre-processing filters [filter[0].apply(context, item, registration, **filter[1]) for filter in registration.filters if filter[0].type == 'pre'] rtype = registration.type if rtype == 1: # psp page # create snapshot txn for reads context._trans = _db.get_transaction(snapshot=True) ServerPage.execute(context, registration.context) elif rtype == 0: # static file f_name = registration.context if_none_match = request.HTTP_IF_NONE_MATCH if if_none_match is not None and if_none_match == \ '"%s"' % misc.generate_file_etag(f_name): response._code = 304 else: response.load_from_file(f_name) if not any([f[0].mutates_output for f in registration.filters if f[0].type == 'post']): response.set_header( 'ETag', '"%s"' % misc.generate_file_etag(f_name)) if registration.encoding: response.charset = registration.encoding except exceptions.ResponseEnd as e: pass if registration is not None and response._code == 200: # do we have caching directive? if registration.max_age: response.set_expiration(registration.max_age) # apply post-processing filters [filter[0].apply(context, item, registration, **filter[1]) for filter in registration.filters if filter[0].type == 'post'] except exceptions.InternalRedirect as e: lstPathInfo = e.args[0].split('?') raw_request['env']['PATH_INFO'] = lstPathInfo[0] if len(lstPathInfo) == 2: raw_request['env']['QUERY_STRING'] = lstPathInfo[1] else: raw_request['env']['QUERY_STRING'] = '' self.handle_request(rh, raw_request) except exceptions.DBReadOnly: context._teardown() # proxy request to master rep_mgr = _db.get_replication_manager() if rep_mgr.master is not None: master_addr = rep_mgr.master.req_address master_request = BaseRequest(rh.input_buffer) try: master_response = master_request.get_response(master_addr) except: pass else: rh.write_buffer(master_response) return e = exceptions.InternalServerError('Database is in read-only mode') e.output_traceback = False e.emit(context, item) except exceptions.PorcupineException as e: e.emit(context, item) except: e = exceptions.InternalServerError() e.emit(context, item) context._teardown() settings['requestinterfaces'][request.interface](rh, response)
def handle_request(self, rh, raw_request=None): if raw_request == None: raw_request = loads(rh.input_buffer) response = HttpResponse() request = HttpRequest(raw_request) item = None registration = None try: try: self.context = HttpContext(request, response) sPath = request.serverVariables['PATH_INFO'] item = _db.get_item(sPath) if item != None and not item._isDeleted: self.context._fetch_session() self.dispatch_method(item) else: # dir request lstPath = sPath.split('/') dirName = lstPath[1] # remove blank entry & app name to get the requested path sDirPath = '/'.join(lstPath[2:]) webApp = pubdirs.dirs.get(dirName, None) if webApp: registration = webApp.getRegistration( sDirPath, request.serverVariables['REQUEST_METHOD'], request.serverVariables['HTTP_USER_AGENT'], request.getLang()) if not registration: raise exceptions.NotFound, \ 'The resource "%s" does not exist' % sPath rtype = registration.type if rtype == 1: # in case of psp fetch session self.context._fetch_session() # apply pre-processing filters [filter[0].apply(self.context, item, registration, **filter[1]) for filter in registration.filters if filter[0].type == 'pre'] if rtype == 1: # psp page ServerPage.execute(self.context, registration.context) elif rtype == 0: # static file f_name = registration.context if_none_match = request.HTTP_IF_NONE_MATCH if if_none_match != None and if_none_match == \ '"%s"' % misc.generate_file_etag(f_name): response._code = 304 else: response.loadFromFile(f_name) response.setHeader('ETag', '"%s"' % misc.generate_file_etag(f_name)) if registration.encoding: response.charset = registration.encoding except exceptions.ResponseEnd, e: pass if registration != None and response._code == 200: # do we have caching directive? if registration.max_age: response.setExpiration(registration.max_age) # apply post-processing filters [filter[0].apply(self.context, item, registration, **filter[1]) for filter in registration.filters if filter[0].type == 'post']