From 80a8ff76d7ff83fdee9320181b327980938ba1f8 Mon Sep 17 00:00:00 2001 From: Daniel Zinov Date: Thu, 27 Jan 2022 23:44:47 +0000 Subject: [PATCH] fix multiple content type issue for requestBody --- Makefile | 14 ++++---- almdrlib/client.py | 51 +++++++++++++++++++----------- tests/apis/testapi/testapi.v1.yaml | 29 +++++++++++++++++ 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index d128e80..58a10a0 100644 --- a/Makefile +++ b/Makefile @@ -21,10 +21,12 @@ for line in sys.stdin: endef export PRINT_HELP_PYSCRIPT -BROWSER := python -c "$$BROWSER_PYSCRIPT" +PYTHON := python +BROWSER := $(PYTHON) -c "$$BROWSER_PYSCRIPT" +PIP := pip help: - @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) + @$(PYTHON) -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts @@ -51,7 +53,7 @@ lint: ## check style with flake8 flake8 almdrlib tests test: ## run tests quickly with the default Python - python setup.py test + $(PYTHON) setup.py test test-all: ## run tests on every Python version with tox tox @@ -78,11 +80,11 @@ release: dist ## package and upload a release twine upload --skip-existing dist/alertlogic-sdk-python-*.* dist/* dist: clean ## builds source and wheel package - python setup.py sdist + $(PYTHON) setup.py sdist install: clean ## install the package to the active Python's site-packages - python setup.py install + $(PYTHON) setup.py install uninstall: ## uninstall the package from the active Python's site-packages - pip uninstall alertlogic-sdk-python -y + $(PIP) uninstall alertlogic-sdk-python -y diff --git a/almdrlib/client.py b/almdrlib/client.py index 67e8d4d..2d879d7 100644 --- a/almdrlib/client.py +++ b/almdrlib/client.py @@ -104,8 +104,9 @@ def exceptions(self): class RequestBodyParameter(object): - def __init__(self, name, schema, required=False, session=None): + def __init__(self, name, content_type, schema, required=False, session=None): self._name = name + self._content_type = content_type self._schema = schema self._required = required self._session = session @@ -130,6 +131,10 @@ def validate(self, data): def name(self): return self._name + @property + def content_type(self): + return self._content_type + @property def required(self): return self._required @@ -142,18 +147,22 @@ def schema(self): class RequestBodySchemaParameter(RequestBodyParameter): - def __init__(self, name, schema, required=False, session=None): - super().__init__(name, schema, required, session) + def __init__(self, name, content_type, schema, required=False, session=None): + super().__init__(name, content_type, schema, required, session) def serialize(self, kwargs, header=[]): data = kwargs.pop(self.name, {}) - self.validate(data) - kwargs['data'] = json.dumps(data) + json_content_types = ['application/json', 'alertlogic/json'] + if self.content_type in json_content_types: + self.validate(data) + kwargs['data'] = json.dumps(data) + else: + kwargs['data'] = data class RequestBodySimpleParameter(RequestBodyParameter): - def __init__(self, name, schema, required=False, session=None): - super().__init__(name, schema, required, session) + def __init__(self, name, content_type, schema, required=False, session=None): + super().__init__(name, content_type, schema, required, session) self._format = schema.get(OpenAPIKeyWord.FORMAT) def serialize(self, kwargs, header=None): @@ -167,12 +176,14 @@ def serialize(self, kwargs, header=None): class RequestBodyObjectParameter(RequestBodyParameter): def __init__(self, name, + content_type, schema, al_schema={}, required=False, session=None): super().__init__( name, + content_type, _normalize_schema(name, schema, required), @@ -268,6 +279,7 @@ def add_content(self, content_type, schema, al_schema): if datatype == OpenAPIKeyWord.OBJECT: parameter = RequestBodyObjectParameter( name=name, + content_type = content_type, schema=schema, al_schema=al_schema, required=self._required, @@ -276,6 +288,7 @@ def add_content(self, content_type, schema, al_schema): elif datatype in OpenAPIKeyWord.SIMPLE_DATA_TYPES: parameter = RequestBodySimpleParameter( name=name, + content_type = content_type, schema=schema, required=self._required, session=self._session @@ -283,6 +296,7 @@ def add_content(self, content_type, schema, al_schema): else: parameter = RequestBodySchemaParameter( name=name, + content_type = content_type, schema=schema, required=self._required, session=self._session @@ -299,7 +313,11 @@ def serialize(self, headers, kwargs): # # Get content parameters. # - if OpenAPIKeyWord.CONTENT_TYPE_PARAM in headers: + if 'content_type' in kwargs: + content_type = kwargs.pop('content_type') + payload_body_param = self._content[content_type] + headers[OpenAPIKeyWord.CONTENT_TYPE_PARAM] = content_type + elif OpenAPIKeyWord.CONTENT_TYPE_PARAM in headers: content_type = headers[OpenAPIKeyWord.CONTENT_TYPE_PARAM] payload_body_param = self._content[content_type] elif self.default_content_type: @@ -626,16 +644,13 @@ def get_schema(self): params_schema.update(schema.get(OpenAPIKeyWord.PROPERTIES)) payload_content = schema.get('x-alertlogic-payload-content') if payload_content: - params_schema['content_type'].update( - {'x-alertlogic-payload-content': payload_content} - ) - - # if OpenAPIKeyWord.CONTENT in schema: - # result.update(schema) - # if 'x-alertlogic-payload' in schema: - # params_schema['content_type'].update(schema) - # else: - # params_schema.update(schema.get(OpenAPIKeyWord.PROPERTIES)) + # require alcli --content_type argument + params_schema['content_type'] = { + OpenAPIKeyWord.IN: OpenAPIKeyWord.HEADER, + OpenAPIKeyWord.NAME: 'content_type', + OpenAPIKeyWord.REQUIRED: True, + OpenAPIKeyWord.TYPE: OpenAPIKeyWord.STRING + } result.update({ OpenAPIKeyWord.PARAMETERS: dict(sorted(params_schema.items())) diff --git a/tests/apis/testapi/testapi.v1.yaml b/tests/apis/testapi/testapi.v1.yaml index 57ad07b..856a405 100644 --- a/tests/apis/testapi/testapi.v1.yaml +++ b/tests/apis/testapi/testapi.v1.yaml @@ -84,6 +84,35 @@ paths: name: payload encoding: explode: true + + /testapi/v1/{account_id}/test_multiple_content_types: + post: + operationId: test_multiple_content_types + requestBody: + required: true + content: + text/csv: + schema: + type: object + application/json: + examples: + schema: + type: object + summary: Import protection scope + description: |- + Endpoint for importing the protection scope of a deployment. + parameters: + - schema: + type: string + name: account_id + in: path + required: true + description: AIMS Account ID + + responses: + '200': + description: OK + components: schemas: SimpleDataTypesModel: