def on_post(self, req, resp):
"""Method handler for POST requests.
:param req: Falcon request object
:param resp: Falcon response object
"""
try:
json_data = self.req_json(req)
design = None
if json_data is not None:
base_design = json_data.get('base_design_id', None)
if base_design is not None:
base_design = uuid.UUID(base_design)
design = hd_objects.SiteDesign(base_design_id=base_design)
else:
design = hd_objects.SiteDesign()
design.assign_id()
design.create(req.context, self.state_manager)
resp.body = json.dumps(design.obj_to_simple())
resp.status = falcon.HTTP_201
except errors.StateError:
self.error(req.context, "Error updating persistence")
self.return_error(
resp,
falcon.HTTP_500,
message="Error updating persistence",
retry=True)
except errors.InvalidFormat as fex:
self.error(req.context, str(fex))
self.return_error(
resp, falcon.HTTP_400, message=str(fex), retry=False)
python类HTTP_400的实例源码
def on_post(self, req, resp):
"""Handler for POST method."""
# A map of supported actions to the handlers for tasks for those actions
supported_actions = {
'validate_design': TasksResource.task_validate_design,
'verify_site': TasksResource.task_verify_site,
'prepare_site': TasksResource.task_prepare_site,
'verify_nodes': TasksResource.task_verify_nodes,
'prepare_nodes': TasksResource.task_prepare_nodes,
'deploy_nodes': TasksResource.task_deploy_nodes,
'destroy_nodes': TasksResource.task_destroy_nodes,
}
try:
json_data = self.req_json(req)
action = json_data.get('action', None)
if supported_actions.get(action, None) is None:
self.error(req.context, "Unsupported action %s" % action)
self.return_error(
resp,
falcon.HTTP_400,
message="Unsupported action %s" % action,
retry=False)
else:
supported_actions.get(action)(self, req, resp, json_data)
except Exception as ex:
self.error(req.context, "Unknown error: %s\n%s" %
(str(ex), traceback.format_exc()))
self.return_error(
resp, falcon.HTTP_500, message="Unknown error", retry=False)
def test_should_fail_empty_body(self, bulk_processor):
events_resource = _init_resource(self)
events_resource._processor = bulk_processor
self.simulate_request(
path=ENDPOINT,
method='POST',
headers={
'Content-Type': 'application/json',
'X_ROLES': 'monasca'
},
body=''
)
self.assertEqual(falcon.HTTP_400, self.srmock.status)
def test_request_for_incorrect_version(self):
incorrect_version = 'v2.0'
uri = _get_versioned_url(incorrect_version)
self.simulate_request(
uri,
method='GET',
headers={
'Content-Type': 'application/json'
}
)
self.assertEqual(falcon.HTTP_400, self.srmock.status)
def cmd_post_rgb_change_single(self, req, resp, post_params):
"""This method handles changing the keys of the keyboard to a single colour."""
# We check if all arguments exist
if post_params["arguments"]["key"] and post_params["arguments"]["color"]:
if self.is_hex_color(post_params["arguments"]["color"]):
# We check if the command executed successfully
if self.keyboard.set_key_color(post_params["arguments"]["key"], (
int(post_params["arguments"]["color"][:2], base=16),
int(post_params["arguments"]["color"][2:4], base=16),
int(post_params["arguments"]["color"][4:], base=16))):
# Successfully executed the command
resp.status = falcon.HTTP_200
resp.body = json.dumps({"message": "Command successfully executed"})
return
else:
# Invalid arguments
resp.status = falcon.HTTP_400
resp.body = json.dumps({"message": "Invalid arguments"})
else:
# Invalid arguments
resp.status = falcon.HTTP_400
resp.body = json.dumps({"message": "Invalid arguments"})
else:
# Invalid arguments
resp.status = falcon.HTTP_400
resp.body = json.dumps({"message": "Invalid arguments"})
def on_post(self, req, resp):
href = req.get_param('href', required=True)
try:
config = Configuration.from_design_ref(href)
validation.check_design(config)
msg = "Promenade validations succeeded"
return self._return_msg(resp, falcon.HTTP_200, message=msg)
except exceptions.ValidationException as e:
msg = "Promenade validations failed: %s" % str(e)
return self._return_msg(
resp, falcon.HTTP_400, status="Invalid", message=msg)
def on_get(self, req, resp):
"""Handles GET requests"""
model_type = req.get_param('model-type')
resp.status = falcon.HTTP_200 # This is the default status
if model_type:
resp.body = str(self.load_balancer.get_model_to_workers_list(model_type))
else:
resp.status = falcon.HTTP_400
raise falcon.HTTPBadRequest("Bad Request", "model-type is missing in query params")
def bad_request(message):
raise falcon.HTTPBadRequest(
description=message, title=falcon.HTTP_400, code=400)
def on_put(self, req, resp, address):
"""
Handles the creation of a new Host.
:param req: Request instance that will be passed through.
:type req: falcon.Request
:param resp: Response instance that will be passed through.
:type resp: falcon.Response
:param address: The address of the Host being requested.
:type address: str
"""
try:
# Extract what we need from the input data.
# Don't treat it as a skeletal host record.
req_data = req.stream.read()
req_body = json.loads(req_data.decode())
ssh_priv_key = req_body['ssh_priv_key']
# Remote user is optional.
remote_user = req_body.get('remote_user', 'root')
# Cluster member is optional.
cluster_name = req_body.get('cluster', None)
except (KeyError, ValueError):
self.logger.info(
'Bad client PUT request for host {0}: {1}'.
format(address, req_data))
resp.status = falcon.HTTP_400
return
resp.status, host_model = util.etcd_host_create(
address, ssh_priv_key, remote_user, cluster_name)
req.context['model'] = host_model
def on_put(self, req, resp):
"""
Handles the creation of a new Host.
:param req: Request instance that will be passed through.
:type req: falcon.Request
:param resp: Response instance that will be passed through.
:type resp: falcon.Response
"""
try:
address = req.env['REMOTE_ADDR']
except KeyError:
self.logger.info('Unable to determine host address')
resp.status = falcon.HTTP_400
return
try:
# Extract what we need from the input data.
# Don't treat it as a skeletal host record.
req_data = req.stream.read()
req_body = json.loads(req_data.decode())
ssh_priv_key = req_body['ssh_priv_key']
# Remote user is optional.
remote_user = req_body.get('remote_user', 'root')
# Cluster member is optional.
cluster_name = req_body.get('cluster', None)
except (KeyError, ValueError):
self.logger.info(
'Bad client PUT request for host {0}: {1}'.
format(address, req_data))
resp.status = falcon.HTTP_400
return
resp.status, host_model = util.etcd_host_create(
address, ssh_priv_key, remote_user, cluster_name)
req.context['model'] = host_model
def on_post(self, req, resp):
# create resp message
resp_message = {
'kind': 'Status',
'apiVersion': 'v1',
'metaData': {},
'status': '',
'message': '',
'reason': 'Validation',
'details': {
'errorCount': 0,
'messageList': []
},
'code': '',
}
try:
json_data = self.req_json(req)
if json_data is None:
resp.status = falcon.HTTP_400
err_message = 'Request body must not be empty for validation.'
self.error(req.context, err_message)
return self.return_error(resp, falcon.HTTP_400, err_message)
design_ref = json_data.get('href', None)
if not design_ref:
resp.status = falcon.HTTP_400
err_message = 'The "href" key must be provided in the request body.'
self.error(req.context, err_message)
return self.return_error(resp, falcon.HTTP_400, err_message)
message, design_data = self.orchestrator.get_effective_site(
design_ref)
resp_message['details']['errorCount'] = message.error_count
resp_message['details']['messageList'] = [m.to_dict() for m in message.message_list]
if message.error_count == 0:
resp_message['status'] = 'Valid'
resp_message['message'] = 'Drydock Validations succeeded'
resp_message['code'] = 200
resp.status = falcon.HTTP_200
resp.body = json.dumps(resp_message)
else:
resp_message['status'] = 'Invalid'
resp_message['message'] = 'Drydock Validations failed'
resp_message['code'] = 400
resp.status = falcon.HTTP_400
resp.body = json.dumps(resp_message)
except errors.InvalidFormat as e:
err_message = str(e)
resp.status = falcon.HTTP_400
self.error(req.context, err_message)
self.return_error(resp, falcon.HTTP_400, err_message)
def on_post(self, req, resp, design_id):
ingester_name = req.params.get('ingester', None)
if ingester_name is None:
self.error(
None,
"DesignsPartsResource POST requires parameter 'ingester'")
self.return_error(
resp,
falcon.HTTP_400,
message="POST requires parameter 'ingester'",
retry=False)
else:
try:
raw_body = req.stream.read(req.content_length or 0)
if raw_body is not None and len(raw_body) > 0:
parsed_items = self.ingester.ingest_data(
plugin_name=ingester_name,
design_state=self.state_manager,
content=raw_body,
design_id=design_id,
context=req.context)
resp.status = falcon.HTTP_201
resp.body = json.dumps(
[x.obj_to_simple() for x in parsed_items])
else:
self.return_error(
resp,
falcon.HTTP_400,
message="Empty body not supported",
retry=False)
except ValueError:
self.return_error(
resp,
falcon.HTTP_500,
message="Error processing input",
retry=False)
except LookupError:
self.return_error(
resp,
falcon.HTTP_400,
message="Ingester %s not registered" % ingester_name,
retry=False)
def on_get(self, req, resp):
"""This method handles all get requests to our API."""
# The requester has to be able to accept json
if req.client_accepts_json:
# We check if the user used a command or not
if req.content_length in (0, None):
# Everything went ok
resp.status = falcon.HTTP_200
# We return the string representation of the keyboard
resp.body = json.dumps({"keyboard": str(self.keyboard)})
else:
# We check if the user want/tries to use a command
try:
# Store the request body
req_body = req.stream.read().decode("utf-8")
# We try to parse the request as json
post_params = json.loads(req_body)
# We check that the arguments exist and are valid
if post_params["command"]:
# We check what command was used
for command in self.get_commands:
# We check if the current request matches the command
if post_params["command"] == command["command"]:
# We call the command method with the request object, response object, and the parsed request dictionary
command["method"](req, resp, post_params)
# No more than one command shall be executed per request
break
else:
# If no command was found we return bad request
resp.status = falcon.HTTP_400
resp.body = json.dumps({"message": "Invalid command"})
else:
# Invalid arguments
resp.status = falcon.HTTP_400
resp.body = json.dumps({"message": "Invalid arguments"})
# We're done now
return
except json.JSONDecodeError:
resp.status = falcon.HTTP_400
resp.body = json.dumps({"message": "Invalid JSON"})
else:
# Fuck you user
resp.status = falcon.HTTP_417
resp.body = json.dumps({"message": "Client doesn't accept JSON"})
def on_post(self, req, resp):
"""This method handles all post requests to our API."""
# The requester has to be able to accept json
if req.client_accepts_json:
try:
if req.content_length in (0, None):
raise json.JSONDecodeError
# We store the request body
req_body = req.stream.read().decode("utf-8")
# We try to parse the request as json
post_params = json.loads(req_body)
# We check that the arguments exist and are valid
if post_params["command"]:
# We check what command was used
for command in self.post_commands:
# We check if the current request matches the command
if post_params["command"] == command["command"]:
# We call the command method with the request object, response object, and the parsed request dictionary
command["method"](req, resp, post_params)
# No more than one command shall be executed per request
break
else:
# If no command was found we return bad request
resp.status = falcon.HTTP_400
resp.body = json.dumps({"message": "Invalid command"})
else:
# Invalid arguments
resp.status = falcon.HTTP_400
resp.body = json.dumps({"message": "Invalid arguments"})
# We're done now
return
except json.JSONDecodeError:
resp.status = falcon.HTTP_400
resp.body = json.dumps({"message": "Invalid JSON"})
else:
# Fuck you user
resp.status = falcon.HTTP_417
def getGeonym(self, req, resp, query=None):
resp.status = falcon.HTTP_200
geo = None
# projections utilisées pour transformation en WGS84/Lambert93
s_srs = Proj(init='EPSG:2154')
t_srs = Proj(init='EPSG:4326')
if 'x' in req.params and 'y' in req.params:
lon,lat = transform(s_srs,t_srs,req.params['x'],req.params['y'])
query = geonym.ll2geonym(lat, lon)
elif 'lat' in req.params and 'lon' in req.params:
query = geonym.ll2geonym(float(req.params['lat']), float(req.params['lon']))
elif 'geonym' in req.params:
query = req.params['geonym']
elif 'adresse' in req.params:
r = requests.get(URL_GEOCODER+'/search', params={"q":req.params['adresse'], "autocomplete":0, "limit":1}, timeout=1)
geo = json.loads(r.text)
geo['source']=URL_GEOCODER
query = geonym.ll2geonym(geo['features'][0]['geometry']['coordinates'][1], geo['features'][0]['geometry']['coordinates'][0])
if query is not None and geonym.checkGeonym(query):
rev = None
data = geonym.geonym2ll(query)
if 'reverse' in req.params and req.params['reverse']=='yes':
r = requests.get(URL_GEOCODER+'/reverse', params={"lat":data['lat'],"lon":data['lon'],"limit":1}, timeout=1)
if r.status_code == 200:
rev = json.loads(r.text)
rev['source']=URL_GEOCODER
x,y = transform(t_srs,s_srs,data['lon'],data['lat'])
# on ne retourne les coordonnées Lambert que si on est en zone Lambert93
if y > -357823.2365 and x > 6037008.6939 and y < 1313632.3628 and x< 7230727.3772:
data['x'] = int(x)
data['y'] = int(y)
data['checksum'] = geonym.checksum(query)
geojson = {"type":"Feature",
"properties":data,
"link": "http://www.geonym.fr/visu/?g=%s" % (geonym.cleanGeonym(query),),
"params":geonym.getParams(),
"geometry":{"type":"Polygon","coordinates":[[[data['west'],data['south']],[data['east'],data['south']],[data['east'],data['north']],[data['west'],data['north']],[data['west'],data['south']]]]}}
if rev is not None:
geojson['reverse'] = rev
if geo is not None:
geojson['geocode'] = geo
resp.body = json.dumps(geojson, sort_keys=True, indent=4, separators=(',', ': '))
resp.set_header('Content-type','application/json')
else:
geojson = {
"type": "Feature",
"link": "https://github.com/geonym/geonymapi",
"params": geonym.getParams()
}
resp.status = falcon.HTTP_400
resp.set_header('Content-type', 'application/json')
resp.body = json.dumps(
geojson, sort_keys=True, indent=4, separators=(',', ': '))
def test_cluster_hosts_overwrite(self):
"""
Verify overwriting a cluster host list.
"""
with mock.patch('cherrypy.engine.publish') as _publish:
manager = mock.MagicMock(StoreHandlerManager)
_publish.return_value = [manager]
# Verify setting host list works with a proper request
manager.get.return_value = make_new(CLUSTER_WITH_FLAT_HOST)
body = self.simulate_request(
'/api/v0/cluster/development/hosts', method='PUT',
body='{"old": ["10.2.0.2"], "new": ["10.2.0.2", "10.2.0.3"]}')
self.assertEqual(falcon.HTTP_200, self.srmock.status)
self.assertEqual({}, json.loads(body[0]))
# Verify bad request (KeyError) returns the proper result
manager.get.side_effect = KeyError
body = self.simulate_request(
'/api/v0/cluster/development/hosts', method='PUT',
body='{"new": ["10.2.0.2", "10.2.0.3"]}')
self.assertEqual(falcon.HTTP_400, self.srmock.status)
self.assertEqual({}, json.loads(body[0]))
# Verify bad request (TypeError) returns the proper result
manager.get.side_effect = TypeError
body = self.simulate_request(
'/api/v0/cluster/development/hosts', method='PUT',
body='["10.2.0.2", "10.2.0.3"]')
self.assertEqual(falcon.HTTP_400, self.srmock.status)
self.assertEqual({}, json.loads(body[0]))
# Verify bad cluster name returns the proper result
manager.get.side_effect = Exception
body = self.simulate_request(
'/api/v0/cluster/bogus/hosts', method='PUT',
body='{"old": ["10.2.0.2"], "new": ["10.2.0.2", "10.2.0.3"]}')
self.assertEqual(falcon.HTTP_404, self.srmock.status)
self.assertEqual({}, json.loads(body[0]))
# Verify host list conflict returns the proper result
manager.get.side_effect = None
body = self.simulate_request(
'/api/v0/cluster/development/hosts', method='PUT',
body='{"old": [], "new": ["10.2.0.2", "10.2.0.3"]}')
self.assertEqual(falcon.HTTP_409, self.srmock.status)
self.assertEqual({}, json.loads(body[0]))
def on_put(self, req, resp, name):
"""
Handles PUT requests for Cluster hosts.
This replaces the entire host list for a Cluster.
:param req: Request instance that will be passed through.
:type req: falcon.Request
:param resp: Response instance that will be passed through.
:type resp: falcon.Response
:param name: The name of the Cluster being requested.
:type name: str
"""
try:
req_body = json.loads(req.stream.read().decode())
old_hosts = set(req_body['old']) # Ensures no duplicates
new_hosts = set(req_body['new']) # Ensures no duplicates
except (KeyError, TypeError):
self.logger.info(
'Bad client PUT request for cluster "{0}": {1}'.
format(name, req_body))
resp.status = falcon.HTTP_400
return
try:
store_manager = cherrypy.engine.publish('get-store-manager')[0]
cluster = store_manager.get(Cluster.new(name=name))
except:
resp.status = falcon.HTTP_404
return
# old_hosts must match current hosts to accept new_hosts.
if old_hosts != set(cluster.hostset):
self.logger.info(
'Conflict setting hosts for cluster {0}'.format(name))
self.logger.debug('{0} != {1}'.format(old_hosts, cluster.hostset))
resp.status = falcon.HTTP_409
return
# FIXME: Need input validation. For each new host,
# - Does the host exist at /commissaire/hosts/{IP}?
# - Does the host already belong to another cluster?
# FIXME: Should guard against races here, since we're fetching
# the cluster record and writing it back with some parts
# unmodified. Use either locking or a conditional write
# with the etcd 'modifiedIndex'. Deferring for now.
cluster.hostset = list(new_hosts)
store_manager.save(cluster)
resp.status = falcon.HTTP_200
def on_put(self, req, resp, name):
"""
Handles the creation of a new Network.
:param req: Request instance that will be passed through.
:type req: falcon.Request
:param resp: Response instance that will be passed through.
:type resp: falcon.Response
:param name: The friendly name of the network.
:type address: str
"""
try:
req_data = req.stream.read()
req_body = json.loads(req_data.decode())
network_type = req_body['type']
options = req_body.get('options', {})
except (KeyError, ValueError):
self.logger.info(
'Bad client PUT request for network {0}: {1}'.
format(name, req_data))
resp.status = falcon.HTTP_400
return
store_manager = cherrypy.engine.publish('get-store-manager')[0]
# If the type is flannel_etcd yet we have not etcd backend configured
# don't create and notify the caller
if network_type == C.NETWORK_TYPE_FLANNEL_ETCD:
backend_found = False
for handler_type, _, _ in store_manager.list_store_handlers():
if handler_type is EtcdStoreHandler:
backend_found = True
break
if not backend_found:
self.logger.info(
'Network {0} can not be created as type flannel_etcd '
'as no etcd backend is configured.'.format(name))
resp.status = falcon.HTTP_CONFLICT
return
network = Network.new(name=name, type=network_type, options=options)
self.logger.debug('Saving network: {0}'.format(network.to_json()))
store_manager.save(network)
resp.status = falcon.HTTP_CREATED
req.context['model'] = network