def _transform(self, resource, reverse, path=[]): if isinstance(resource, dict): if '!type' not in resource: if reverse: raise HTTPReturn(http.INTERNAL_SERVER_ERROR, reason='Resource does not specify !type') elif len(path) == 0: type = collection.contains else: type = self.hints.get(path).get('type') if type is None: raise HTTPReturn(http.BAD_REQUEST, reason='No type hint for resource.') resource['!type'] = type path.append(None) for key, value in resource.items(): path[-1] = key resource[key] = self._transform(value, reverse, path) del path[-1] proc = self._get_transform(resource, reverse) if proc: if reverse: resource = proc.process_reverse(resource) else: resource = proc.process(resource) elif isinstance(resource, list): for ix, elem in enumerate(resource): resource[ix] = self._transform(resource[ix], reverse, path) return resource
def filter(self, output): if output: raise HTTPReturn( http.INTERNAL_SERVER_ERROR, reason='Not expecting any output for "delete" action') response.status = http.NO_CONTENT return ''
def parse(self, input, encoding): """Parse a JSON entity.""" try: parsed = json.loads(input, encoding) except ValueError, err: raise HTTPReturn(http.BAD_REQUEST, reason='JSON parsing error: %s' % str(err))
def format(self, object, encoding=None): """Format a resource as YAML under the specified encoding.""" try: output = yaml.dump(object, default_flow_style=False, version=(1, 1), encoding=encoding) except YAMLError, e: raise HTTPReturn(http.INTERNAL_SERVER_ERROR, reason='YAML dump error: %s' % str(e))
def parse(self, input, encoding=None): """Parse a YAML entity.""" # We can ignore the encoding as the YAML spec mandates either UTF-8 # or UTF-16 with a BOM, which can be autodetected. # We use a Loader that turns unrecognized !tags into Resources. try: parsed = yaml.load(input) except YAMLError, e: raise HTTPReturn(http.BAD_REQUEST, reason='YAML load error: %s' % str(e))
def handle(self, exception): if not isinstance(exception, ArgProcError): return exception format = FormatEntity() error = Resource('error') error['id'] = 'rest.entity_error' error['message'] = str(exception) body = format.filter(error) headers = response.headers raise HTTPReturn(http.BAD_REQUEST, headers=headers, body=body)
def parse(self, input, encoding=None): """Parse XML from `input' according to `encoding'.""" if encoding and self._re_preamble_start.match(input): # The encoding from the HTTP header takes precedence. The preamble # is the only way in which we can pass it on to ElementTree. preamble = '<?xml version="1.0" encoding="%s" ?>' % encoding mobj = self._re_preamble_end.search(input) if mobj == None: raise HTTPReturn(http.BAD_REQUEST, reason='Illegal XML input') input = input[mobj.end() + 1:] elif not encoding and not self._re_preamble_start.match(input): # RFC2616 section 3.7.1 preamble = '<?xml version="1.0" encoding="utf-8" ?>' else: preamble = '' try: root = etree.fromstring(preamble + input) except ExpatError, err: raise HTTPReturn(http.BAD_REQUEST, reason='XML Error: %s' % str(err))
def format(self, object): """Format an entity.""" if not isinstance(object, dict) and not isinstance(object, list): return object accept = request.header('Accept', '*/*') ctype = http.select_content_type(self.formatters.keys(), accept) if not ctype: raise HTTPReturn(http.NOT_ACCEPTABLE, reason='No acceptable content-type in: %s' % accept) accept = request.header('Accept-Charset', '*') charset = http.select_charset(('utf-8', ), accept) if not charset: raise HTTPReturn(http.NOT_ACCEPTABLE, reason='No acceptable charset in: %s' % accept) formatter = self.formatters[ctype] output = formatter.format(object, charset) response.set_header('Content-Type', '%s; charset=%s' % (ctype, charset)) response.set_header('Content-Length', str(len(output))) return output
def parse(self, input): """Parse an entity.""" ctype = request.header('Content-Type') if not ctype: raise HTTPReturn(http.BAD_REQUEST, reason='Missing Content-Type header') try: type, subtype, options = http.parse_content_type(ctype) except ValueError: raise HTTPReturn(http.BAD_REQUEST, reason='Illegal Content-Type header [%s]' % ctype) ctype = '%s/%s' % (type, subtype) encoding = options.get('charset') if not len(input): raise HTTPReturn(http.BAD_REQUEST, reason='No request entity provided') if ctype not in self.parsers: raise HTTPReturn(http.UNSUPPORTED_MEDIA_TYPE, reason='Content-Type not supported [%s]' % ctype) parser = self.parsers[ctype] parsed = parser.parse(input, encoding) return parsed
def _get_detail(self): for i in range(4): ctypes.append('text/xml; detail=%s' % i) ctypes.append('text/yaml; detail=%s' % i) ctype = request.preferred_content_type(ctypes) if ctype is None: return sub, subtype, params = http.parse_content_type(ctype) try: detail = int(params['detail']) except ValueError: raise HTTPReturn(http.NOT_ACCEPTABLE, reason='Non-integer "detail" in Accept header.') return detail
def read(self, size=None): """Read from the request.""" if self.content_length is None: encoding = self.header('Transfer-Encoding', 'identity') if encoding != 'identity': raise HTTPReturn(http.NOT_IMPLEMENTED, reason='Unsupported transfer encoding [%s]' % encoding) self.content_length = int(self.header('Content-Length', '0')) # Make sure we never attempt to read beyond Content-Length, as some # WSGI servers will block instead of returning EOF (which is allowed # by PEP-333). bytes_left = self.content_length - self.bytes_read if size is None or size > bytes_left: size = bytes_left input = self.environ['wsgi.input'] data = input.read(size) self.bytes_read += len(data) return data
def filter(self, input): if input: reason = 'Action does not accept any input.' raise HTTPReturn(http.BAD_REQUEST, reason=reason) return input
def filter(self, input): if request.match.get('action') == '_method_not_allowed': headers = [('Allowed', ', '.join(mapper.methods_for(request.path))) ] raise HTTPReturn(http.METHOD_NOT_ALLOWED, headers) return input