def get(self, private_id, public_id): try: exists = False db_data = yield self.ha_get_slice(key=private_id, column_family=config.PUBLIC_IDS_TABLE, start=public_id, finish=public_id) for column in db_data: if column.column.name == public_id: exists = True if not exists: raise NotFoundException() encrypted_hash = yield self.ha_get(column_family=self.table, key=private_id, column=self.column) digest = utils.decrypt_password(encrypted_hash.column.value, settings.PASSWORD_ENCRYPTION_KEY) except NotFoundException, e: if not settings.HSS_ENABLED: raise HTTPError(httplib.NOT_FOUND) # Either the digest or the association doesn't exist in the DB, attempt an # import from the HSS try: digest = yield self.application.hss_gateway.get_digest(private_id, public_id) public_ids = yield self.application.hss_gateway.get_public_ids(private_id, public_id) except HSSNotFound, e: raise HTTPError(httplib.NOT_FOUND)
def validate(self, file): """ Takes as input a file object and raises an exception if the file does not conform to the criteria. """ if self.maxFileSize and file['size'] < self.maxFileSize: raise HTTPError(406, "File too big") if not self.acceptedFileType(file['type']): raise HTTPError(406, "File of unsupported type")
def post(self, channel): try: channel = self.decode_argument(channel, "channel") except: raise HTTPError(400, "Invalid value for channel.") try: card = json.loads(self.request.body) except: raise HTTPError(400, "Invalid card in request body.") self.store.publish(channel, card) self.set_header("Content-Type", "application/json") self.write(json.dumps({"success": True}))
def check_xsrf_cookie(self): """ Override needed to change name of header name """ token = self.request.headers.get("X-XSRF-TOKEN") if not token: token = self.get_argument('xsrf-token', default=None) if not token: raise HTTPError(403, "X-XSRF-TOKEN argument missing from POST") # This is a constant time comparison provided by cryptography package if not bytes_eq(self.xsrf_token.encode('utf-8'), token.encode('utf-8')): raise HTTPError(403, "XSRF cookie does not match POST argument")
def get(self, private_id, public_id=None): if public_id is not None: raise HTTPError(httplib.METHOD_NOT_ALLOWED) db_data = yield self.ha_get_slice(key=private_id, column_family=self.table) public_ids = [] for record in db_data: public_ids.append(record.column.value) if public_ids == []: raise HTTPError(httplib.NOT_FOUND) self.finish({"private_id": private_id, "public_ids": public_ids})
def validate_request(self, request): allowed_headers = ['user-agent', 'accept', 'accept-language'] required_keys = ['http_request', 'tcp_connect'] for rk in required_keys: if rk not in request.keys(): raise HTTPError(400, "Missing %s" % rk) if not HTTP_REQUEST_REGEXP.match(request['http_request']): raise HTTPError(400, "Invalid http_request URL") http_request_headers = request.get('http_request_headers', {}) for k, v in http_request_headers.iteritems(): if k.lower() not in allowed_headers: raise HTTPError(400, "Invalid header %s" % k) if not isinstance(v, list): raise HTTPError(400, "Headers must be a list")
def get(self, public_id): db_data = yield self.ha_get_slice( key=public_id, column_family=config.PRIVATE_IDS_TABLE) private_ids = [] for record in db_data: private_ids.append(record.column.value) if private_ids == []: raise HTTPError(httplib.NOT_FOUND) # Currently only permit one private ID per public ID. assert (len(private_ids) == 1) db_data = yield self.ha_get_slice( key=private_ids[0], column_family=config.PUBLIC_IDS_TABLE) public_ids = [] for record in db_data: public_ids.append(record.column.value) assert (public_ids != [] ) # There are probably tiny windows in which this # is not the case. Best strategy? self.finish({"public_ids": public_ids})
def get(self, row): try: result = yield self.ha_get(column_family=self.table, key=row, column=self.column) self.finish(result.column.value) except NotFoundException: raise HTTPError(404)
def get(self, public_id, private_id=None): if private_id is not None: raise HTTPError(httplib.METHOD_NOT_ALLOWED) db_data = yield self.ha_get_slice(key=public_id, column_family=self.table) private_ids = [] for record in db_data: private_ids.append(record.column.value) if private_ids == []: # Note: The get_slice API does not throw a NotFoundException if it # finds no matches raise HTTPError(httplib.NOT_FOUND) self.finish({"public_id": public_id, "private_ids": private_ids})
def get(self, private_id): try: encrypted_hash = yield self.ha_get(column_family=self.table, key=private_id, column=self.column) digest = utils.decrypt_password(encrypted_hash.column.value, settings.PASSWORD_ENCRYPTION_KEY) except NotFoundException, e: raise HTTPError(httplib.NOT_FOUND)
def post(self, private_id, public_id=None): if public_id is not None: raise HTTPError(httplib.METHOD_NOT_ALLOWED) else: public_id = self.request_data.get("public_id", "") if public_id == "": raise HTTPError(httplib.METHOD_NOT_ALLOWED) yield self.insert_in_both_tables(private_id, public_id) # Retrieve the updated full list of public IDs associated with this private ID db_data = yield self.ha_get_slice(key=private_id, column_family=self.table) public_ids = [] for record in db_data: public_ids.append(record.column.value) self.finish({"private_id": private_id, "public_ids": public_ids})
def write_file(self, filepath): if not os.path.exists(filepath): raise HTTPError(404) mime_type, encoding = mimetypes.guess_type(filepath) if mime_type: self.set_header("Content-Type", mime_type) StaticFileProducer(self, open(filepath, "rb")).start()
def force_file_download(self, filename, filepath): if not os.path.exists(filepath): raise HTTPError(404) self.set_header('X-Download-Options', 'noopen') self.set_header('Content-Type', 'application/octet-stream') self.set_header('Content-Disposition', 'attachment; filename=\"%s\"' % filename) StaticFileProducer(self, open(filepath, "rb")).start()
def _success(response, deferred): if response.code == 200: data = escape.json_decode(response.body) error = data.get("error") if error: deferred.errback(Exception(error)) else: deferred.callback(data.get("result")) else: deferred.errback(HTTPError(response.code, response.phrase))
def prepare(self): # timestamp the request self._start = time.time() _log.debug( "Received request from %s - %s %s://%s%s" % (self.request.remote_ip, self.request.method, self.request.protocol, self.request.host, self.request.uri)) if not _loadmonitor.admit_request(): _log.debug("Rejecting request because of overload") return Failure(HTTPError(httplib.SERVICE_UNAVAILABLE))
def prepare(self): # Increment the request counter incoming_requests.increment() # timestamp the request self._start = monotonic() _log.info("Received request from %s - %s %s://%s%s" % (self.request.remote_ip, self.request.method, self.request.protocol, self.request.host, self.request.uri)) if not loadmonitor.admit_request(): _log.warning("Rejecting request because of overload") overload_counter.increment() return Failure(HTTPError(httplib.SERVICE_UNAVAILABLE))
def post(self, *args): self._auto_finish = False try: req = cyclone.escape.json_decode(self.request.body) jsonid = req["id"] method = req["method"] assert isinstance(method, types.StringTypes), \ "Invalid method type: %s" % type(method) params = req.get("params", []) assert isinstance(params, (types.ListType, types.TupleType)), \ "Invalid params type: %s" % type(params) except Exception, e: log.msg("Bad Request: %s" % str(e)) raise HTTPError(400)
def get(self, public_id): try: result = yield self.cass.get(column_family=self.table, key=public_id, column=self.column) ifc = result.column.value except NotFoundException, e: if not settings.HSS_ENABLED: # No HSS raise HTTPError(404) # IFC not in Cassandra, attempt to fetch from HSS try: # TODO For now we assume to same public to private id mapping as ellis private_id = utils.sip_public_id_to_private(public_id) ifc = yield self.application.hss_gateway.get_ifc( private_id, public_id) except HSSNotFound: raise HTTPError(404) # Have result from HSS, store in Cassandra yield self.cass.insert(column_family=self.table, key=public_id, column=self.column, value=ifc)
def get(self, path): if path == '': path = 'index.html' abspath = os.path.abspath(os.path.join(self.root, path)) directory_traversal_check(self.root, abspath) if not os.path.exists(abspath) or not os.path.isfile(abspath): raise HTTPError(404) mime_type, encoding = mimetypes.guess_type(abspath) if mime_type: self.set_header("Content-Type", mime_type) yield self.write_file(abspath)
def _success(response, deferred): if response.code == 200: data = escape.json_decode(response.body) error = data.get("error") if error: if isinstance(error, DictType) and 'message' in error: # JSON-RPC spec is not very verbose about error schema, # but it should look like {'code': 0, 'message': 'msg'} deferred.errback(Exception(error['message'])) else: # For backward compatibility with previous versions of # cyclone.jsonrpc.JsonrpcRequestHandler deferred.errback(Exception(error)) else: deferred.callback(data.get("result")) else: deferred.errback(HTTPError(response.code, response.phrase))
def post(self): try: request = json.loads(self.request.body) # Here we fix inconsistencies in the tcp_connect field. Due to: # https://github.com/TheTorProject/ooni-probe/issues/727 ooniprobe # was sending hostnames as part of the tcp_connect key as well as # IP addresses. # If we find something that isn't an IP address we return it with # the key value None to support backward compatibility with older # bugged clients. tcp_connect = [] invalid_sockets = [] for socket in request['tcp_connect']: if SOCKET_REGEXP.match(socket): tcp_connect.append(socket) else: invalid_sockets.append(socket) request['tcp_connect'] = tcp_connect self.validate_request(request) include_http_responses = request.get( "include_http_responses", False ) # We convert headers to str so twisted is happy (unicode triggers # errors) http_request_headers = {} for k, v in request.get('http_request_headers', {}).iteritems(): http_request_headers[str(k)] = map(str, v) self.control_measurement( http_url=str(request['http_request']), include_http_responses=include_http_responses, http_request_headers=http_request_headers, socket_list=request['tcp_connect'], invalid_sockets=invalid_sockets ) except HTTPError: raise except Exception as exc: log.msg("Got invalid request") log.exception(exc) raise HTTPError(400, 'invalid request')
def post(self, *args): self._auto_finish = False try: req = cyclone.escape.json_decode(self.request.body) jsonid = req["id"] method = req["method"] assert isinstance(method, types.StringTypes), \ "Invalid method type: %s" % type(method) params = req.get("params", []) assert isinstance(params, (types.ListType, types.TupleType)), \ "Invalid params type: %s" % type(params) except Exception as e: log.msg("Bad Request: %s" % str(e)) raise HTTPError(400) function = getattr(self, "jsonrpc_%s" % method, None) if callable(function): args = list(args) + params d = defer.maybeDeferred(function, *args) d.addBoth(self._cbResult, jsonid) else: self._cbResult(AttributeError("method not found: %s" % method), jsonid)
def post(self, *args): raise HTTPError(405)
def delete(self, *args): raise HTTPError(405)
def wrapper(self, *args, **kwargs): _log.info("Performing XSD validation") try: _validate(self.request.body, schema_path) except etree.XMLSyntaxError, e: raise HTTPError(400, log_message=str(e))
def insert_in_both_tables(self, private_id, public_id): # Check whether this association already exists - choice of 200/201 # status depends on this exists = False db_data = yield self.ha_get_slice( key=private_id, column_family=config.PUBLIC_IDS_TABLE, start=public_id, finish=public_id) for record in db_data: exists = (record.column.name == public_id) if exists: self.set_status(httplib.OK) else: # check that neither pri nor public ID is at limit of allowed associations d1 = self.ha_get_slice(key=private_id, column_family=config.PUBLIC_IDS_TABLE) d2 = self.ha_get_slice(key=public_id, column_family=config.PRIVATE_IDS_TABLE) pub_ids = yield d1 priv_ids = yield d2 if len(pub_ids) >= config.MAX_ASSOCIATED_PUB_IDS: raise HTTPError( httplib.BAD_REQUEST, "", {"reason": "Associated Public Identity limit reached"}) if len(priv_ids) >= config.MAX_ASSOCIATED_PRI_IDS: raise HTTPError( httplib.BAD_REQUEST, "", {"reason": "Associated Private Identity limit reached"}) try: # Insert in both tables. If either insert fails for any reason # at all, remove both entries so that the tables stay in step. d1 = self.cass.insert(column_family=config.PUBLIC_IDS_TABLE, key=private_id, column=public_id, value=public_id) d2 = self.cass.insert(column_family=config.PRIVATE_IDS_TABLE, key=public_id, column=private_id, value=private_id) yield d1 yield d2 except: d3 = self.cass.remove(column_family=config.PUBLIC_IDS_TABLE, key=private_id, column=public_id, value=public_id) d4 = self.cass.remove(column_family=config.PRIVATE_IDS_TABLE, key=public_id, column=private_id, value=private_id) yield d3 yield d4 raise HTTPError(httplib.INTERNAL_SERVER_ERROR) self.set_status(httplib.CREATED)
def delete(self, private_id, public_id=None): raise HTTPError(httplib.METHOD_NOT_ALLOWED)
def post(self, *args): raise HTTPError(httplib.METHOD_NOT_ALLOWED)
def test_rpc_request_error1(self): response = Mock() response.code = 404 response.body = escape.json_encode({"result": True}) cyclone.httpclient.fetch.return_value = fail(HTTPError(404)) return self.assertFailure(self.client.foo(), HTTPError)
def test_bad_status_code_error(self): self.handler.send_error = MagicMock() e = HTTPError(799) f = Failure(e) self.handler._handle_request_exception(f) self.handler.send_error.assert_called_once_with(500, exception=e)