From e3cdbaf26eb5a8eaa95c364bd8bf9a0535cfb01e Mon Sep 17 00:00:00 2001 From: "Jonathan M. Henson" Date: Fri, 27 Mar 2020 20:16:55 -0700 Subject: [PATCH] apply http stream activation refactor. (#136) apply http stream activation refactor. Numerous bug fixes. Reworked Mac OS trust store evaluation. --- .github/workflows/ci.yml | 10 +++--- .github/workflows/lint.yml | 3 +- .gitignore | 4 +-- aws-common-runtime/aws-c-auth | 2 +- aws-common-runtime/aws-c-common | 2 +- aws-common-runtime/aws-c-compression | 2 +- aws-common-runtime/aws-c-http | 2 +- aws-common-runtime/aws-c-io | 2 +- aws-common-runtime/aws-c-mqtt | 2 +- aws-common-runtime/s2n | 2 +- awscrt/http.py | 5 ++- elasticurl.py | 1 + setup.py | 2 +- source/http.h | 2 ++ source/http_stream.c | 45 +++++++++++++++------------ source/module.c | 1 + test/appexit_http.py | 1 + test/resources/ca.crt | 24 ++++++++++++++ test/resources/crt.unittests.crt | 24 ++++++++++++++ test/resources/crt.unittests.key | 27 ++++++++++++++++ test/resources/crt.unittests.p12 | Bin 0 -> 2621 bytes test/resources/unittests.crt | 23 -------------- test/resources/unittests.csr | 18 ----------- test/resources/unittests.key | 27 ---------------- test/resources/unittests.p12 | Bin 2581 -> 0 bytes test/test_http_client.py | 31 +++++++++++++++--- test/test_io.py | 6 ++-- 27 files changed, 156 insertions(+), 112 deletions(-) create mode 100644 test/resources/ca.crt create mode 100644 test/resources/crt.unittests.crt create mode 100644 test/resources/crt.unittests.key create mode 100644 test/resources/crt.unittests.p12 delete mode 100755 test/resources/unittests.crt delete mode 100755 test/resources/unittests.csr delete mode 100755 test/resources/unittests.key delete mode 100644 test/resources/unittests.p12 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3014c47e5..953ae9618 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: - '!master' env: - BUILDER_VERSION: v0.5.3 + BUILDER_VERSION: v0.6.0 BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net PACKAGE_NAME: aws-crt-python LINUX_BASE_IMAGE: ubuntu-16-x64 @@ -79,7 +79,7 @@ jobs: steps: - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | - python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" + python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/releases/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" python builder.pyz build -p ${{ env.PACKAGE_NAME }} windows-vc14: @@ -96,15 +96,15 @@ jobs: spectre: true - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | - python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" - python builder.pyz -p ${{ env.PACKAGE_NAME }} build + python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/releases/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" + python builder.pyz build -p ${{ env.PACKAGE_NAME }} osx: runs-on: macos-latest steps: - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | - python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" + python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/releases/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" chmod a+x builder ./builder build -p ${{ env.PACKAGE_NAME }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ac6649145..1f30c7736 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -27,5 +27,6 @@ jobs: - name: Build and Test run: | python3 -m pip install --upgrade setuptools + python3 -m pip install --upgrade wheel python3 -m pip install --upgrade autopep8 - python3 -m autopep8 --exit-code --diff --recursive awscrt test .builder setup.py \ No newline at end of file + python3 -m autopep8 --exit-code --diff --recursive awscrt test .builder setup.py diff --git a/.gitignore b/.gitignore index 96bd43a3e..81557d132 100644 --- a/.gitignore +++ b/.gitignore @@ -525,9 +525,9 @@ ASALocalRun/ # End of https://www.gitignore.io/api/git,c++,cmake,python,visualstudio,visualstudiocode # credentials -*.key +.key *.pem -*.crt +.crt # deps from build-deps.sh deps/ diff --git a/aws-common-runtime/aws-c-auth b/aws-common-runtime/aws-c-auth index 85dd9e394..479187b39 160000 --- a/aws-common-runtime/aws-c-auth +++ b/aws-common-runtime/aws-c-auth @@ -1 +1 @@ -Subproject commit 85dd9e39474a2b9e04f41e9feabb589a4bec20ca +Subproject commit 479187b39ddc7ae8b67d782b444ceb64fc2ff1c8 diff --git a/aws-common-runtime/aws-c-common b/aws-common-runtime/aws-c-common index 4a6ae22c7..6f0787f0c 160000 --- a/aws-common-runtime/aws-c-common +++ b/aws-common-runtime/aws-c-common @@ -1 +1 @@ -Subproject commit 4a6ae22c728bb69fbd462159542bf5013f965575 +Subproject commit 6f0787f0c567326a5313188af7cb3b4dbfef1a24 diff --git a/aws-common-runtime/aws-c-compression b/aws-common-runtime/aws-c-compression index c7e477bf6..4b32a9b8b 160000 --- a/aws-common-runtime/aws-c-compression +++ b/aws-common-runtime/aws-c-compression @@ -1 +1 @@ -Subproject commit c7e477bf6ab7df17cdad223300541fe3aa978f35 +Subproject commit 4b32a9b8bdf07698fd080bade472a5e135abb70a diff --git a/aws-common-runtime/aws-c-http b/aws-common-runtime/aws-c-http index e5386127c..f5096cab2 160000 --- a/aws-common-runtime/aws-c-http +++ b/aws-common-runtime/aws-c-http @@ -1 +1 @@ -Subproject commit e5386127cd43b5aea476500b9a38d7e9b72b82f7 +Subproject commit f5096cab294d201bc4a217ed5679f912baa14684 diff --git a/aws-common-runtime/aws-c-io b/aws-common-runtime/aws-c-io index 44eabdfc0..60a451a6a 160000 --- a/aws-common-runtime/aws-c-io +++ b/aws-common-runtime/aws-c-io @@ -1 +1 @@ -Subproject commit 44eabdfc0f0586e221e1a5eb37253ec1e90ebd1c +Subproject commit 60a451a6a7269f1f99718950cd34befcf7e8a096 diff --git a/aws-common-runtime/aws-c-mqtt b/aws-common-runtime/aws-c-mqtt index 5ed5ee07e..b578a68ca 160000 --- a/aws-common-runtime/aws-c-mqtt +++ b/aws-common-runtime/aws-c-mqtt @@ -1 +1 @@ -Subproject commit 5ed5ee07e3be9515a30a6ff47a43ab7b9144ef3a +Subproject commit b578a68cab067513cc9f2ecbc189c2a1a0755a57 diff --git a/aws-common-runtime/s2n b/aws-common-runtime/s2n index e460a33a1..bffd9b768 160000 --- a/aws-common-runtime/s2n +++ b/aws-common-runtime/s2n @@ -1 +1 @@ -Subproject commit e460a33a15dd0a786c2ce82d3d7bb8c64f4feb96 +Subproject commit bffd9b768d6051bce4badfed1ee73bd983c2b260 diff --git a/awscrt/http.py b/awscrt/http.py index 5ee1d7780..5d290d3a9 100644 --- a/awscrt/http.py +++ b/awscrt/http.py @@ -174,12 +174,15 @@ def __init__(self, connection, request, on_response=None, on_body=None): self._on_response_cb = on_response self._response_status_code = None - _awscrt.http_client_stream_new(self, connection, request) + self._binding = _awscrt.http_client_stream_new(self, connection, request) @property def response_status_code(self): return self._response_status_code + def activate(self): + _awscrt.http_client_stream_activate(self) + def _on_response(self, status_code, name_value_pairs): self._response_status_code = status_code diff --git a/elasticurl.py b/elasticurl.py index 14e756b21..5e49b7773 100644 --- a/elasticurl.py +++ b/elasticurl.py @@ -240,6 +240,7 @@ def response_received_cb(http_stream, status_code, headers, **kwargs): # make the request stream = connection.request(request, response_received_cb, on_incoming_body) +stream.activate() # wait until the full response is finished stream.completion_future.result() diff --git a/setup.py b/setup.py index cf9e9b5fd..43e92de83 100644 --- a/setup.py +++ b/setup.py @@ -244,7 +244,7 @@ def awscrt_ext(): setuptools.setup( name="awscrt", - version="0.5.11", + version="0.5.12", author="Amazon Web Services, Inc", author_email="aws-sdk-common-runtime@amazon.com", description="A common runtime for AWS Python projects", diff --git a/source/http.h b/source/http.h index 288d8e135..2f6d479dc 100644 --- a/source/http.h +++ b/source/http.h @@ -48,6 +48,8 @@ PyObject *aws_py_http_client_connection_new(PyObject *self, PyObject *args); PyObject *aws_py_http_client_stream_new(PyObject *self, PyObject *args); +PyObject *aws_py_http_client_stream_activate(PyObject *self, PyObject *args); + /* Create capsule around new request-style aws_http_message struct */ PyObject *aws_py_http_message_new_request(PyObject *self, PyObject *args); diff --git a/source/http_stream.c b/source/http_stream.c index 8acb7584a..b2da0ad50 100644 --- a/source/http_stream.c +++ b/source/http_stream.c @@ -27,7 +27,7 @@ struct http_stream_binding { /* Weak reference proxy to python self. * NOTE: The python self is forced to stay alive until on_complete fires. - * We do this by INCREFing when setup is successful, and DECREFing when on_complete fires. */ + * We do this by INCREFing when activate() is called, and DECREFing when on_complete fires. */ PyObject *self_proxy; /* Buffer up headers as they come in via repeated on_headers callacks. @@ -100,9 +100,6 @@ static int s_on_incoming_header_block_done( return AWS_OP_ERR; /* Python has shut down. Nothing matters anymore, but don't crash */ } - /* Set this just in case callback fires before aws_http_connection_make_request() has even returned */ - stream->native = native_stream; - /* Build up a list of (name,value) tuples, * extracting values from buffer of [name,value,name,value,...] null-terminated strings */ PyObject *header_list = PyList_New(num_headers); @@ -204,9 +201,6 @@ static void s_on_stream_complete(struct aws_http_stream *native_stream, int erro return; /* Python has shut down. Nothing matters anymore, but don't crash */ } - /* Set this just in case callback fires before aws_http_connection_make_request() has even returned */ - stream->native = native_stream; - PyObject *result = PyObject_CallMethod(stream->self_proxy, "_on_complete", "(i)", error_code); if (result) { Py_DECREF(result); @@ -289,12 +283,6 @@ PyObject *aws_py_http_client_stream_new(PyObject *self, PyObject *args) { goto error; } - /* NOTE: Callbacks might start firing before aws_http_connection_make_request() can even return. - * Therefore, we set `HttpClientStream._binding = capsule` now, instead of returning capsule to caller */ - if (PyObject_SetAttrString(py_stream, "_binding", capsule) == -1) { - goto error; - } - struct aws_http_make_request_options request_options = { .self_size = sizeof(request_options), .request = native_request, @@ -311,13 +299,7 @@ PyObject *aws_py_http_client_stream_new(PyObject *self, PyObject *args) { goto error; } - /* From hereon, nothing will fail */ - - /* Force python self to stay alive until on_complete callback */ - Py_INCREF(py_stream); - - Py_DECREF(capsule); - Py_RETURN_NONE; + return capsule; error: if (capsule) { @@ -327,3 +309,26 @@ PyObject *aws_py_http_client_stream_new(PyObject *self, PyObject *args) { } return NULL; } + +PyObject *aws_py_http_client_stream_activate(PyObject *self, PyObject *args) { + (void)self; + + PyObject *py_stream = NULL; + if (!PyArg_ParseTuple(args, "O", &py_stream)) { + return NULL; + } + + struct aws_http_stream *native_stream = aws_py_get_http_stream(py_stream); + if (!native_stream) { + return NULL; + } + + if (aws_http_stream_activate(native_stream)) { + return PyErr_AwsLastError(); + } + + /* Force python self to stay alive until on_complete callback */ + Py_INCREF(py_stream); + + Py_RETURN_NONE; +} diff --git a/source/module.c b/source/module.c index f3f5eddc0..e8f99dfc3 100644 --- a/source/module.c +++ b/source/module.c @@ -528,6 +528,7 @@ static PyMethodDef s_module_methods[] = { AWS_PY_METHOD_DEF(http_connection_is_open, METH_VARARGS), AWS_PY_METHOD_DEF(http_client_connection_new, METH_VARARGS), AWS_PY_METHOD_DEF(http_client_stream_new, METH_VARARGS), + AWS_PY_METHOD_DEF(http_client_stream_activate, METH_VARARGS), AWS_PY_METHOD_DEF(http_message_new_request, METH_VARARGS), AWS_PY_METHOD_DEF(http_message_get_request_method, METH_VARARGS), AWS_PY_METHOD_DEF(http_message_set_request_method, METH_VARARGS), diff --git a/test/appexit_http.py b/test/appexit_http.py index c8ee92c90..d30726034 100644 --- a/test/appexit_http.py +++ b/test/appexit_http.py @@ -108,6 +108,7 @@ def on_incoming_body(http_stream, chunk): receiving_body_event.set() http_stream = http_connection.request(request, on_body=on_incoming_body) + http_stream.activate() set_stage(Stage.HttpStreamStart) # HttpStreamReceivingBodyMainThread: Exit from main thread while receiving body diff --git a/test/resources/ca.crt b/test/resources/ca.crt new file mode 100644 index 000000000..cf4d9cbae --- /dev/null +++ b/test/resources/ca.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEADCCAugCCQCtEgLxN71/TDANBgkqhkiG9w0BAQsFADCBwTELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxITAfBgNV +BAoMGEFtYXpvbiBXZWIgU2VydmljZXMsIEluYzEbMBkGA1UECwwSQXdzIGNvbW1v +biBydW50aW1lMRkwFwYDVQQDDBBwa2kuaXMudGhlLndvcnN0MTAwLgYJKoZIhvcN +AQkBFiFhd3Mtc2RrLWNvbW1vbi1ydW50aW1lQGFtYXpvbi5jb20wHhcNMjAwMzI4 +MDMwNTI4WhcNNDcwODE0MDMwNTI4WjCBwTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxITAfBgNVBAoMGEFtYXpvbiBX +ZWIgU2VydmljZXMsIEluYzEbMBkGA1UECwwSQXdzIGNvbW1vbiBydW50aW1lMRkw +FwYDVQQDDBBwa2kuaXMudGhlLndvcnN0MTAwLgYJKoZIhvcNAQkBFiFhd3Mtc2Rr +LWNvbW1vbi1ydW50aW1lQGFtYXpvbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDCUFDcwnUkyK/7M2RFXmWGryCfUM/Y4sPV5dm8Q52wZcPATaAO +Ucnh03qhPbxHyiF56EYNxF6tIXqMifO6CyiC1Dcvkq4yYVAYBH2GpwpscBraVrNX +KUeBZVv3tAFIFWMgGSz4SYB+6pdTEHxFA3iZjH4WIMgMMAZWiz7ktqz3b+OqOSHT +i89rShb0QVrAdHzSeKXwyRA5X4vTMLQEFwNU/6D57+1IdSlo0svdrF70GYuxpR7G +2VOIZqbVSyoL0dkuFCh1XjbuIyvNqshWXV644BtEwoP5P36tSONUiLbhLaR++pO0 +RB2WgniJSBGUe0gSfl9djaaAg7KdbfIoIosRAgMBAAEwDQYJKoZIhvcNAQELBQAD +ggEBAKdg2Z2DL2sow8ckf90uqrwNpuCKlydg1XGS2hBSWyhiFd3Ztj9pRKdpsjA8 +mF9x4U+WwmekzV6CZKXPlO5qlCvU1h7dFVRHZtG4O1bIRQNcgycoiL7Q9Sp+crP1 +Y8pF1vjCuoMlGFSSMXazRVXcJ/FVeBD4rS8AmyR6B4W8fykVQAYNcH4gXwQ0WP7O +bjJrI1kTB+3JQU1KHHDTi3/gMvCUanzDc8HJ0CEpch8AY9S4suAYJmM6HpWzczoy +jUH/yQT0ehur9wRy566BwUdTVfi+2cQQfYNPqs9iJdYZ7loSBDRH7vO7ivE4Y/Zz +ilbJgpP/vnoxwEVSYD0W+1ctaEg= +-----END CERTIFICATE----- diff --git a/test/resources/crt.unittests.crt b/test/resources/crt.unittests.crt new file mode 100644 index 000000000..fae429d90 --- /dev/null +++ b/test/resources/crt.unittests.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID+TCCAuECCQDufZzOyUBvoTANBgkqhkiG9w0BAQUFADCBwTELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxITAfBgNV +BAoMGEFtYXpvbiBXZWIgU2VydmljZXMsIEluYzEbMBkGA1UECwwSQXdzIGNvbW1v +biBydW50aW1lMRkwFwYDVQQDDBBwa2kuaXMudGhlLndvcnN0MTAwLgYJKoZIhvcN +AQkBFiFhd3Mtc2RrLWNvbW1vbi1ydW50aW1lQGFtYXpvbi5jb20wHhcNMjAwMzI4 +MDMwODU3WhcNMzAwMzI2MDMwODU3WjCBujELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxITAfBgNVBAoMGEFtYXpvbiBX +ZWIgU2VydmljZXMsIEluYzEbMBkGA1UECwwSQXdzIGNvbW1vbiBydW50aW1lMRIw +EAYDVQQDDAlsb2NhbGhvc3QxMDAuBgkqhkiG9w0BCQEWIWF3cy1zZGstY29tbW9u +LXJ1bnRpbWVAYW1hem9uLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAJ/WE+6CF8V/UJ4uL79LvnEfXWlfUA/KMiopiDJOKyn4dP4McKSqzZsuaiBK +XJcT1O25MRIdyacHht0+c4+zlLChqhiGs5Ld1M+AHr5bA55dBojUfbPQJIN36TiH +SzyhvENn4XGK140HynhlW2omnnNoUEqNi45qJTgPy4+IqfH5e8zpiI9bs7GXcewz +PCNiX0mxeNq0wlyrCjfY35XY+fKCqo80kdJ6e12RM7+a2JO1BAiqhs0+TngNfXSP +eo5jdeC8GhREssR7/JVyB2yWDx5VDmdWAxDwWYy51t9MlsSLWXB2kA51NC8ER6YX +aFMwiU48G2xveaXp/0lVDR0ohD0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAOljE +Z5yomuomyQSzsmGc3gbGsSKY6waSTpns6A6teqEqi99Xcvxk6rpUjkqXavedpaEu +5CiLJQXbXLiqoz2aVKj4eN94R/PGXYHWZ3l8MXGpUssUyee6jveHLNclliHNfgyX +hecS7EAeGks88bY33RF5zh80TTurWs7Eaddw8CoxZmLPUFq+2SeMirxS2HVgjytV +ex/MS3XkWEvBcTpzZNYSP2H4nHlpzRtB/scRBf3rIcEuLiLyaRuvSZAkxrdFRnSa +tj1mArGWt9CRvRANL18TzhHTIxZkQ4gnxTXJHAWsqexQqucWSOblm9ouFkooetoO +TI4h04F8jszodmLKUA== +-----END CERTIFICATE----- diff --git a/test/resources/crt.unittests.key b/test/resources/crt.unittests.key new file mode 100644 index 000000000..2f7500bcf --- /dev/null +++ b/test/resources/crt.unittests.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAn9YT7oIXxX9Qni4vv0u+cR9daV9QD8oyKimIMk4rKfh0/gxw +pKrNmy5qIEpclxPU7bkxEh3JpweG3T5zj7OUsKGqGIazkt3Uz4AevlsDnl0GiNR9 +s9Akg3fpOIdLPKG8Q2fhcYrXjQfKeGVbaiaec2hQSo2LjmolOA/Lj4ip8fl7zOmI +j1uzsZdx7DM8I2JfSbF42rTCXKsKN9jfldj58oKqjzSR0np7XZEzv5rYk7UECKqG +zT5OeA19dI96jmN14LwaFESyxHv8lXIHbJYPHlUOZ1YDEPBZjLnW30yWxItZcHaQ +DnU0LwRHphdoUzCJTjwbbG95pen/SVUNHSiEPQIDAQABAoIBAQCC3+mGG+OXBT5f +pvXVrxGK0uHLzA1kQG1+9G7esf7J6PTyqAD79BdSf1jKg9j4o3ZwCHlTmixppdIa +Cm7ZNXQEhPsgBfu3wAfmt8N0nlWCMC2PkF41A7NCKsc+UBmc1dmvX7nLHKKOidiR +aHzHmEOZv8ouoWOqAuPi2ZwWNRLiW9gUw4xuCa13u8CJstrB83KqLN9qycfzzI0z +i1VjoxicQ5rvp/btTVAHNIfaNLdSP8pydO0Z9GuYn0HbtlTpPhTV+jE1iFwG9Ft1 +03kTv+6EtlbUeJohjYRtSXw7DkRGfzOuSFsZgLvn0bbbUCz3IfgV/5/eQrOMR4zQ +fxGDWc8BAoGBANO8AS0p8F3ooELhHEojo70SJHtGjfMnzZ/d3NYesSGnJ94I6c/t +7YkgWX9eYhgefCdHBou+OITMXenHMto9Oy5bVs85WRkbHryTzqMpgGLY1UdVH2IF +aSZXOUrz+WhXJq2VwIs/G2Y+0+xRYLaw1Sg+CsLY2tZnG2kFUXrSVuDhAoGBAMFA +fcuQhDE513ogK0aC2W6U8TaZOzlauNRmyUhp5o2jMxK7dfnsFkQ0g2slxIrNmNMN +RGFE9hg6WfOqprXwfZ2SqZ7u/M4c4yY3NShnfTQHua0CoDMZ3FYWeX0F2NtWwSTP +hN2O4bZPw9KGNV8AS5BF9XTd4A/RzZR2UNOXGqLdAoGAGPlJ4jvaIBl6HalTnuMJ +QxnKt8egopeFR1/x1keUePWwXB4NBft4Uv4/0CgfxdyCpFdaTE1JeVBpm1NlihxC +yLr5SEPpYG60d2Wvr8sLW51buqgtpXAh8OXE2jRgrI/q/fp11XbCEpNCh9MpZyMA +YVjACC9v0G4k64Q3EheRK8ECgYEAgOF8w5TmxFmZ/eWUVtsPHTORxuLcX3zEhUrj +dDrEOrObbSO+I2Yy11vaRUwTzqodAKv5bZFrOm837ExkEDSJ4duc6dTinqcfSi5J +cl/KXTfFub9ljY7ypiso7JtIq8co2l7XcldG6qo5o55D2867lkVB1KXgN0ypeRiL +AQHmDrUCgYEAvKFJYxA8j6we3xzKSKb627nodAjW4tX4ohJSaEwICm7YNUkC1Bfa +SD9O2fBm2mtLoX1h7vicmaOnZ8V4wf2JGYp2DgPBsZK8sxhi9xzGP7iYMpTMq2TM +KO9KBGl1MvZNdq7edqlSoqFX1XlPk21o+iHC3lm2w1njUWo4O/avzc8= +-----END RSA PRIVATE KEY----- diff --git a/test/resources/crt.unittests.p12 b/test/resources/crt.unittests.p12 new file mode 100644 index 0000000000000000000000000000000000000000..44ce31c336bdfaf4cb08fdca483e39e750a0ec57 GIT binary patch literal 2621 zcmV-D3c~d;f(khT0Ru3C3I7HODuzgg_YDCD0ic2j@C1Sh>@b1}=rDo=p9TpkhDe6@ z4FLxRpn?RDFoFb(0s#Opf&_&I2`Yw2hW8Bt2LUh~1_~;MNQU-CIZ4RiOF!JFe1haoxIK9UBbmApx>5B52j|7=NDN8sP0IR#i z(|`j)cQ4m|5%fv@tOU?ogZ^xcHcMa1313!BTIVk8lq9uYWkDDngQ> zhpN0@Ni1t^HnqgwbdF6l5iR-abI-qqk0O0C{LUcXlZ~*r32sawU66|B3|I*h5%)(g zelUtjH>1_y2F7U`Mu=MMm6Tj5KFg7?Ef_sq-wUEa&v}FLO9wOCDvdta3^Y--=ku-m z!!>fIEq*D9P@Hi|C-GkTDjacM$HS7SLdel!Zr)6S#}I)m3+kVrTOuQtxvK>E|04>* zlY(*)#w<4(K(ub9cckb%7n>32CkyrLv0%H&RSamDH%bDd!>FMuBb6{|<7T$haCw#N8jhVx3_7 z$U(M)_=Y)|!e)$3!L&`QCfaY;CV9dA@j8_?VOuj+=Hp-rh`77j-mX z;N4~gvdQ*lZXAjryvrBSyV+ncMpj~s$&Gn75 zzye0XeJl*OEtca{&v{smM)q-`CDm6X$8<6)m~Kd{q2nFg@ZlO^Sa+G{aCH<KJ zrAse)3|{R@Ld|=Gc6}Jwo4GN+&JW@l^(dR8Q8ASW%>m2gq-;VSasxqImYRY`$-fm= z`i|w`w?1fe*c*ZIJCgMEck!A@HXCGmyfr`*_+tcV7N>>$?r)pB_=Boi@gA+t*my

&LNQUe@gs9@~F`HVR~wA2&; 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 diff --git a/test/test_http_client.py b/test/test_http_client.py index d7dcac67f..15619235d 100644 --- a/test/test_http_client.py +++ b/test/test_http_client.py @@ -81,8 +81,8 @@ def _start_server(self, secure, http_1_0=False): self.server = HTTPServer((self.hostname, 0), TestRequestHandler) if secure: self.server.socket = ssl.wrap_socket(self.server.socket, - keyfile="test/resources/unittests.key", - certfile='test/resources/unittests.crt', + keyfile="test/resources/crt.unittests.key", + certfile='test/resources/crt.unittests.crt', server_side=True) self.port = self.server.server_address[1] @@ -100,7 +100,7 @@ def _stop_server(self): def _new_client_connection(self, secure, proxy_options=None): if secure: tls_ctx_opt = TlsContextOptions() - tls_ctx_opt.override_default_trust_store_from_path(None, 'test/resources/unittests.crt') + tls_ctx_opt.override_default_trust_store_from_path(None, 'test/resources/ca.crt') tls_ctx = ClientTlsContext(tls_ctx_opt) tls_conn_opt = tls_ctx.new_connection_options() tls_conn_opt.set_server_name(self.hostname) @@ -174,6 +174,7 @@ def _test_get(self, secure, proxy_options=None): request = HttpRequest('GET', '/' + test_asset_path) response = Response() stream = connection.request(request, response.on_response, response.on_body) + stream.activate() # wait for stream to complete stream_completion_result = stream.completion_future.result(self.timeout) @@ -204,6 +205,7 @@ def _test_shutdown_error(self, secure): request = HttpRequest('GET', '/') response = Response() stream = connection.request(request, response.on_response, response.on_body) + stream.activate() stream.completion_future.result(self.timeout) # Wait for server to hang up, which should be immediate since it's using HTTP/1.0 @@ -236,7 +238,7 @@ def _test_put(self, secure): request = HttpRequest('PUT', '/' + test_asset_path, headers, outgoing_body_stream) response = Response() http_stream = connection.request(request, response.on_response, response.on_body) - + http_stream.activate() # wait for stream to complete stream_completion_result = http_stream.completion_future.result(self.timeout) @@ -264,6 +266,7 @@ def _test_stream_lives_until_complete(self, secure): request = HttpRequest('GET', '/test/test_http_client.py') stream = connection.request(request) + stream.activate() completion_future = stream.completion_future # delete all local references @@ -281,6 +284,26 @@ def test_stream_lives_until_complete_http(self): def test_stream_lives_until_complete_https(self): self._test_stream_lives_until_complete(secure=True) + # If a stream is never activated, it should just clean itself up + def _test_stream_cleans_up_if_never_activated(self, secure): + self._start_server(secure) + + connection = self._new_client_connection(secure) + stream = connection.request(HttpRequest('GET', '/test/test_http_client.py')) + # note we do NOT activate the stream + + # delete local references, stream should clean itself up, connection should shut itself down + del stream + del connection + + self._stop_server() + + def test_stream_cleans_up_if_never_activated_http(self): + self._test_stream_cleans_up_if_never_activated(secure=False) + + def test_stream_cleans_up_if_never_activated_https(self): + self._test_stream_cleans_up_if_never_activated(secure=True) + @unittest.skipIf(PROXY_HOST is None, 'requires "proxyhost" and "proxyport" env vars') def test_proxy_http(self): proxy_options = HttpProxyOptions(host_name=PROXY_HOST, port=PROXY_PORT) diff --git a/test/test_io.py b/test/test_io.py index f6ef34f58..f8196d54a 100644 --- a/test/test_io.py +++ b/test/test_io.py @@ -56,12 +56,12 @@ def test_init_defaults(self): def test_with_mtls_from_path(self): opt = TlsContextOptions.create_client_with_mtls_from_path( - 'test/resources/unittests.crt', 'test/resources/unittests.key') + 'test/resources/crt.unittests.crt', 'test/resources/crt.unittests.key') ctx = ClientTlsContext(opt) def test_with_mtls_pkcs12(self): opt = TlsContextOptions.create_client_with_mtls_pkcs12( - 'test/resources/unittests.p12', '1234') + 'test/resources/crt.unittests.p12', '1234') ctx = ClientTlsContext(opt) def test_override_default_trust_store_dir(self): @@ -71,7 +71,7 @@ def test_override_default_trust_store_dir(self): def test_override_default_trust_store_file(self): opt = TlsContextOptions() - opt.override_default_trust_store_from_path(None, 'test/resources/unittests.crt') + opt.override_default_trust_store_from_path(None, 'test/resources/ca.crt') ctx = ClientTlsContext(opt)