diff --git a/examples/protocols/http2_request/example_test.py b/examples/protocols/http2_request/example_test.py new file mode 100644 index 0000000000..c97d7f7f8e --- /dev/null +++ b/examples/protocols/http2_request/example_test.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# Copyright 2021 Espressif Systems (Shanghai) CO LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import http.client +import os + +import tiny_test_fw +import ttfw_idf +from tiny_test_fw import Utility + +HTTP_OK = 200 +TEST_SERVER = 'http2.golang.org' + + +def is_test_server_available(): # type: () -> bool + # 443 - default https port + conn = http.client.HTTPSConnection(TEST_SERVER, 443, timeout=10) + conn.request('GET', '/') + resp = conn.getresponse() + conn.close() + if resp.status == HTTP_OK: + return True + return False + + +@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') +def test_examples_protocol_http2_request(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument + """ + steps: | + 1. join AP + 2. connect to http2.golang.org + 3. send http2 request + 4. send http2 put response + """ + dut1 = env.get_dut('http2_request', 'examples/protocols/http2_request', dut_class=ttfw_idf.ESP32DUT) + # check and log bin size + binary_file = os.path.join(dut1.app.binary_path, 'http2-request.bin') + bin_size = os.path.getsize(binary_file) + ttfw_idf.log_performance('http2_request_bin_size', '{}KB'.format(bin_size // 1024)) + # start the test + # check if test server is avilable + test_server_available = is_test_server_available() + # Skip the test if the server test server (http2.golang.org) is not available at the moment. + if test_server_available: + dut1.start_app() + # check for connection + dut1.expect('Connection done', timeout=30) + # check for echo response + dut1.expect('[echo-response] HELLO WORLD', timeout=30) + dut1.expect('[echo-response] Frame fully received') + dut1.expect('[echo-response] Stream Closed') + # check for get response + dut1.expect('[get-response] Frame fully received') + else: + Utility.console_log('test server \"{0}\" is not available at the moment.\nSkipping the test with status = success.'.format(TEST_SERVER)) + + +if __name__ == '__main__': + test_examples_protocol_http2_request() # pylint: disable=no-value-for-parameter diff --git a/examples/protocols/http2_request/sdkconfig.ci b/examples/protocols/http2_request/sdkconfig.ci new file mode 100644 index 0000000000..42f4b389e1 --- /dev/null +++ b/examples/protocols/http2_request/sdkconfig.ci @@ -0,0 +1,11 @@ +CONFIG_ESP32_SPIRAM_SUPPORT=y +CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y diff --git a/examples/protocols/http_request/example_test.py b/examples/protocols/http_request/example_test.py new file mode 100644 index 0000000000..3c10c11949 --- /dev/null +++ b/examples/protocols/http_request/example_test.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# +# Copyright 2021 Espressif Systems (Shanghai) CO LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import re + +import tiny_test_fw +import ttfw_idf + + +@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') +def test_examples_protocol_http_request(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument + """ + steps: | + 1. join AP + 2. connect to example.com + 3. check conneciton success + """ + dut1 = env.get_dut('http_request', 'examples/protocols/http_request', dut_class=ttfw_idf.ESP32DUT) + # check and log bin size + binary_file = os.path.join(dut1.app.binary_path, 'http-request.bin') + bin_size = os.path.getsize(binary_file) + ttfw_idf.log_performance('http_request_bin_size', '{}KB'.format(bin_size // 1024)) + # start test + dut1.start_app() + dut1.expect(re.compile(r'DNS lookup succeeded.')) + # check if connected or not + dut1.expect(' ... connected', timeout=60) + dut1.expect(' ... socket send success') + dut1.expect(' ... set socket receiving timeout success') + # check server response + dut1.expect(re.compile(r'HTTP/1.0 200 OK')) + # read from the socket completed + dut1.expect('... done reading from socket. Last read return=0 errno=128') + dut1.expect(re.compile(r'(\d)...')) + + +if __name__ == '__main__': + test_examples_protocol_http_request() # pylint: disable=no-value-for-parameter diff --git a/examples/protocols/http_request/sdkconfig.ci b/examples/protocols/http_request/sdkconfig.ci new file mode 100644 index 0000000000..539fa3b43d --- /dev/null +++ b/examples/protocols/http_request/sdkconfig.ci @@ -0,0 +1,9 @@ +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y diff --git a/examples/protocols/http_server/file_serving/http_server_file_serving_test.py b/examples/protocols/http_server/file_serving/http_server_file_serving_test.py new file mode 100644 index 0000000000..690b84c9c6 --- /dev/null +++ b/examples/protocols/http_server/file_serving/http_server_file_serving_test.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +# +# Copyright 2021 Espressif Systems (Shanghai) CO LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import hashlib +import http.client +import os +import re + +import tiny_test_fw +import ttfw_idf +from idf_http_server_test import adder as client +from tiny_test_fw import Utility + + +@ttfw_idf.idf_example_test(env_tag='Example_WIFI') +def test_examples_protocol_http_server_file_serving(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument + # Acquire DUT + dut1 = env.get_dut('http file_serving', 'examples/protocols/http_server/file_serving', dut_class=ttfw_idf.ESP32DUT) + + # Get binary file + binary_file = os.path.join(dut1.app.binary_path, 'file_server.bin') + bin_size = os.path.getsize(binary_file) + ttfw_idf.log_performance('file_server_bin_size', '{}KB'.format(bin_size // 1024)) + Utility.console_log('Erasing the flash on the chip') + # erase the flash + dut1.erase_flash() + # Upload binary and start testing + Utility.console_log('Starting http file serving simple test app') + dut1.start_app() + + # Parse IP address of STA + Utility.console_log('Waiting to connect with AP') + got_ip = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)'), timeout=30)[0] + # Expected logs + dut1.expect('Initializing SPIFFS', timeout=30) + got_port = dut1.expect(re.compile(r"Starting HTTP Server on port: '(\d+)'"), timeout=30)[0] + Utility.console_log('Got IP : ' + got_ip) + Utility.console_log('Got Port : ' + got_port) + + # Run test script + conn = client.start_session(got_ip, got_port) + + # upload a file onto the server + upload_data = 'Test data to be sent to the server' + + upload_file_name = 'example.txt' + upload_file_hash = hashlib.md5(upload_data.encode('UTF-8')) + upload_file_digest = upload_file_hash.digest() + Utility.console_log('\nTesting the uploading of file on the file server') + client.postreq(conn, '/upload/' + str(upload_file_name), upload_data) + + try: + dut1.expect('File reception complete', timeout=10) + except Exception: + Utility.console_log('Failed the test to upload file on the file server') + raise + Utility.console_log('Passed the test to uploaded file on the file server') + + # Download the uploaded file from the file server + Utility.console_log("\nTesting for Download of \"existing\" file from the file server") + + download_data = client.getreq(conn, '/' + str(upload_file_name)) + + try: + dut1.expect('File sending complete', timeout=10) + except Exception: + Utility.console_log('Failed the test to download existing file from the file server') + raise + Utility.console_log('Passed the test to downloaded existing file from the file server') + + download_file_hash = hashlib.md5(download_data) + download_file_digest = download_file_hash.digest() + + if download_file_digest != upload_file_digest: + raise RuntimeError('The md5 hash of the downloaded file does not match with that of the uploaded file') + + # Upload existing file on the file server + Utility.console_log("\nTesting the upload of \"already existing\" file on the file server") + client.postreq(conn, '/upload/' + str(upload_file_name), data=None) + try: + dut1.expect('File already exists : /spiffs/' + str(upload_file_name), timeout=10) + except Exception: + Utility.console_log('Failed the test for uploading existing file on the file server') + raise + Utility.console_log('Passed the test for uploading existing file on the file server') + # Previous URI was an invalid URI so the server should have closed the connection. + # Trying to send request to the server + try: + client.getreq(conn, '/') + except http.client.RemoteDisconnected: + # It is correct behavior that the connection was closed by the server + pass + except Exception: + Utility.console_log('Connection was not closed successfully by the server after last invalid URI') + raise + + conn = client.start_session(got_ip, got_port) + # Delete the existing file from the file server + Utility.console_log("\nTesting the deletion of \"existing\" file on the file server") + client.postreq(conn, '/delete/' + str(upload_file_name), data=None) + try: + dut1.expect('Deleting file : /' + str(upload_file_name), timeout=10) + except Exception: + Utility.console_log('Failed the test for deletion of existing file on the file server') + raise + Utility.console_log('Passed the test for deletion of existing file on the file server') + + conn = client.start_session(got_ip, got_port) + # Try to delete non existing file from the file server + Utility.console_log("\nTesting the deletion of \"non existing\" file on the file server") + client.postreq(conn, '/delete/' + str(upload_file_name), data=None) + try: + dut1.expect('File does not exist : /' + str(upload_file_name), timeout=10) + except Exception: + Utility.console_log('Failed the test for deleting non existing file on the file server') + raise + Utility.console_log('Passed the test for deleting non existing file on the file server') + + conn = client.start_session(got_ip, got_port) + # Try to download non existing file from the file server + Utility.console_log("\nTesting for Download of \"non existing\" file from the file server") + + download_data = client.getreq(conn, '/' + str(upload_file_name)) + + try: + dut1.expect('Failed to stat file : /spiffs/' + str(upload_file_name), timeout=10) + except Exception: + Utility.console_log('Failed the test to download non existing file from the file server') + raise + Utility.console_log('Passed the test to downloaded non existing file from the file server') + + +if __name__ == '__main__': + test_examples_protocol_http_server_file_serving() # pylint: disable=no-value-for-parameter diff --git a/examples/protocols/http_server/file_serving/main/file_server.c b/examples/protocols/http_server/file_serving/main/file_server.c index 878fdab4d0..021749ae86 100644 --- a/examples/protocols/http_server/file_serving/main/file_server.c +++ b/examples/protocols/http_server/file_serving/main/file_server.c @@ -475,7 +475,7 @@ esp_err_t start_file_server(const char *base_path) * target URIs which match the wildcard scheme */ config.uri_match_fn = httpd_uri_match_wildcard; - ESP_LOGI(TAG, "Starting HTTP Server"); + ESP_LOGI(TAG, "Starting HTTP Server on port: '%d'", config.server_port); if (httpd_start(&server, &config) != ESP_OK) { ESP_LOGE(TAG, "Failed to start file server!"); return ESP_FAIL; diff --git a/examples/protocols/http_server/file_serving/sdkconfig.ci b/examples/protocols/http_server/file_serving/sdkconfig.ci index a34935d196..b9bb0c0a5d 100644 --- a/examples/protocols/http_server/file_serving/sdkconfig.ci +++ b/examples/protocols/http_server/file_serving/sdkconfig.ci @@ -1,3 +1,3 @@ -CONFIG_EXAMPLE_MOUNT_SD_CARD=y -CONFIG_EXAMPLE_FORMAT_IF_MOUNT_SDCARD_FAILED=y -CONFIG_EXAMPLE_USE_SDMMC_HOST=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv" diff --git a/examples/protocols/http_server/file_serving/sdkconfig.ci.sdcard b/examples/protocols/http_server/file_serving/sdkconfig.ci.sdcard new file mode 100644 index 0000000000..a34935d196 --- /dev/null +++ b/examples/protocols/http_server/file_serving/sdkconfig.ci.sdcard @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_MOUNT_SD_CARD=y +CONFIG_EXAMPLE_FORMAT_IF_MOUNT_SDCARD_FAILED=y +CONFIG_EXAMPLE_USE_SDMMC_HOST=y diff --git a/examples/protocols/http_server/ws_echo_server/main/ws_echo_server.c b/examples/protocols/http_server/ws_echo_server/main/ws_echo_server.c index 03e810f73d..cac6365045 100644 --- a/examples/protocols/http_server/ws_echo_server/main/ws_echo_server.c +++ b/examples/protocols/http_server/ws_echo_server/main/ws_echo_server.c @@ -72,6 +72,7 @@ static esp_err_t echo_handler(httpd_req_t *req) return ESP_OK; } httpd_ws_frame_t ws_pkt; + uint8_t *buf = NULL; memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t)); ws_pkt.type = HTTPD_WS_TYPE_TEXT; /* Set max_len = 0 to get the frame len */ @@ -81,25 +82,27 @@ static esp_err_t echo_handler(httpd_req_t *req) return ret; } ESP_LOGI(TAG, "frame len is %d", ws_pkt.len); - /* ws_pkt.len + 1 is for NULL termination as we are expecting a string */ - uint8_t *buf = calloc(1, ws_pkt.len + 1); - if (buf == NULL) { - ESP_LOGE(TAG, "Failed to calloc memory for buf"); - return ESP_ERR_NO_MEM; + if (ws_pkt.len) { + /* ws_pkt.len + 1 is for NULL termination as we are expecting a string */ + buf = calloc(1, ws_pkt.len + 1); + if (buf == NULL) { + ESP_LOGE(TAG, "Failed to calloc memory for buf"); + return ESP_ERR_NO_MEM; + } + ws_pkt.payload = buf; + /* Set max_len = ws_pkt.len to get the frame payload */ + ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "httpd_ws_recv_frame failed with %d", ret); + free(buf); + return ret; + } + ESP_LOGI(TAG, "Got packet with message: %s", ws_pkt.payload); } - ws_pkt.payload = buf; - /* Set max_len = ws_pkt.len to get the frame payload */ - ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "httpd_ws_recv_frame failed with %d", ret); - return ret; - } - ESP_LOGI(TAG, "Got packet with message: %s", ws_pkt.payload); ESP_LOGI(TAG, "Packet type: %d", ws_pkt.type); if (ws_pkt.type == HTTPD_WS_TYPE_TEXT && strcmp((char*)ws_pkt.payload,"Trigger async") == 0) { free(buf); - buf = NULL; return trigger_async_send(req->handle, req); } @@ -108,7 +111,6 @@ static esp_err_t echo_handler(httpd_req_t *req) ESP_LOGE(TAG, "httpd_ws_send_frame failed with %d", ret); } free(buf); - buf = NULL; return ret; } diff --git a/examples/protocols/https_mbedtls/example_test.py b/examples/protocols/https_mbedtls/example_test.py new file mode 100644 index 0000000000..41f151e30d --- /dev/null +++ b/examples/protocols/https_mbedtls/example_test.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# +# Copyright 2021 Espressif Systems (Shanghai) CO LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import re + +import tiny_test_fw +import ttfw_idf +from tiny_test_fw import Utility + + +@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') +def test_examples_protocol_https_mbedtls(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument + """ + steps: | + 1. join AP + 2. connect to www.howsmyssl.com:443 + 3. send http request + """ + dut1 = env.get_dut('https_mbedtls', 'examples/protocols/https_mbedtls', dut_class=ttfw_idf.ESP32DUT) + # check and log bin size + binary_file = os.path.join(dut1.app.binary_path, 'https-mbedtls.bin') + bin_size = os.path.getsize(binary_file) + ttfw_idf.log_performance('https_mbedtls_bin_size', '{}KB'.format(bin_size // 1024)) + # start test + dut1.start_app() + dut1.expect('Connected.', timeout=30) + Utility.console_log('TCP connection established with the server\n performing SSL/TLS handshake') + dut1.expect('Performing the SSL/TLS handshake...') + dut1.expect('Certificate verified.') + Utility.console_log('SSL/TLS handshake successful') + dut1.expect('Writing HTTP request...') + dut1.expect('Reading HTTP response...') + dut1.expect(re.compile(r'Completed (\d) requests')) + + +if __name__ == '__main__': + test_examples_protocol_https_mbedtls() # pylint: disable=no-value-for-parameter diff --git a/examples/protocols/https_mbedtls/sdkconfig.ci b/examples/protocols/https_mbedtls/sdkconfig.ci new file mode 100644 index 0000000000..42f4b389e1 --- /dev/null +++ b/examples/protocols/https_mbedtls/sdkconfig.ci @@ -0,0 +1,11 @@ +CONFIG_ESP32_SPIRAM_SUPPORT=y +CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y diff --git a/examples/protocols/https_server/simple/example_test.py b/examples/protocols/https_server/simple/example_test.py new file mode 100644 index 0000000000..d6385451b8 --- /dev/null +++ b/examples/protocols/https_server/simple/example_test.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# +# Copyright 2021 Espressif Systems (Shanghai) CO LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import http.client +import os +import re +import ssl + +import tiny_test_fw +import ttfw_idf +from tiny_test_fw import Utility + +server_cert_pem = '-----BEGIN CERTIFICATE-----\n'\ + 'MIIDKzCCAhOgAwIBAgIUBxM3WJf2bP12kAfqhmhhjZWv0ukwDQYJKoZIhvcNAQEL\n'\ + 'BQAwJTEjMCEGA1UEAwwaRVNQMzIgSFRUUFMgc2VydmVyIGV4YW1wbGUwHhcNMTgx\n'\ + 'MDE3MTEzMjU3WhcNMjgxMDE0MTEzMjU3WjAlMSMwIQYDVQQDDBpFU1AzMiBIVFRQ\n'\ + 'UyBzZXJ2ZXIgZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n'\ + 'ALBint6nP77RCQcmKgwPtTsGK0uClxg+LwKJ3WXuye3oqnnjqJCwMEneXzGdG09T\n'\ + 'sA0SyNPwrEgebLCH80an3gWU4pHDdqGHfJQa2jBL290e/5L5MB+6PTs2NKcojK/k\n'\ + 'qcZkn58MWXhDW1NpAnJtjVniK2Ksvr/YIYSbyD+JiEs0MGxEx+kOl9d7hRHJaIzd\n'\ + 'GF/vO2pl295v1qXekAlkgNMtYIVAjUy9CMpqaQBCQRL+BmPSJRkXBsYk8GPnieS4\n'\ + 'sUsp53DsNvCCtWDT6fd9D1v+BB6nDk/FCPKhtjYOwOAZlX4wWNSZpRNr5dfrxKsb\n'\ + 'jAn4PCuR2akdF4G8WLUeDWECAwEAAaNTMFEwHQYDVR0OBBYEFMnmdJKOEepXrHI/\n'\ + 'ivM6mVqJgAX8MB8GA1UdIwQYMBaAFMnmdJKOEepXrHI/ivM6mVqJgAX8MA8GA1Ud\n'\ + 'EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADiXIGEkSsN0SLSfCF1VNWO3\n'\ + 'emBurfOcDq4EGEaxRKAU0814VEmU87btIDx80+z5Dbf+GGHCPrY7odIkxGNn0DJY\n'\ + 'W1WcF+DOcbiWoUN6DTkAML0SMnp8aGj9ffx3x+qoggT+vGdWVVA4pgwqZT7Ybntx\n'\ + 'bkzcNFW0sqmCv4IN1t4w6L0A87ZwsNwVpre/j6uyBw7s8YoJHDLRFT6g7qgn0tcN\n'\ + 'ZufhNISvgWCVJQy/SZjNBHSpnIdCUSJAeTY2mkM4sGxY0Widk8LnjydxZUSxC3Nl\n'\ + 'hb6pnMh3jRq4h0+5CZielA4/a+TdrNPv/qok67ot/XJdY3qHCCd8O2b14OVq9jo=\n'\ + '-----END CERTIFICATE-----\n' + +success_response = '