From 5f77709881ec023adc8fe80369e7d32f5e6d3b82 Mon Sep 17 00:00:00 2001 From: Li Zhu Date: Thu, 21 Jul 2022 22:25:14 -0400 Subject: [PATCH] Debian: Add decode for the request headers According to python and WSGI documentations, in python3, all WSGI applications are expected to return encode bytes. All strings passed to or from the server must be standard Python byte strings, so no exception for the headers. We added utf-8 decode to make sure the byte string headers can be processed properly. This would not impact the previous string headers processing in the old version on CentOS. Test Plan: Verify: Subcloud manage/unmanage on CentOS Verify: Subcloud manage/unmanage on Debian Story: 2010119 Task: 45859 Signed-off-by: Li Zhu Change-Id: I69f9c3273d9b46f6b976b4ccd09504173965e1e5 --- .../dcmanager/api/controllers/v1/subclouds.py | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/distributedcloud/dcmanager/api/controllers/v1/subclouds.py b/distributedcloud/dcmanager/api/controllers/v1/subclouds.py index cb54d1fd6..9c25d40fe 100644 --- a/distributedcloud/dcmanager/api/controllers/v1/subclouds.py +++ b/distributedcloud/dcmanager/api/controllers/v1/subclouds.py @@ -197,10 +197,11 @@ class SubcloudsController(object): request.body, pecan.request.headers.get('Content-Type')) for f in fields: for part in multipart_data.parts: - header = part.headers.get('Content-Disposition') - if f in header: - data = yaml.safe_load(part.content.decode('utf8')) - payload.update({f: data}) + for hk, hv in part.headers.items(): + if (hk.decode('utf8') == 'Content-Disposition' and + f in hv.decode('utf8')): + data = yaml.safe_load(part.content.decode('utf8')) + payload.update({f: data}) return payload @staticmethod @@ -248,18 +249,22 @@ class SubcloudsController(object): def _get_reconfig_payload(self, request, subcloud_name): payload = dict() - multipart_data = decoder.MultipartDecoder(request.body, - pecan.request.headers.get('Content-Type')) + multipart_data = decoder.MultipartDecoder( + request.body, pecan.request.headers.get('Content-Type')) for filename in SUBCLOUD_RECONFIG_MANDATORY_FILE: for part in multipart_data.parts: - header = part.headers.get('Content-Disposition') - if filename in header: - fn = self._get_config_file_path(subcloud_name, consts.DEPLOY_CONFIG) - self._upload_config_file(part.content, fn, consts.DEPLOY_CONFIG) - payload.update({consts.DEPLOY_CONFIG: fn}) - elif "sysadmin_password" in header: - payload.update({'sysadmin_password': part.content}) + for hk, hv in part.headers.items(): + hv = hv.decode('utf8') + if hk.decode('utf8') == 'Content-Disposition': + if filename in hv: + fn = self._get_config_file_path( + subcloud_name, consts.DEPLOY_CONFIG) + self._upload_config_file( + part.content, fn, consts.DEPLOY_CONFIG) + payload.update({consts.DEPLOY_CONFIG: fn}) + elif "sysadmin_password" in hv: + payload.update({'sysadmin_password': part.content}) self._get_common_deploy_files(payload) return payload @@ -270,21 +275,23 @@ class SubcloudsController(object): if f not in request.POST: pecan.abort(400, _("Missing required file for %s") % f) - multipart_data = decoder.MultipartDecoder(request.body, - pecan.request.headers.get('Content-Type')) + multipart_data = decoder.MultipartDecoder( + request.body, pecan.request.headers.get('Content-Type')) for f in SUBCLOUD_RESTORE_MANDATORY_FILE: for part in multipart_data.parts: - header = part.headers.get('Content-Disposition') - if f in header: - file_item = request.POST[f] - file_item.file.seek(0, os.SEEK_SET) - data = yaml.safe_load(file_item.file.read().decode('utf8')) - payload.update({RESTORE_VALUES: data}) - elif "sysadmin_password" in header: - payload.update({'sysadmin_password': part.content}) - elif "with_install" in header: - payload.update({'with_install': part.content}) - + for hk, hv in part.headers.items(): + hv = hv.decode('utf8') + if hk.decode('utf8') == 'Content-Disposition': + if f in hv: + file_item = request.POST[f] + file_item.file.seek(0, os.SEEK_SET) + data = yaml.safe_load( + file_item.file.read().decode('utf8')) + payload.update({RESTORE_VALUES: data}) + elif "sysadmin_password" in hv: + payload.update({'sysadmin_password': part.content}) + elif "with_install" in hv: + payload.update({'with_install': part.content}) return payload def _get_config_file_path(self, subcloud_name, config_file_type=None):