From f6c49a7590a02d39a15297577b9ac2d30ed6ba20 Mon Sep 17 00:00:00 2001 From: tustha Date: Sun, 6 Apr 2025 08:46:34 +1000 Subject: [PATCH 1/4] Add Amazon private API gateway with private custom domain name configured with private SSL cert imported and managed by ACM --- apigw-private-cdn-acm/README.md | 114 ++ .../cfnresponse-1.1.5.dist-info/INSTALLER | 1 + .../cfnresponse-1.1.5.dist-info/LICENSE | 201 +++ .../cfnresponse-1.1.5.dist-info/METADATA | 39 + .../cfnresponse-1.1.5.dist-info/RECORD | 9 + .../cfnresponse-1.1.5.dist-info/REQUESTED | 0 .../cfnresponse-1.1.5.dist-info/WHEEL | 6 + .../cfnresponse-1.1.5.dist-info/top_level.txt | 1 + .../acm-certificate/cfnresponse/__init__.py | 47 + .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 1785 bytes .../acm-certificate/index.py | 76 + .../acm-certificate/rootCA.pem | 33 + .../acm-certificate/server.crt | 27 + .../acm-certificate/server.key | 28 + .../urllib3-2.3.0.dist-info/INSTALLER | 1 + .../urllib3-2.3.0.dist-info/METADATA | 154 ++ .../urllib3-2.3.0.dist-info/RECORD | 79 + .../urllib3-2.3.0.dist-info/WHEEL | 4 + .../licenses/LICENSE.txt | 21 + .../acm-certificate/urllib3/__init__.py | 211 +++ .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 7145 bytes .../_base_connection.cpython-313.pyc | Bin 0 -> 6988 bytes .../__pycache__/_collections.cpython-313.pyc | Bin 0 -> 22682 bytes .../_request_methods.cpython-313.pyc | Bin 0 -> 9982 bytes .../__pycache__/_version.cpython-313.pyc | Bin 0 -> 616 bytes .../__pycache__/connection.cpython-313.pyc | Bin 0 -> 36571 bytes .../connectionpool.cpython-313.pyc | Bin 0 -> 39141 bytes .../__pycache__/exceptions.cpython-313.pyc | Bin 0 -> 16919 bytes .../__pycache__/fields.cpython-313.pyc | Bin 0 -> 11628 bytes .../__pycache__/filepost.cpython-313.pyc | Bin 0 -> 3517 bytes .../__pycache__/poolmanager.cpython-313.pyc | Bin 0 -> 23665 bytes .../__pycache__/response.cpython-313.pyc | Bin 0 -> 51900 bytes .../urllib3/_base_connection.py | 165 +++ .../acm-certificate/urllib3/_collections.py | 479 ++++++ .../urllib3/_request_methods.py | 278 ++++ .../acm-certificate/urllib3/_version.py | 16 + .../acm-certificate/urllib3/connection.py | 1044 ++++++++++++++ .../acm-certificate/urllib3/connectionpool.py | 1178 +++++++++++++++ .../urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 212 bytes .../__pycache__/pyopenssl.cpython-313.pyc | Bin 0 -> 27963 bytes .../contrib/__pycache__/socks.cpython-313.pyc | Bin 0 -> 8431 bytes .../urllib3/contrib/emscripten/__init__.py | 16 + .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 922 bytes .../__pycache__/connection.cpython-313.pyc | Bin 0 -> 10532 bytes .../__pycache__/fetch.cpython-313.pyc | Bin 0 -> 28647 bytes .../__pycache__/request.cpython-313.pyc | Bin 0 -> 1488 bytes .../__pycache__/response.cpython-313.pyc | Bin 0 -> 12873 bytes .../urllib3/contrib/emscripten/connection.py | 255 ++++ .../emscripten/emscripten_fetch_worker.js | 110 ++ .../urllib3/contrib/emscripten/fetch.py | 708 +++++++++ .../urllib3/contrib/emscripten/request.py | 22 + .../urllib3/contrib/emscripten/response.py | 285 ++++ .../urllib3/contrib/pyopenssl.py | 554 +++++++ .../acm-certificate/urllib3/contrib/socks.py | 228 +++ .../acm-certificate/urllib3/exceptions.py | 327 +++++ .../acm-certificate/urllib3/fields.py | 341 +++++ .../acm-certificate/urllib3/filepost.py | 89 ++ .../acm-certificate/urllib3/http2/__init__.py | 53 + .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 1774 bytes .../__pycache__/connection.cpython-313.pyc | Bin 0 -> 17451 bytes .../http2/__pycache__/probe.cpython-313.pyc | Bin 0 -> 3809 bytes .../urllib3/http2/connection.py | 356 +++++ .../acm-certificate/urllib3/http2/probe.py | 87 ++ .../acm-certificate/urllib3/poolmanager.py | 637 ++++++++ .../acm-certificate/urllib3/py.typed | 2 + .../acm-certificate/urllib3/response.py | 1278 +++++++++++++++++ .../acm-certificate/urllib3/util/__init__.py | 42 + .../util/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 1025 bytes .../__pycache__/connection.cpython-313.pyc | Bin 0 -> 4755 bytes .../util/__pycache__/proxy.cpython-313.pyc | Bin 0 -> 1245 bytes .../util/__pycache__/request.cpython-313.pyc | Bin 0 -> 8258 bytes .../util/__pycache__/response.cpython-313.pyc | Bin 0 -> 2924 bytes .../util/__pycache__/retry.cpython-313.pyc | Bin 0 -> 20281 bytes .../util/__pycache__/ssl_.cpython-313.pyc | Bin 0 -> 16653 bytes .../ssl_match_hostname.cpython-313.pyc | Bin 0 -> 5751 bytes .../__pycache__/ssltransport.cpython-313.pyc | Bin 0 -> 13466 bytes .../util/__pycache__/timeout.cpython-313.pyc | Bin 0 -> 11318 bytes .../util/__pycache__/url.cpython-313.pyc | Bin 0 -> 16310 bytes .../util/__pycache__/util.cpython-313.pyc | Bin 0 -> 2148 bytes .../util/__pycache__/wait.cpython-313.pyc | Bin 0 -> 3572 bytes .../urllib3/util/connection.py | 137 ++ .../acm-certificate/urllib3/util/proxy.py | 43 + .../acm-certificate/urllib3/util/request.py | 258 ++++ .../acm-certificate/urllib3/util/response.py | 101 ++ .../acm-certificate/urllib3/util/retry.py | 533 +++++++ .../acm-certificate/urllib3/util/ssl_.py | 504 +++++++ .../urllib3/util/ssl_match_hostname.py | 159 ++ .../urllib3/util/ssltransport.py | 271 ++++ .../acm-certificate/urllib3/util/timeout.py | 275 ++++ .../acm-certificate/urllib3/util/url.py | 469 ++++++ .../acm-certificate/urllib3/util/util.py | 42 + .../acm-certificate/urllib3/util/wait.py | 124 ++ apigw-private-cdn-acm/api-testing/index.py | 40 + apigw-private-cdn-acm/api-testing/rootCA.pem | 33 + apigw-private-cdn-acm/example-pattern.json | 65 + apigw-private-cdn-acm/images/architecture.png | Bin 0 -> 77964 bytes apigw-private-cdn-acm/images/tusharthapar.jpg | Bin 0 -> 308262 bytes apigw-private-cdn-acm/images/vijay.jpg | Bin 0 -> 8859 bytes apigw-private-cdn-acm/template.yaml | 258 ++++ 100 files changed, 12914 insertions(+) create mode 100644 apigw-private-cdn-acm/README.md create mode 100644 apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/INSTALLER create mode 100644 apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/LICENSE create mode 100644 apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/METADATA create mode 100644 apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/RECORD create mode 100644 apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/REQUESTED create mode 100644 apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/WHEEL create mode 100644 apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/top_level.txt create mode 100644 apigw-private-cdn-acm/acm-certificate/cfnresponse/__init__.py create mode 100644 apigw-private-cdn-acm/acm-certificate/cfnresponse/__pycache__/__init__.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/index.py create mode 100644 apigw-private-cdn-acm/acm-certificate/rootCA.pem create mode 100644 apigw-private-cdn-acm/acm-certificate/server.crt create mode 100644 apigw-private-cdn-acm/acm-certificate/server.key create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/INSTALLER create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/METADATA create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/RECORD create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/WHEEL create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/licenses/LICENSE.txt create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__init__.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/__init__.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/_base_connection.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/_collections.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/_request_methods.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/_version.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/connection.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/connectionpool.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/exceptions.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/fields.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/filepost.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/poolmanager.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/response.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/_base_connection.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/_collections.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/_request_methods.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/_version.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/connection.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/connectionpool.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/__init__.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/__pycache__/__init__.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/__pycache__/pyopenssl.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/__pycache__/socks.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__init__.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/__init__.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/connection.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/fetch.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/request.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/response.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/connection.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/emscripten_fetch_worker.js create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/fetch.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/request.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/response.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/pyopenssl.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/contrib/socks.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/exceptions.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/fields.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/filepost.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/http2/__init__.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/http2/__pycache__/__init__.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/http2/__pycache__/connection.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/http2/__pycache__/probe.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/http2/connection.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/http2/probe.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/poolmanager.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/py.typed create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/response.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__init__.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/__init__.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/connection.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/proxy.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/request.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/response.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/retry.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/ssl_.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/ssl_match_hostname.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/ssltransport.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/timeout.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/url.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/util.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/wait.cpython-313.pyc create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/connection.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/proxy.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/request.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/response.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/retry.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/ssl_.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/ssl_match_hostname.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/ssltransport.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/timeout.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/url.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/util.py create mode 100644 apigw-private-cdn-acm/acm-certificate/urllib3/util/wait.py create mode 100644 apigw-private-cdn-acm/api-testing/index.py create mode 100644 apigw-private-cdn-acm/api-testing/rootCA.pem create mode 100644 apigw-private-cdn-acm/example-pattern.json create mode 100644 apigw-private-cdn-acm/images/architecture.png create mode 100644 apigw-private-cdn-acm/images/tusharthapar.jpg create mode 100644 apigw-private-cdn-acm/images/vijay.jpg create mode 100644 apigw-private-cdn-acm/template.yaml diff --git a/apigw-private-cdn-acm/README.md b/apigw-private-cdn-acm/README.md new file mode 100644 index 000000000..5d7a72cad --- /dev/null +++ b/apigw-private-cdn-acm/README.md @@ -0,0 +1,114 @@ +# Amazon API gateway private REST API with private custom domain name configured with private SSL cert imported and managed by ACM + +This pattern enables secure access to a private REST API Gateway using a private custom domain name. The solution utilizes SSL certificates, imported and managed through AWS Certificate Manager (ACM). + +Learn more about this pattern at [Serverless Land Patterns](https://serverlessland.com/patterns/apigw-private-cdn). + +You can update the template to add AWS resources through the same deployment process that updates your application code. + +Important: This application uses various AWS Services and there are costs associated with these services after the Free Tier Usage - please see the [AWS Pricing Page](https://aws.amazon.com/pricing/) for more details. You are responsible for any AWS costs incurred. No warranty is implied in this example. + +### Requirements + +- [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. +- [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured +- [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) installed and configured +- [A VPC with subnets and a security group](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-getting-started.html). The security group must have following conditions: + 1. Inbound rule allowing 443 traffic on the VPC CIDR range. + 2. Outbound rule allowing 443 traffic on VPC CIDR range. +- [An Amazon S3 bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html) that stores local artifacts, including Lambda function source code required for this deployment. + +### How it works + +Please refer to the architecture diagram below: + +![End to End Architecture](images/architecture.png) + +This implementation consists of three major components: + +1. Certificate and API Gateway Setup + 1. Import a private SSL certificate into ACM + 2. Create a private REST API in API gateway + 3. Associate the ACM certificate with API Gateway's private custom domain + 4. Configure a Lambda function as the API Gateway backend processor + 5. Deploys a private REST API through API Gateway + 6. Associate the custom domain with the API Gateway stage + +2. "execute-api" VPC Endpoint configuration - Provides private access to the private REST API + +3. DNS Configuration + 1. Establish a private hosted zone for the domain name + 2. Creates a CNAME record within the hosted zone for custom domain name + 3. Points API Gateway's private custom domain name to the "execute-api" VPC Endpoint DNS name + +### Deployment Instructions + +**Note**: Please make sure to follow the below steps in order to make sure the deployment is successful. + +1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: + ``` bash + git clone https://github.com/aws-samples/serverless-patterns + ``` +2. Change directory to the pattern directory: + ```bash + cd serverless-patterns/apigw-private-cdn + ``` +3. Execute the following AWS CLI command after replacing the placeholders (indicated by <>) with their corresponding values: + ```bash + aws cloudformation package \ + --template-file template.yaml \ + --s3-bucket \ + --output-template-file output.yaml + ``` +4. Execute the following AWS CLI command after replacing the placeholders (indicated by <>) with their corresponding values: + ```bash + aws cloudformation deploy \ + --template-file output.yaml \ + --stack-name apigw-private-cdn \ + --parameter-overrides VpcIdParameter= VpcEndpointSubnetIdsParameter= ApiVPCESecurityGroup= \ + --capabilities CAPABILITY_IAM + ``` +4. To implement your own custom domain configuration: + 1. Modify the CloudFormation template.yaml file by updating two constant parameter's values: `CustomDomain` and `DomainName`: + ```bash + Mappings: + Constants: + CustomDomain: + Value: "apigw.example.com" + DomainName: + Value: "example.com" + ``` + 2. Prepare the following certificate files: + 1. Root certificate `rootCA.pem`. + 2. Server certificate `server.crt`. + 3. Server private key `server.key`. + 3. Update certificate files in the following directories: + 1. `acm-certificate` folder: + 1. `rootCA.pem` + 2. `server.crt` + 3. `server.key` + 2. `api-testing` folder: + 1. `rootCA.pem` + +## Testing + +1. Sign in to the AWS Management Console. +2. Navigate to AWS Lambda by searching 'Lambda' in the services search bar. +3. From the Lambda functions list, select the function containing 'APITestingLambdaFunction' in its name. +4. Click the 'Test' button in the function's detail page. +5. Review the execution results in the output section, which will contain the response from the private API Gateway API. + +## Cleanup + +To remove all resources deployed to your AWS account through CloudFormation: + +```bash +aws cloudformation delete-stack --stack-name apigw-private-cdn +``` + + +--- + +Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 \ No newline at end of file diff --git a/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/INSTALLER b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/INSTALLER new file mode 100644 index 000000000..a1b589e38 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/LICENSE b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/METADATA b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/METADATA new file mode 100644 index 000000000..cc81a34fe --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/METADATA @@ -0,0 +1,39 @@ +Metadata-Version: 2.1 +Name: cfnresponse +Version: 1.1.5 +Summary: Send a response object to a custom resource by way of an Amazon S3 presigned URL +Home-page: https://github.com/gene1wood/cfnresponse +Author: Amazon Web Services +Project-URL: Download, https://github.com/gene1wood/cfnresponse/archive/refs/tags/v1.1.5.tar.gz +Project-URL: Source, https://github.com/gene1wood/cfnresponse +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 2 +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Description-Content-Type: text/markdown +License-File: LICENSE +Requires-Dist: urllib3 + +# cfnresponse + +[![PyPi Version](https://badgen.net/pypi/v/cfnresponse)](https://pypi.org/project/cfnresponse/) + +This package contains the Amazon Web Services (AWS) cfnresponse module which is +available in Python AWS Lambda environments. + +The code for this module can be found [in the AWS documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-lambda-function-code-cfnresponsemodule.html#w2ab1c23c23c16b9c15) +and in the [awslabs GitHub repo](https://github.com/awslabs/aws-cloudformation-templates/blob/master/aws/services/CloudFormation/MacrosExamples/StackMetrics/lambda/cfnresponse.py) + +You can compare the code in `awslabs` with this pypi package with this command + +``` +if [ "$(curl -s https://raw.githubusercontent.com/awslabs/aws-cloudformation-templates/master/aws/services/CloudFormation/MacrosExamples/StackMetrics/lambda/cfnresponse.py | sha256sum)" = "$(curl -s https://raw.githubusercontent.com/gene1wood/cfnresponse/master/cfnresponse/__init__.py | sha256sum)" ]; then echo "GitHub matches AWS"; else echo "GitHub does not match AWS"; fi +if [ "$(curl -s https://raw.githubusercontent.com/awslabs/aws-cloudformation-templates/master/aws/services/CloudFormation/MacrosExamples/StackMetrics/lambda/cfnresponse.py | sha256sum)" = "$(wget --quiet https://files.pythonhosted.org/packages/f9/b7/76b0abe8003a797ab535cae77e39568092eff18ac0e8e10fa9ffa245e5d3/cfnresponse-1.1.4-py2.py3-none-any.whl && unzip -p cfnresponse-1.1.4-py2.py3-none-any.whl cfnresponse/__init__.py | sha256sum && rm cfnresponse-1.1.4-py2.py3-none-any.whl)" ]; then echo "PyPi matches AWS"; else echo "PyPi does not match AWS"; fi +``` + +This module [used to use the vendored version of `requests`](https://github.com/awslabs/aws-cloudformation-templates/blob/dd484dd32680fcbfc52b34de45923f78b5626e39/aws/services/CloudFormation/MacrosExamples/StackMetrics/lambda/cfnresponse.py) +provided by `botocore` but this changed in +[April 2020](https://github.com/awslabs/aws-cloudformation-templates/commit/44b76a1f694f82eeee14fe804bf9dc973fdc2230#diff-f6c57142d56d8704aaf1d429ff1a06a6dd3f2ee6d80f0572ada8af010ff17124) +to instead use `urllib3` as +[`botocore.vendored.requests` was removed](https://github.com/boto/botocore/pull/1829). diff --git a/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/RECORD b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/RECORD new file mode 100644 index 000000000..7d44af99b --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/RECORD @@ -0,0 +1,9 @@ +cfnresponse-1.1.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +cfnresponse-1.1.5.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357 +cfnresponse-1.1.5.dist-info/METADATA,sha256=9ViuiIxPzfXuX88NSekCKEAJR0gkoNLYyKrNSJJDBKw,2986 +cfnresponse-1.1.5.dist-info/RECORD,, +cfnresponse-1.1.5.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +cfnresponse-1.1.5.dist-info/WHEEL,sha256=XRxW4r1PNiVhMpP4bT9oWtu3HyndxpJ84SkubFgzp_Y,109 +cfnresponse-1.1.5.dist-info/top_level.txt,sha256=j9Zq5oZ_a04PdpNkYtZ_QZxzTSGGO7cH3MKnJPdL_EE,12 +cfnresponse/__init__.py,sha256=D7jZdfXoxJKagcQ6mwDR5VriUxEQV_W_J6rweR2pi8U,1303 +cfnresponse/__pycache__/__init__.cpython-313.pyc,, diff --git a/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/REQUESTED b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/REQUESTED new file mode 100644 index 000000000..e69de29bb diff --git a/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/WHEEL b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/WHEEL new file mode 100644 index 000000000..28da1fc36 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: setuptools (72.1.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/top_level.txt b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/top_level.txt new file mode 100644 index 000000000..22fdf3c97 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/cfnresponse-1.1.5.dist-info/top_level.txt @@ -0,0 +1 @@ +cfnresponse diff --git a/apigw-private-cdn-acm/acm-certificate/cfnresponse/__init__.py b/apigw-private-cdn-acm/acm-certificate/cfnresponse/__init__.py new file mode 100644 index 000000000..c6b007226 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/cfnresponse/__init__.py @@ -0,0 +1,47 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 + +from __future__ import print_function +import urllib3 +import json + +SUCCESS = "SUCCESS" +FAILED = "FAILED" + +http = urllib3.PoolManager() + + +def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False, reason=None): + responseUrl = event['ResponseURL'] + + print(responseUrl) + + responseBody = { + 'Status': responseStatus, + 'Reason': reason or "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name), + 'PhysicalResourceId': physicalResourceId or context.log_stream_name, + 'StackId': event['StackId'], + 'RequestId': event['RequestId'], + 'LogicalResourceId': event['LogicalResourceId'], + 'NoEcho': noEcho, + 'Data': responseData + } + + json_responseBody = json.dumps(responseBody) + + print("Response body:") + print(json_responseBody) + + headers = { + 'content-type': '', + 'content-length': str(len(json_responseBody)) + } + + try: + response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody) + print("Status code:", response.status) + + + except Exception as e: + + print("send(..) failed executing http.request(..):", e) \ No newline at end of file diff --git a/apigw-private-cdn-acm/acm-certificate/cfnresponse/__pycache__/__init__.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/cfnresponse/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6204ec30806a52cd5481dfa866282356ed4064a GIT binary patch literal 1785 zcmZux&2JM&6rc5e`jf^XBsfl3f}pqoI}I_YArxo`C?AbrmsMLC$=a;PYX@i7nH?iy zRLMtqozjl9`+o1uZ{EE3=FRLz zqai@YcR&7Y4~hW%#uR@9x?uM<1z!Li=-eV$;1H)W99RsXz@Fq0uk%RI1ti`HXc2#T zPmY0XS3$Ba>0$z`a!9cQDfxG1PjMtxMP&!)i#5l>W!G6IvTn@I&gnXlu3w#Bn!9Gn zJ$E2TF;Bl;!m+>%8W@coIC75a`@@j4U918lU`Us^)7_cEFaR`xfW|z$F$_)<-Y`+s z_hbkMywEhM=l|u?cz6~Ml|omFdr~xbT}msCl9T*hG{r|fIR*^H-_r^9a?%gv)Uz5v zpG&h+a$(<3F6yHm!)NNjbifIXf?Uk!Xnj8FNj>y&-3aR8_XH>0+fR=eVJ+Tc`6%0M z7ZupxILICL?J_Wr(6fmg@DMd3J@zr$Oitu##O}%>R|J>%W1z^TV#_3~L9gmM9yGM2 z`WYQU6_=n|fY>ZoJhkkovlX{i_{hXoNnLVnRmTXLYt!n3PiYHb)4DrfAVCeT*Pw?f z?4z8rWmc$Hw}vb@Uq~rLqC{Nth@?T&a~%@DS=#Xa%|h&$5bHa{?hBEY-8rk|65*PO z&3eoaQeANi8`A`&0`-XHIv6_mEZ(TXdd$}<(6Moe@HdUysQ{5n&@4dY5rHkNNA?3z zEw=!t>*F4D3a8WQlv;b|~LV7`dlbw(s_zZSu{`xdOSyO@d+5#FPj5P2_& z`98=u{t5$C$UnsDrJa=p5OC$s0K)+f)`i`gu;@ydk>Yl05j z%iPXX%hj{kL^i}{@8<88ve`*HQz@@xsvEfEIvK0z_&aCv`La{S`Fy&%K?HU@=nM^n zT_SIX{u-bYAKZ+#;-?ymFNEO3@u$L(9SQUw@5G1N@zrK>p`EIgVG@+kCm=<&?f&_q)hpqn*AiKoKwHUq;?g(Thf= +Maintainer-email: Seth Michael Larson , Quentin Pradet , Illia Volochii +License-File: LICENSE.txt +Keywords: filepost,http,httplib,https,pooling,ssl,threadsafe,urllib +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: Software Development :: Libraries +Requires-Python: >=3.9 +Provides-Extra: brotli +Requires-Dist: brotli>=1.0.9; (platform_python_implementation == 'CPython') and extra == 'brotli' +Requires-Dist: brotlicffi>=0.8.0; (platform_python_implementation != 'CPython') and extra == 'brotli' +Provides-Extra: h2 +Requires-Dist: h2<5,>=4; extra == 'h2' +Provides-Extra: socks +Requires-Dist: pysocks!=1.5.7,<2.0,>=1.5.6; extra == 'socks' +Provides-Extra: zstd +Requires-Dist: zstandard>=0.18.0; extra == 'zstd' +Description-Content-Type: text/markdown + +

+ +![urllib3](https://github.com/urllib3/urllib3/raw/main/docs/_static/banner_github.svg) + +

+ +

+ PyPI Version + Python Versions + Join our Discord + Coverage Status + Build Status on GitHub + Documentation Status
+ OpenSSF Scorecard + SLSA 3 + CII Best Practices +

+ +urllib3 is a powerful, *user-friendly* HTTP client for Python. Much of the +Python ecosystem already uses urllib3 and you should too. +urllib3 brings many critical features that are missing from the Python +standard libraries: + +- Thread safety. +- Connection pooling. +- Client-side SSL/TLS verification. +- File uploads with multipart encoding. +- Helpers for retrying requests and dealing with HTTP redirects. +- Support for gzip, deflate, brotli, and zstd encoding. +- Proxy support for HTTP and SOCKS. +- 100% test coverage. + +urllib3 is powerful and easy to use: + +```python3 +>>> import urllib3 +>>> resp = urllib3.request("GET", "http://httpbin.org/robots.txt") +>>> resp.status +200 +>>> resp.data +b"User-agent: *\nDisallow: /deny\n" +``` + +## Installing + +urllib3 can be installed with [pip](https://pip.pypa.io): + +```bash +$ python -m pip install urllib3 +``` + +Alternatively, you can grab the latest source code from [GitHub](https://github.com/urllib3/urllib3): + +```bash +$ git clone https://github.com/urllib3/urllib3.git +$ cd urllib3 +$ pip install . +``` + + +## Documentation + +urllib3 has usage and reference documentation at [urllib3.readthedocs.io](https://urllib3.readthedocs.io). + + +## Community + +urllib3 has a [community Discord channel](https://discord.gg/urllib3) for asking questions and +collaborating with other contributors. Drop by and say hello 👋 + + +## Contributing + +urllib3 happily accepts contributions. Please see our +[contributing documentation](https://urllib3.readthedocs.io/en/latest/contributing.html) +for some tips on getting started. + + +## Security Disclosures + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure with maintainers. + + +## Maintainers + +- [@sethmlarson](https://github.com/sethmlarson) (Seth M. Larson) +- [@pquentin](https://github.com/pquentin) (Quentin Pradet) +- [@illia-v](https://github.com/illia-v) (Illia Volochii) +- [@theacodes](https://github.com/theacodes) (Thea Flowers) +- [@haikuginger](https://github.com/haikuginger) (Jess Shapiro) +- [@lukasa](https://github.com/lukasa) (Cory Benfield) +- [@sigmavirus24](https://github.com/sigmavirus24) (Ian Stapleton Cordasco) +- [@shazow](https://github.com/shazow) (Andrey Petrov) + +👋 + + +## Sponsorship + +If your company benefits from this library, please consider [sponsoring its +development](https://urllib3.readthedocs.io/en/latest/sponsors.html). + + +## For Enterprise + +Professional support for urllib3 is available as part of the [Tidelift +Subscription][1]. Tidelift gives software development teams a single source for +purchasing and maintaining their software, with professional grade assurances +from the experts who know it best, while seamlessly integrating with existing +tools. + +[1]: https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&utm_medium=referral&utm_campaign=readme diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/RECORD b/apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/RECORD new file mode 100644 index 000000000..2a63e5aaa --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/RECORD @@ -0,0 +1,79 @@ +urllib3-2.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +urllib3-2.3.0.dist-info/METADATA,sha256=quSdNDoWoaG7idKpqr1_2N52fUBfxTtifpP3sofNwAY,6488 +urllib3-2.3.0.dist-info/RECORD,, +urllib3-2.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87 +urllib3-2.3.0.dist-info/licenses/LICENSE.txt,sha256=Ew46ZNX91dCWp1JpRjSn2d8oRGnehuVzIQAmgEHj1oY,1093 +urllib3/__init__.py,sha256=JMo1tg1nIV1AeJ2vENC_Txfl0e5h6Gzl9DGVk1rWRbo,6979 +urllib3/__pycache__/__init__.cpython-313.pyc,, +urllib3/__pycache__/_base_connection.cpython-313.pyc,, +urllib3/__pycache__/_collections.cpython-313.pyc,, +urllib3/__pycache__/_request_methods.cpython-313.pyc,, +urllib3/__pycache__/_version.cpython-313.pyc,, +urllib3/__pycache__/connection.cpython-313.pyc,, +urllib3/__pycache__/connectionpool.cpython-313.pyc,, +urllib3/__pycache__/exceptions.cpython-313.pyc,, +urllib3/__pycache__/fields.cpython-313.pyc,, +urllib3/__pycache__/filepost.cpython-313.pyc,, +urllib3/__pycache__/poolmanager.cpython-313.pyc,, +urllib3/__pycache__/response.cpython-313.pyc,, +urllib3/_base_connection.py,sha256=T1cwH3RhzsrBh6Bz3AOGVDboRsE7veijqZPXXQTR2Rg,5568 +urllib3/_collections.py,sha256=tM7c6J1iKtWZYV_QGYb8-r7Nr1524Dehnsa0Ufh6_mU,17295 +urllib3/_request_methods.py,sha256=gCeF85SO_UU4WoPwYHIoz_tw-eM_EVOkLFp8OFsC7DA,9931 +urllib3/_version.py,sha256=ChsIHG8bRc-eXUbXOgv4Fm4DstSKLq9FpsTAsaMeR08,411 +urllib3/connection.py,sha256=dsVIUaPrOdATuO9OGnF5GzMhlVKlAw-2qH9FWYuic4s,39875 +urllib3/connectionpool.py,sha256=ZEhudsa8BIubD2M0XoxBBsjxbsXwMgUScH7oQ9i-j1Y,43371 +urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +urllib3/contrib/__pycache__/__init__.cpython-313.pyc,, +urllib3/contrib/__pycache__/pyopenssl.cpython-313.pyc,, +urllib3/contrib/__pycache__/socks.cpython-313.pyc,, +urllib3/contrib/emscripten/__init__.py,sha256=u6KNgzjlFZbuAAXa_ybCR7gQ71VJESnF-IIdDA73brw,733 +urllib3/contrib/emscripten/__pycache__/__init__.cpython-313.pyc,, +urllib3/contrib/emscripten/__pycache__/connection.cpython-313.pyc,, +urllib3/contrib/emscripten/__pycache__/fetch.cpython-313.pyc,, +urllib3/contrib/emscripten/__pycache__/request.cpython-313.pyc,, +urllib3/contrib/emscripten/__pycache__/response.cpython-313.pyc,, +urllib3/contrib/emscripten/connection.py,sha256=j8DR_flE7hsoFhNfiqHLiaPaCsVbzG44jgahwvsQ52A,8771 +urllib3/contrib/emscripten/emscripten_fetch_worker.js,sha256=CDfYF_9CDobtx2lGidyJ1zjDEvwNT5F-dchmVWXDh0E,3655 +urllib3/contrib/emscripten/fetch.py,sha256=Li6sUnFuFog0fBiahk1Y0C0tdn5fxmj4ucDofPWFiXc,22867 +urllib3/contrib/emscripten/request.py,sha256=mL28szy1KvE3NJhWor5jNmarp8gwplDU-7gwGZY5g0Q,566 +urllib3/contrib/emscripten/response.py,sha256=sc0CJCEV_3t_HTadOmvWNuO-WkYbI1YfQWnBBmaeriE,9981 +urllib3/contrib/pyopenssl.py,sha256=uMNfy0e-wT-WNrTF-4oOQ17-I3w0NPrREm1t5AC9wxg,19398 +urllib3/contrib/socks.py,sha256=-iardc61GypsJzD6W6yuRS7KVCyfowcQrl_719H7lIM,7549 +urllib3/exceptions.py,sha256=VSkjQkvw3iolMKP_ZWfiiXumAj2VCvhmz2B3W-MP4BA,9633 +urllib3/fields.py,sha256=FCf7UULSkf10cuTRUWTQESzxgl1WT8e2aCy3kfyZins,10829 +urllib3/filepost.py,sha256=U8eNZ-mpKKHhrlbHEEiTxxgK16IejhEa7uz42yqA_dI,2388 +urllib3/http2/__init__.py,sha256=xzrASH7R5ANRkPJOot5lGnATOq3KKuyXzI42rcnwmqs,1741 +urllib3/http2/__pycache__/__init__.cpython-313.pyc,, +urllib3/http2/__pycache__/connection.cpython-313.pyc,, +urllib3/http2/__pycache__/probe.cpython-313.pyc,, +urllib3/http2/connection.py,sha256=GNlp9BjI3DmfSKe1W0b9IqRBeM8Q13xd2MA3ROcJ3dY,12668 +urllib3/http2/probe.py,sha256=nnAkqbhAakOiF75rz7W0udZ38Eeh_uD8fjV74N73FEI,3014 +urllib3/poolmanager.py,sha256=2_L2AjVDgoQ0qBmYbX9u9QqyU1u5J37zQbtv_-ueZQA,22913 +urllib3/py.typed,sha256=UaCuPFa3H8UAakbt-5G8SPacldTOGvJv18pPjUJ5gDY,93 +urllib3/response.py,sha256=PBW5ZnK3kYeq0fqeUYywyASKQWK7uRzSa-HgDBzZedU,45190 +urllib3/util/__init__.py,sha256=-qeS0QceivazvBEKDNFCAI-6ACcdDOE4TMvo7SLNlAQ,1001 +urllib3/util/__pycache__/__init__.cpython-313.pyc,, +urllib3/util/__pycache__/connection.cpython-313.pyc,, +urllib3/util/__pycache__/proxy.cpython-313.pyc,, +urllib3/util/__pycache__/request.cpython-313.pyc,, +urllib3/util/__pycache__/response.cpython-313.pyc,, +urllib3/util/__pycache__/retry.cpython-313.pyc,, +urllib3/util/__pycache__/ssl_.cpython-313.pyc,, +urllib3/util/__pycache__/ssl_match_hostname.cpython-313.pyc,, +urllib3/util/__pycache__/ssltransport.cpython-313.pyc,, +urllib3/util/__pycache__/timeout.cpython-313.pyc,, +urllib3/util/__pycache__/url.cpython-313.pyc,, +urllib3/util/__pycache__/util.cpython-313.pyc,, +urllib3/util/__pycache__/wait.cpython-313.pyc,, +urllib3/util/connection.py,sha256=JjO722lzHlzLXPTkr9ZWBdhseXnMVjMSb1DJLVrXSnQ,4444 +urllib3/util/proxy.py,sha256=seP8-Q5B6bB0dMtwPj-YcZZQ30vHuLqRu-tI0JZ2fzs,1148 +urllib3/util/request.py,sha256=qSwxEsJJ-9DUfFDEAZIgQe8sgyywKY0o3faH3ixi3i8,8218 +urllib3/util/response.py,sha256=vQE639uoEhj1vpjEdxu5lNIhJCSUZkd7pqllUI0BZOA,3374 +urllib3/util/retry.py,sha256=bj-2YUqblxLlv8THg5fxww-DM54XCbjgZXIQ71XioCY,18459 +urllib3/util/ssl_.py,sha256=CcYPnFKqJDn58Us2J5AFBQLMthIVVMjb69HwvdmPgoQ,18884 +urllib3/util/ssl_match_hostname.py,sha256=gaWqixoYtQ_GKO8fcRGFj3VXeMoqyxQQuUTPgWeiL_M,5812 +urllib3/util/ssltransport.py,sha256=Ez4O8pR_vT8dan_FvqBYS6dgDfBXEMfVfrzcdUoWfi4,8847 +urllib3/util/timeout.py,sha256=4eT1FVeZZU7h7mYD1Jq2OXNe4fxekdNvhoWUkZusRpA,10346 +urllib3/util/url.py,sha256=WRh-TMYXosmgp8m8lT4H5spoHw5yUjlcMCfU53AkoAs,15205 +urllib3/util/util.py,sha256=j3lbZK1jPyiwD34T8IgJzdWEZVT-4E-0vYIJi9UjeNA,1146 +urllib3/util/wait.py,sha256=_ph8IrUR3sqPqi0OopQgJUlH4wzkGeM5CiyA7XGGtmI,4423 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/WHEEL b/apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/WHEEL new file mode 100644 index 000000000..12228d414 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.27.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/licenses/LICENSE.txt b/apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/licenses/LICENSE.txt new file mode 100644 index 000000000..e6183d027 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3-2.3.0.dist-info/licenses/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2008-2020 Andrey Petrov and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/__init__.py b/apigw-private-cdn-acm/acm-certificate/urllib3/__init__.py new file mode 100644 index 000000000..3fe782c8a --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/__init__.py @@ -0,0 +1,211 @@ +""" +Python HTTP library with thread-safe connection pooling, file post support, user friendly, and more +""" + +from __future__ import annotations + +# Set default logging handler to avoid "No handler found" warnings. +import logging +import sys +import typing +import warnings +from logging import NullHandler + +from . import exceptions +from ._base_connection import _TYPE_BODY +from ._collections import HTTPHeaderDict +from ._version import __version__ +from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url +from .filepost import _TYPE_FIELDS, encode_multipart_formdata +from .poolmanager import PoolManager, ProxyManager, proxy_from_url +from .response import BaseHTTPResponse, HTTPResponse +from .util.request import make_headers +from .util.retry import Retry +from .util.timeout import Timeout + +# Ensure that Python is compiled with OpenSSL 1.1.1+ +# If the 'ssl' module isn't available at all that's +# fine, we only care if the module is available. +try: + import ssl +except ImportError: + pass +else: + if not ssl.OPENSSL_VERSION.startswith("OpenSSL "): # Defensive: + warnings.warn( + "urllib3 v2 only supports OpenSSL 1.1.1+, currently " + f"the 'ssl' module is compiled with {ssl.OPENSSL_VERSION!r}. " + "See: https://github.com/urllib3/urllib3/issues/3020", + exceptions.NotOpenSSLWarning, + ) + elif ssl.OPENSSL_VERSION_INFO < (1, 1, 1): # Defensive: + raise ImportError( + "urllib3 v2 only supports OpenSSL 1.1.1+, currently " + f"the 'ssl' module is compiled with {ssl.OPENSSL_VERSION!r}. " + "See: https://github.com/urllib3/urllib3/issues/2168" + ) + +__author__ = "Andrey Petrov (andrey.petrov@shazow.net)" +__license__ = "MIT" +__version__ = __version__ + +__all__ = ( + "HTTPConnectionPool", + "HTTPHeaderDict", + "HTTPSConnectionPool", + "PoolManager", + "ProxyManager", + "HTTPResponse", + "Retry", + "Timeout", + "add_stderr_logger", + "connection_from_url", + "disable_warnings", + "encode_multipart_formdata", + "make_headers", + "proxy_from_url", + "request", + "BaseHTTPResponse", +) + +logging.getLogger(__name__).addHandler(NullHandler()) + + +def add_stderr_logger( + level: int = logging.DEBUG, +) -> logging.StreamHandler[typing.TextIO]: + """ + Helper for quickly adding a StreamHandler to the logger. Useful for + debugging. + + Returns the handler after adding it. + """ + # This method needs to be in this __init__.py to get the __name__ correct + # even if urllib3 is vendored within another package. + logger = logging.getLogger(__name__) + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s")) + logger.addHandler(handler) + logger.setLevel(level) + logger.debug("Added a stderr logging handler to logger: %s", __name__) + return handler + + +# ... Clean up. +del NullHandler + + +# All warning filters *must* be appended unless you're really certain that they +# shouldn't be: otherwise, it's very hard for users to use most Python +# mechanisms to silence them. +# SecurityWarning's always go off by default. +warnings.simplefilter("always", exceptions.SecurityWarning, append=True) +# InsecurePlatformWarning's don't vary between requests, so we keep it default. +warnings.simplefilter("default", exceptions.InsecurePlatformWarning, append=True) + + +def disable_warnings(category: type[Warning] = exceptions.HTTPWarning) -> None: + """ + Helper for quickly disabling all urllib3 warnings. + """ + warnings.simplefilter("ignore", category) + + +_DEFAULT_POOL = PoolManager() + + +def request( + method: str, + url: str, + *, + body: _TYPE_BODY | None = None, + fields: _TYPE_FIELDS | None = None, + headers: typing.Mapping[str, str] | None = None, + preload_content: bool | None = True, + decode_content: bool | None = True, + redirect: bool | None = True, + retries: Retry | bool | int | None = None, + timeout: Timeout | float | int | None = 3, + json: typing.Any | None = None, +) -> BaseHTTPResponse: + """ + A convenience, top-level request method. It uses a module-global ``PoolManager`` instance. + Therefore, its side effects could be shared across dependencies relying on it. + To avoid side effects create a new ``PoolManager`` instance and use it instead. + The method does not accept low-level ``**urlopen_kw`` keyword arguments. + + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + + :param url: + The URL to perform the request on. + + :param body: + Data to send in the request body, either :class:`str`, :class:`bytes`, + an iterable of :class:`str`/:class:`bytes`, or a file-like object. + + :param fields: + Data to encode and send in the request body. + + :param headers: + Dictionary of custom headers to send, such as User-Agent, + If-None-Match, etc. + + :param bool preload_content: + If True, the response's body will be preloaded into memory. + + :param bool decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param redirect: + If True, automatically handle redirects (status codes 301, 302, + 303, 307, 308). Each redirect counts as a retry. Disabling retries + will disable redirect, too. + + :param retries: + Configure the number of retries to allow before raising a + :class:`~urllib3.exceptions.MaxRetryError` exception. + + If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a + :class:`~urllib3.util.retry.Retry` object for fine-grained control + over different types of retries. + Pass an integer number to retry connection errors that many times, + but no other types of errors. Pass zero to never retry. + + If ``False``, then retries are disabled and any exception is raised + immediately. Also, instead of raising a MaxRetryError on redirects, + the redirect response will be returned. + + :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. + + :param timeout: + If specified, overrides the default timeout for this one + request. It may be a float (in seconds) or an instance of + :class:`urllib3.util.Timeout`. + + :param json: + Data to encode and send as JSON with UTF-encoded in the request body. + The ``"Content-Type"`` header will be set to ``"application/json"`` + unless specified otherwise. + """ + + return _DEFAULT_POOL.request( + method, + url, + body=body, + fields=fields, + headers=headers, + preload_content=preload_content, + decode_content=decode_content, + redirect=redirect, + retries=retries, + timeout=timeout, + json=json, + ) + + +if sys.platform == "emscripten": + from .contrib.emscripten import inject_into_urllib3 # noqa: 401 + + inject_into_urllib3() diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/__init__.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68dd9e4fb0e3526c6834e1e5c3d861b7fac2e0a9 GIT binary patch literal 7145 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�E?tr z36{9=BGOFszlb&y!!M#Or7!A#(cQYpe4%~T_lots9DmJD?X!z}?BZYj@n8SR8#V(G zjt&3inLj_%3iSE!bWLIYQ)AM`j`Tt~!FZES|^_~8U_=`A5ojunayVy)m zH_u(7&S~CEPBtedni literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/_base_connection.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/_base_connection.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65d46bb51618b2eb6d6f44c2dc12334594b2c027 GIT binary patch literal 6988 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 H8jAgYv+;{r literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/_request_methods.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/_request_methods.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da5391ab308d6b6cce10a1c3e4e93db5cd996f3a GIT binary patch literal 9982 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 G&;JHSJpmQ~ literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/_version.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/_version.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..800e57db6d166241c9682d1f381200e2c48240fe GIT binary patch literal 616 zcmYL`O=}ZD7{_OKvYXeXDUG6~(0~@rAv+<->P5YjsBKMJ+*A-2hE2NNu8F&w$s~{- zB;v)R9t6cpj(YL#r!bPsG6xNK%B_$u;A~9n!|;E8&kOVN%v@0tfZMn4KkUx}0Dr<@ zWsxP!Uvc;Vc7P5DFu?6)+PngQF6iQcurCsE9}<`ahG;+|Vn}6C;$1rY=ZSnM8c`w} zk`dD*w|Hei(t>23lmAmRBt3RtAaRn=1n%1-2x4`<=AIgv^Ap5L~ZbnH5wtFma{ zB3(`_iSZIKX6u&$4cmE2SydN_bE&A7)Ituqratc%G&yOm2_i<(SV6XOw z$#md5u1yv_;Y=8GT*_dV5~e(>Jk|FOYq)-V^rXUMukpfaQnrS%>AD^@DZg14VN{zu{DSG-c)~P(Cg|nvpK9z_@U{NFN;dcbe*p&arw{-D literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/connection.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/connection.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72bb2d3dc9b116d641e87b4f91198fc0e4af9ece GIT binary patch literal 36571 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 literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/connectionpool.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/connectionpool.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7fa0ec83de901834b4da4797eca1153d03f1c0a GIT binary patch literal 39141 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

12wdz5 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 literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/exceptions.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/exceptions.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..889f1182fa08ee3eec0caf0388a37c5110d1e092 GIT binary patch literal 16919 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 B6(Ils literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/poolmanager.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/__pycache__/poolmanager.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24cc507a839901397aaab207d442c5805d83b811 GIT binary patch literal 23665 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 pk}!7Nk1xLIP{G-N@m8lqd#WmPi%!262&|o<)X6 zuZ);{7UCjc<^dXsLT>+n^bB97SwO3xwTRkCe%lWmoh^v4mhfd#X%&OxtCh4iSR3}A z5Cr-zeh^qsP_12oB?|qLT&qUKf%bdQ7x4a)Oq1hu=p%?!W8xHk-53|A(1b`Ccmq)< zDY?0fu(goF+oYRaP!TPXkq6YPIx#4*R@ph}|A5I763_exp%wz<;e z+WTRV;-3sC8RFErhmlKS1H!sAOFvnM|55Ea8#wlsNYJ@j`EndG^&?}06DM#Q_Y*Db z)*vcmH9_oxo8$|Cq@SY_&?GDetM#vu7Yki$n!WOA+2)k{cpg$rb576|N1x!H zB9m{}aZ&eKrL2yv)Qd+c?J)|DQ}8hg2y}s3$)-3p#3zMaU3}2`5o%yAqupcZh%~6!+Dxvu7UhK#ex(NL{2*K z_s5jxq=0=s0~qXHX_3-uDfmMQzE43rm1Wc(Bjp$sMbI53 zdYHh&!VtFTE4%itG4p=)<)S+q_lC|TXaqV+=YZvGLgjkts7 zJr7G2C|o;Wv{=No+$>8TPF~YhI#!GO9>0$VF$k9U^*Zdz9Ck;KxQ6Ru>en(dEVXOS z?Uuq-0J;qKJ>z~$9hJkiI*6_I8bSZ9T6S0l3?K!I%HPSND7!gFPIKZ$Ar_?@bKcEn zQS4?awHXcbLWr?4JcWu-jF+Goz^HaL&tZd{ni7&_`9|fjjm;wEG=s`o25p+ z+{k7rmIo8Dwc;#G?ph)423m7wS{l~!ot9&UwK}(@62~wO8IIrgdEQX+~gYfITBfe?Y-ED0rWOcM-sQVrUZAUQ8y8Qb1x?wf`P=ULu2oCVn~KLCQ$h zkCDKI2wh)7pdpc+#8pZ}^CVn4Xn=Jw;ZA;|u(=Y+_N3pY=5mHV_VA(6?!$+=j~*F# zDB&EX3p|p2+mm=NVLL5_(EixO#1y+gERlWW99<`Th%RwRWX&m8tngdHERk7wu7vk| z{|rN&u+s|orLi+`nm?*|hZs#{OhOeu69y1M@p0va^dhyF+ofDI&RXD3DG7@+w-XFU z!>9gO2u^v~>`S;?`&^2V=#croO4u}?U=m}1Nvn0J;=J4h0t|_&f#AQSf^dyh%cveu^{7_er$Vd!NU1iX61^j_>vWR^-I>j7xI51G~(ai3f)nm z`#oc}!T6q_2E~G5?@xq^q`qvvlaUk8D0(BKXwe$WsD8%uUWUa`_l|&I%~@fnUijpi zfIsgYFqjMl?+6Ii>}5#yt_k?Fx<@eEqNaj1bFQUmF?UVCpLc5nvwh8+Zz);`t_k?F z)|78>FYH6y;9hHT7|P$P>oph(-vN9w6s`>!XH16T1&ORd*93~MO=NyD+fcjgs{MsP zk@r_0fgyYm{Bl_e-?A29=q-i6x|5lY1VjExPTp^l=T1ZZuK;4RiWak%KE9mUPVaDI zwEH&?(>vVJyazM)nrQB=5MJA4?%gYVzrxnrZ2EqKq1P*XzsW%HW)sD|*4|Fj_jeg6 O+?)N79Za?X;r|0%$=5>w literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/_base_connection.py b/apigw-private-cdn-acm/acm-certificate/urllib3/_base_connection.py new file mode 100644 index 000000000..dc0f318c0 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/_base_connection.py @@ -0,0 +1,165 @@ +from __future__ import annotations + +import typing + +from .util.connection import _TYPE_SOCKET_OPTIONS +from .util.timeout import _DEFAULT_TIMEOUT, _TYPE_TIMEOUT +from .util.url import Url + +_TYPE_BODY = typing.Union[bytes, typing.IO[typing.Any], typing.Iterable[bytes], str] + + +class ProxyConfig(typing.NamedTuple): + ssl_context: ssl.SSLContext | None + use_forwarding_for_https: bool + assert_hostname: None | str | typing.Literal[False] + assert_fingerprint: str | None + + +class _ResponseOptions(typing.NamedTuple): + # TODO: Remove this in favor of a better + # HTTP request/response lifecycle tracking. + request_method: str + request_url: str + preload_content: bool + decode_content: bool + enforce_content_length: bool + + +if typing.TYPE_CHECKING: + import ssl + from typing import Protocol + + from .response import BaseHTTPResponse + + class BaseHTTPConnection(Protocol): + default_port: typing.ClassVar[int] + default_socket_options: typing.ClassVar[_TYPE_SOCKET_OPTIONS] + + host: str + port: int + timeout: None | ( + float + ) # Instance doesn't store _DEFAULT_TIMEOUT, must be resolved. + blocksize: int + source_address: tuple[str, int] | None + socket_options: _TYPE_SOCKET_OPTIONS | None + + proxy: Url | None + proxy_config: ProxyConfig | None + + is_verified: bool + proxy_is_verified: bool | None + + def __init__( + self, + host: str, + port: int | None = None, + *, + timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, + source_address: tuple[str, int] | None = None, + blocksize: int = 8192, + socket_options: _TYPE_SOCKET_OPTIONS | None = ..., + proxy: Url | None = None, + proxy_config: ProxyConfig | None = None, + ) -> None: ... + + def set_tunnel( + self, + host: str, + port: int | None = None, + headers: typing.Mapping[str, str] | None = None, + scheme: str = "http", + ) -> None: ... + + def connect(self) -> None: ... + + def request( + self, + method: str, + url: str, + body: _TYPE_BODY | None = None, + headers: typing.Mapping[str, str] | None = None, + # We know *at least* botocore is depending on the order of the + # first 3 parameters so to be safe we only mark the later ones + # as keyword-only to ensure we have space to extend. + *, + chunked: bool = False, + preload_content: bool = True, + decode_content: bool = True, + enforce_content_length: bool = True, + ) -> None: ... + + def getresponse(self) -> BaseHTTPResponse: ... + + def close(self) -> None: ... + + @property + def is_closed(self) -> bool: + """Whether the connection either is brand new or has been previously closed. + If this property is True then both ``is_connected`` and ``has_connected_to_proxy`` + properties must be False. + """ + + @property + def is_connected(self) -> bool: + """Whether the connection is actively connected to any origin (proxy or target)""" + + @property + def has_connected_to_proxy(self) -> bool: + """Whether the connection has successfully connected to its proxy. + This returns False if no proxy is in use. Used to determine whether + errors are coming from the proxy layer or from tunnelling to the target origin. + """ + + class BaseHTTPSConnection(BaseHTTPConnection, Protocol): + default_port: typing.ClassVar[int] + default_socket_options: typing.ClassVar[_TYPE_SOCKET_OPTIONS] + + # Certificate verification methods + cert_reqs: int | str | None + assert_hostname: None | str | typing.Literal[False] + assert_fingerprint: str | None + ssl_context: ssl.SSLContext | None + + # Trusted CAs + ca_certs: str | None + ca_cert_dir: str | None + ca_cert_data: None | str | bytes + + # TLS version + ssl_minimum_version: int | None + ssl_maximum_version: int | None + ssl_version: int | str | None # Deprecated + + # Client certificates + cert_file: str | None + key_file: str | None + key_password: str | None + + def __init__( + self, + host: str, + port: int | None = None, + *, + timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, + source_address: tuple[str, int] | None = None, + blocksize: int = 16384, + socket_options: _TYPE_SOCKET_OPTIONS | None = ..., + proxy: Url | None = None, + proxy_config: ProxyConfig | None = None, + cert_reqs: int | str | None = None, + assert_hostname: None | str | typing.Literal[False] = None, + assert_fingerprint: str | None = None, + server_hostname: str | None = None, + ssl_context: ssl.SSLContext | None = None, + ca_certs: str | None = None, + ca_cert_dir: str | None = None, + ca_cert_data: None | str | bytes = None, + ssl_minimum_version: int | None = None, + ssl_maximum_version: int | None = None, + ssl_version: int | str | None = None, # Deprecated + cert_file: str | None = None, + key_file: str | None = None, + key_password: str | None = None, + ) -> None: ... diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/_collections.py b/apigw-private-cdn-acm/acm-certificate/urllib3/_collections.py new file mode 100644 index 000000000..1b6c13642 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/_collections.py @@ -0,0 +1,479 @@ +from __future__ import annotations + +import typing +from collections import OrderedDict +from enum import Enum, auto +from threading import RLock + +if typing.TYPE_CHECKING: + # We can only import Protocol if TYPE_CHECKING because it's a development + # dependency, and is not available at runtime. + from typing import Protocol + + from typing_extensions import Self + + class HasGettableStringKeys(Protocol): + def keys(self) -> typing.Iterator[str]: ... + + def __getitem__(self, key: str) -> str: ... + + +__all__ = ["RecentlyUsedContainer", "HTTPHeaderDict"] + + +# Key type +_KT = typing.TypeVar("_KT") +# Value type +_VT = typing.TypeVar("_VT") +# Default type +_DT = typing.TypeVar("_DT") + +ValidHTTPHeaderSource = typing.Union[ + "HTTPHeaderDict", + typing.Mapping[str, str], + typing.Iterable[tuple[str, str]], + "HasGettableStringKeys", +] + + +class _Sentinel(Enum): + not_passed = auto() + + +def ensure_can_construct_http_header_dict( + potential: object, +) -> ValidHTTPHeaderSource | None: + if isinstance(potential, HTTPHeaderDict): + return potential + elif isinstance(potential, typing.Mapping): + # Full runtime checking of the contents of a Mapping is expensive, so for the + # purposes of typechecking, we assume that any Mapping is the right shape. + return typing.cast(typing.Mapping[str, str], potential) + elif isinstance(potential, typing.Iterable): + # Similarly to Mapping, full runtime checking of the contents of an Iterable is + # expensive, so for the purposes of typechecking, we assume that any Iterable + # is the right shape. + return typing.cast(typing.Iterable[tuple[str, str]], potential) + elif hasattr(potential, "keys") and hasattr(potential, "__getitem__"): + return typing.cast("HasGettableStringKeys", potential) + else: + return None + + +class RecentlyUsedContainer(typing.Generic[_KT, _VT], typing.MutableMapping[_KT, _VT]): + """ + Provides a thread-safe dict-like container which maintains up to + ``maxsize`` keys while throwing away the least-recently-used keys beyond + ``maxsize``. + + :param maxsize: + Maximum number of recent elements to retain. + + :param dispose_func: + Every time an item is evicted from the container, + ``dispose_func(value)`` is called. Callback which will get called + """ + + _container: typing.OrderedDict[_KT, _VT] + _maxsize: int + dispose_func: typing.Callable[[_VT], None] | None + lock: RLock + + def __init__( + self, + maxsize: int = 10, + dispose_func: typing.Callable[[_VT], None] | None = None, + ) -> None: + super().__init__() + self._maxsize = maxsize + self.dispose_func = dispose_func + self._container = OrderedDict() + self.lock = RLock() + + def __getitem__(self, key: _KT) -> _VT: + # Re-insert the item, moving it to the end of the eviction line. + with self.lock: + item = self._container.pop(key) + self._container[key] = item + return item + + def __setitem__(self, key: _KT, value: _VT) -> None: + evicted_item = None + with self.lock: + # Possibly evict the existing value of 'key' + try: + # If the key exists, we'll overwrite it, which won't change the + # size of the pool. Because accessing a key should move it to + # the end of the eviction line, we pop it out first. + evicted_item = key, self._container.pop(key) + self._container[key] = value + except KeyError: + # When the key does not exist, we insert the value first so that + # evicting works in all cases, including when self._maxsize is 0 + self._container[key] = value + if len(self._container) > self._maxsize: + # If we didn't evict an existing value, and we've hit our maximum + # size, then we have to evict the least recently used item from + # the beginning of the container. + evicted_item = self._container.popitem(last=False) + + # After releasing the lock on the pool, dispose of any evicted value. + if evicted_item is not None and self.dispose_func: + _, evicted_value = evicted_item + self.dispose_func(evicted_value) + + def __delitem__(self, key: _KT) -> None: + with self.lock: + value = self._container.pop(key) + + if self.dispose_func: + self.dispose_func(value) + + def __len__(self) -> int: + with self.lock: + return len(self._container) + + def __iter__(self) -> typing.NoReturn: + raise NotImplementedError( + "Iteration over this class is unlikely to be threadsafe." + ) + + def clear(self) -> None: + with self.lock: + # Copy pointers to all values, then wipe the mapping + values = list(self._container.values()) + self._container.clear() + + if self.dispose_func: + for value in values: + self.dispose_func(value) + + def keys(self) -> set[_KT]: # type: ignore[override] + with self.lock: + return set(self._container.keys()) + + +class HTTPHeaderDictItemView(set[tuple[str, str]]): + """ + HTTPHeaderDict is unusual for a Mapping[str, str] in that it has two modes of + address. + + If we directly try to get an item with a particular name, we will get a string + back that is the concatenated version of all the values: + + >>> d['X-Header-Name'] + 'Value1, Value2, Value3' + + However, if we iterate over an HTTPHeaderDict's items, we will optionally combine + these values based on whether combine=True was called when building up the dictionary + + >>> d = HTTPHeaderDict({"A": "1", "B": "foo"}) + >>> d.add("A", "2", combine=True) + >>> d.add("B", "bar") + >>> list(d.items()) + [ + ('A', '1, 2'), + ('B', 'foo'), + ('B', 'bar'), + ] + + This class conforms to the interface required by the MutableMapping ABC while + also giving us the nonstandard iteration behavior we want; items with duplicate + keys, ordered by time of first insertion. + """ + + _headers: HTTPHeaderDict + + def __init__(self, headers: HTTPHeaderDict) -> None: + self._headers = headers + + def __len__(self) -> int: + return len(list(self._headers.iteritems())) + + def __iter__(self) -> typing.Iterator[tuple[str, str]]: + return self._headers.iteritems() + + def __contains__(self, item: object) -> bool: + if isinstance(item, tuple) and len(item) == 2: + passed_key, passed_val = item + if isinstance(passed_key, str) and isinstance(passed_val, str): + return self._headers._has_value_for_header(passed_key, passed_val) + return False + + +class HTTPHeaderDict(typing.MutableMapping[str, str]): + """ + :param headers: + An iterable of field-value pairs. Must not contain multiple field names + when compared case-insensitively. + + :param kwargs: + Additional field-value pairs to pass in to ``dict.update``. + + A ``dict`` like container for storing HTTP Headers. + + Field names are stored and compared case-insensitively in compliance with + RFC 7230. Iteration provides the first case-sensitive key seen for each + case-insensitive pair. + + Using ``__setitem__`` syntax overwrites fields that compare equal + case-insensitively in order to maintain ``dict``'s api. For fields that + compare equal, instead create a new ``HTTPHeaderDict`` and use ``.add`` + in a loop. + + If multiple fields that are equal case-insensitively are passed to the + constructor or ``.update``, the behavior is undefined and some will be + lost. + + >>> headers = HTTPHeaderDict() + >>> headers.add('Set-Cookie', 'foo=bar') + >>> headers.add('set-cookie', 'baz=quxx') + >>> headers['content-length'] = '7' + >>> headers['SET-cookie'] + 'foo=bar, baz=quxx' + >>> headers['Content-Length'] + '7' + """ + + _container: typing.MutableMapping[str, list[str]] + + def __init__(self, headers: ValidHTTPHeaderSource | None = None, **kwargs: str): + super().__init__() + self._container = {} # 'dict' is insert-ordered + if headers is not None: + if isinstance(headers, HTTPHeaderDict): + self._copy_from(headers) + else: + self.extend(headers) + if kwargs: + self.extend(kwargs) + + def __setitem__(self, key: str, val: str) -> None: + # avoid a bytes/str comparison by decoding before httplib + if isinstance(key, bytes): + key = key.decode("latin-1") + self._container[key.lower()] = [key, val] + + def __getitem__(self, key: str) -> str: + val = self._container[key.lower()] + return ", ".join(val[1:]) + + def __delitem__(self, key: str) -> None: + del self._container[key.lower()] + + def __contains__(self, key: object) -> bool: + if isinstance(key, str): + return key.lower() in self._container + return False + + def setdefault(self, key: str, default: str = "") -> str: + return super().setdefault(key, default) + + def __eq__(self, other: object) -> bool: + maybe_constructable = ensure_can_construct_http_header_dict(other) + if maybe_constructable is None: + return False + else: + other_as_http_header_dict = type(self)(maybe_constructable) + + return {k.lower(): v for k, v in self.itermerged()} == { + k.lower(): v for k, v in other_as_http_header_dict.itermerged() + } + + def __ne__(self, other: object) -> bool: + return not self.__eq__(other) + + def __len__(self) -> int: + return len(self._container) + + def __iter__(self) -> typing.Iterator[str]: + # Only provide the originally cased names + for vals in self._container.values(): + yield vals[0] + + def discard(self, key: str) -> None: + try: + del self[key] + except KeyError: + pass + + def add(self, key: str, val: str, *, combine: bool = False) -> None: + """Adds a (name, value) pair, doesn't overwrite the value if it already + exists. + + If this is called with combine=True, instead of adding a new header value + as a distinct item during iteration, this will instead append the value to + any existing header value with a comma. If no existing header value exists + for the key, then the value will simply be added, ignoring the combine parameter. + + >>> headers = HTTPHeaderDict(foo='bar') + >>> headers.add('Foo', 'baz') + >>> headers['foo'] + 'bar, baz' + >>> list(headers.items()) + [('foo', 'bar'), ('foo', 'baz')] + >>> headers.add('foo', 'quz', combine=True) + >>> list(headers.items()) + [('foo', 'bar, baz, quz')] + """ + # avoid a bytes/str comparison by decoding before httplib + if isinstance(key, bytes): + key = key.decode("latin-1") + key_lower = key.lower() + new_vals = [key, val] + # Keep the common case aka no item present as fast as possible + vals = self._container.setdefault(key_lower, new_vals) + if new_vals is not vals: + # if there are values here, then there is at least the initial + # key/value pair + assert len(vals) >= 2 + if combine: + vals[-1] = vals[-1] + ", " + val + else: + vals.append(val) + + def extend(self, *args: ValidHTTPHeaderSource, **kwargs: str) -> None: + """Generic import function for any type of header-like object. + Adapted version of MutableMapping.update in order to insert items + with self.add instead of self.__setitem__ + """ + if len(args) > 1: + raise TypeError( + f"extend() takes at most 1 positional arguments ({len(args)} given)" + ) + other = args[0] if len(args) >= 1 else () + + if isinstance(other, HTTPHeaderDict): + for key, val in other.iteritems(): + self.add(key, val) + elif isinstance(other, typing.Mapping): + for key, val in other.items(): + self.add(key, val) + elif isinstance(other, typing.Iterable): + other = typing.cast(typing.Iterable[tuple[str, str]], other) + for key, value in other: + self.add(key, value) + elif hasattr(other, "keys") and hasattr(other, "__getitem__"): + # THIS IS NOT A TYPESAFE BRANCH + # In this branch, the object has a `keys` attr but is not a Mapping or any of + # the other types indicated in the method signature. We do some stuff with + # it as though it partially implements the Mapping interface, but we're not + # doing that stuff safely AT ALL. + for key in other.keys(): + self.add(key, other[key]) + + for key, value in kwargs.items(): + self.add(key, value) + + @typing.overload + def getlist(self, key: str) -> list[str]: ... + + @typing.overload + def getlist(self, key: str, default: _DT) -> list[str] | _DT: ... + + def getlist( + self, key: str, default: _Sentinel | _DT = _Sentinel.not_passed + ) -> list[str] | _DT: + """Returns a list of all the values for the named field. Returns an + empty list if the key doesn't exist.""" + try: + vals = self._container[key.lower()] + except KeyError: + if default is _Sentinel.not_passed: + # _DT is unbound; empty list is instance of List[str] + return [] + # _DT is bound; default is instance of _DT + return default + else: + # _DT may or may not be bound; vals[1:] is instance of List[str], which + # meets our external interface requirement of `Union[List[str], _DT]`. + return vals[1:] + + def _prepare_for_method_change(self) -> Self: + """ + Remove content-specific header fields before changing the request + method to GET or HEAD according to RFC 9110, Section 15.4. + """ + content_specific_headers = [ + "Content-Encoding", + "Content-Language", + "Content-Location", + "Content-Type", + "Content-Length", + "Digest", + "Last-Modified", + ] + for header in content_specific_headers: + self.discard(header) + return self + + # Backwards compatibility for httplib + getheaders = getlist + getallmatchingheaders = getlist + iget = getlist + + # Backwards compatibility for http.cookiejar + get_all = getlist + + def __repr__(self) -> str: + return f"{type(self).__name__}({dict(self.itermerged())})" + + def _copy_from(self, other: HTTPHeaderDict) -> None: + for key in other: + val = other.getlist(key) + self._container[key.lower()] = [key, *val] + + def copy(self) -> Self: + clone = type(self)() + clone._copy_from(self) + return clone + + def iteritems(self) -> typing.Iterator[tuple[str, str]]: + """Iterate over all header lines, including duplicate ones.""" + for key in self: + vals = self._container[key.lower()] + for val in vals[1:]: + yield vals[0], val + + def itermerged(self) -> typing.Iterator[tuple[str, str]]: + """Iterate over all headers, merging duplicate ones together.""" + for key in self: + val = self._container[key.lower()] + yield val[0], ", ".join(val[1:]) + + def items(self) -> HTTPHeaderDictItemView: # type: ignore[override] + return HTTPHeaderDictItemView(self) + + def _has_value_for_header(self, header_name: str, potential_value: str) -> bool: + if header_name in self: + return potential_value in self._container[header_name.lower()][1:] + return False + + def __ior__(self, other: object) -> HTTPHeaderDict: + # Supports extending a header dict in-place using operator |= + # combining items with add instead of __setitem__ + maybe_constructable = ensure_can_construct_http_header_dict(other) + if maybe_constructable is None: + return NotImplemented + self.extend(maybe_constructable) + return self + + def __or__(self, other: object) -> Self: + # Supports merging header dicts using operator | + # combining items with add instead of __setitem__ + maybe_constructable = ensure_can_construct_http_header_dict(other) + if maybe_constructable is None: + return NotImplemented + result = self.copy() + result.extend(maybe_constructable) + return result + + def __ror__(self, other: object) -> Self: + # Supports merging header dicts using operator | when other is on left side + # combining items with add instead of __setitem__ + maybe_constructable = ensure_can_construct_http_header_dict(other) + if maybe_constructable is None: + return NotImplemented + result = type(self)(maybe_constructable) + result.extend(self) + return result diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/_request_methods.py b/apigw-private-cdn-acm/acm-certificate/urllib3/_request_methods.py new file mode 100644 index 000000000..297c271bf --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/_request_methods.py @@ -0,0 +1,278 @@ +from __future__ import annotations + +import json as _json +import typing +from urllib.parse import urlencode + +from ._base_connection import _TYPE_BODY +from ._collections import HTTPHeaderDict +from .filepost import _TYPE_FIELDS, encode_multipart_formdata +from .response import BaseHTTPResponse + +__all__ = ["RequestMethods"] + +_TYPE_ENCODE_URL_FIELDS = typing.Union[ + typing.Sequence[tuple[str, typing.Union[str, bytes]]], + typing.Mapping[str, typing.Union[str, bytes]], +] + + +class RequestMethods: + """ + Convenience mixin for classes who implement a :meth:`urlopen` method, such + as :class:`urllib3.HTTPConnectionPool` and + :class:`urllib3.PoolManager`. + + Provides behavior for making common types of HTTP request methods and + decides which type of request field encoding to use. + + Specifically, + + :meth:`.request_encode_url` is for sending requests whose fields are + encoded in the URL (such as GET, HEAD, DELETE). + + :meth:`.request_encode_body` is for sending requests whose fields are + encoded in the *body* of the request using multipart or www-form-urlencoded + (such as for POST, PUT, PATCH). + + :meth:`.request` is for making any kind of request, it will look up the + appropriate encoding format and use one of the above two methods to make + the request. + + Initializer parameters: + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + """ + + _encode_url_methods = {"DELETE", "GET", "HEAD", "OPTIONS"} + + def __init__(self, headers: typing.Mapping[str, str] | None = None) -> None: + self.headers = headers or {} + + def urlopen( + self, + method: str, + url: str, + body: _TYPE_BODY | None = None, + headers: typing.Mapping[str, str] | None = None, + encode_multipart: bool = True, + multipart_boundary: str | None = None, + **kw: typing.Any, + ) -> BaseHTTPResponse: # Abstract + raise NotImplementedError( + "Classes extending RequestMethods must implement " + "their own ``urlopen`` method." + ) + + def request( + self, + method: str, + url: str, + body: _TYPE_BODY | None = None, + fields: _TYPE_FIELDS | None = None, + headers: typing.Mapping[str, str] | None = None, + json: typing.Any | None = None, + **urlopen_kw: typing.Any, + ) -> BaseHTTPResponse: + """ + Make a request using :meth:`urlopen` with the appropriate encoding of + ``fields`` based on the ``method`` used. + + This is a convenience method that requires the least amount of manual + effort. It can be used in most situations, while still having the + option to drop down to more specific methods when necessary, such as + :meth:`request_encode_url`, :meth:`request_encode_body`, + or even the lowest level :meth:`urlopen`. + + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + + :param url: + The URL to perform the request on. + + :param body: + Data to send in the request body, either :class:`str`, :class:`bytes`, + an iterable of :class:`str`/:class:`bytes`, or a file-like object. + + :param fields: + Data to encode and send in the URL or request body, depending on ``method``. + + :param headers: + Dictionary of custom headers to send, such as User-Agent, + If-None-Match, etc. If None, pool headers are used. If provided, + these headers completely replace any pool-specific headers. + + :param json: + Data to encode and send as JSON with UTF-encoded in the request body. + The ``"Content-Type"`` header will be set to ``"application/json"`` + unless specified otherwise. + """ + method = method.upper() + + if json is not None and body is not None: + raise TypeError( + "request got values for both 'body' and 'json' parameters which are mutually exclusive" + ) + + if json is not None: + if headers is None: + headers = self.headers + + if not ("content-type" in map(str.lower, headers.keys())): + headers = HTTPHeaderDict(headers) + headers["Content-Type"] = "application/json" + + body = _json.dumps(json, separators=(",", ":"), ensure_ascii=False).encode( + "utf-8" + ) + + if body is not None: + urlopen_kw["body"] = body + + if method in self._encode_url_methods: + return self.request_encode_url( + method, + url, + fields=fields, # type: ignore[arg-type] + headers=headers, + **urlopen_kw, + ) + else: + return self.request_encode_body( + method, url, fields=fields, headers=headers, **urlopen_kw + ) + + def request_encode_url( + self, + method: str, + url: str, + fields: _TYPE_ENCODE_URL_FIELDS | None = None, + headers: typing.Mapping[str, str] | None = None, + **urlopen_kw: str, + ) -> BaseHTTPResponse: + """ + Make a request using :meth:`urlopen` with the ``fields`` encoded in + the url. This is useful for request methods like GET, HEAD, DELETE, etc. + + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + + :param url: + The URL to perform the request on. + + :param fields: + Data to encode and send in the URL. + + :param headers: + Dictionary of custom headers to send, such as User-Agent, + If-None-Match, etc. If None, pool headers are used. If provided, + these headers completely replace any pool-specific headers. + """ + if headers is None: + headers = self.headers + + extra_kw: dict[str, typing.Any] = {"headers": headers} + extra_kw.update(urlopen_kw) + + if fields: + url += "?" + urlencode(fields) + + return self.urlopen(method, url, **extra_kw) + + def request_encode_body( + self, + method: str, + url: str, + fields: _TYPE_FIELDS | None = None, + headers: typing.Mapping[str, str] | None = None, + encode_multipart: bool = True, + multipart_boundary: str | None = None, + **urlopen_kw: str, + ) -> BaseHTTPResponse: + """ + Make a request using :meth:`urlopen` with the ``fields`` encoded in + the body. This is useful for request methods like POST, PUT, PATCH, etc. + + When ``encode_multipart=True`` (default), then + :func:`urllib3.encode_multipart_formdata` is used to encode + the payload with the appropriate content type. Otherwise + :func:`urllib.parse.urlencode` is used with the + 'application/x-www-form-urlencoded' content type. + + Multipart encoding must be used when posting files, and it's reasonably + safe to use it in other times too. However, it may break request + signing, such as with OAuth. + + Supports an optional ``fields`` parameter of key/value strings AND + key/filetuple. A filetuple is a (filename, data, MIME type) tuple where + the MIME type is optional. For example:: + + fields = { + 'foo': 'bar', + 'fakefile': ('foofile.txt', 'contents of foofile'), + 'realfile': ('barfile.txt', open('realfile').read()), + 'typedfile': ('bazfile.bin', open('bazfile').read(), + 'image/jpeg'), + 'nonamefile': 'contents of nonamefile field', + } + + When uploading a file, providing a filename (the first parameter of the + tuple) is optional but recommended to best mimic behavior of browsers. + + Note that if ``headers`` are supplied, the 'Content-Type' header will + be overwritten because it depends on the dynamic random boundary string + which is used to compose the body of the request. The random boundary + string can be explicitly set with the ``multipart_boundary`` parameter. + + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + + :param url: + The URL to perform the request on. + + :param fields: + Data to encode and send in the request body. + + :param headers: + Dictionary of custom headers to send, such as User-Agent, + If-None-Match, etc. If None, pool headers are used. If provided, + these headers completely replace any pool-specific headers. + + :param encode_multipart: + If True, encode the ``fields`` using the multipart/form-data MIME + format. + + :param multipart_boundary: + If not specified, then a random boundary will be generated using + :func:`urllib3.filepost.choose_boundary`. + """ + if headers is None: + headers = self.headers + + extra_kw: dict[str, typing.Any] = {"headers": HTTPHeaderDict(headers)} + body: bytes | str + + if fields: + if "body" in urlopen_kw: + raise TypeError( + "request got values for both 'fields' and 'body', can only specify one." + ) + + if encode_multipart: + body, content_type = encode_multipart_formdata( + fields, boundary=multipart_boundary + ) + else: + body, content_type = ( + urlencode(fields), # type: ignore[arg-type] + "application/x-www-form-urlencoded", + ) + + extra_kw["body"] = body + extra_kw["headers"].setdefault("Content-Type", content_type) + + extra_kw.update(urlopen_kw) + + return self.urlopen(method, url, **extra_kw) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/_version.py b/apigw-private-cdn-acm/acm-certificate/urllib3/_version.py new file mode 100644 index 000000000..af6144bb2 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/_version.py @@ -0,0 +1,16 @@ +# file generated by setuptools_scm +# don't change, don't track in version control +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Tuple, Union + VERSION_TUPLE = Tuple[Union[int, str], ...] +else: + VERSION_TUPLE = object + +version: str +__version__: str +__version_tuple__: VERSION_TUPLE +version_tuple: VERSION_TUPLE + +__version__ = version = '2.3.0' +__version_tuple__ = version_tuple = (2, 3, 0) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/connection.py b/apigw-private-cdn-acm/acm-certificate/urllib3/connection.py new file mode 100644 index 000000000..591ac407b --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/connection.py @@ -0,0 +1,1044 @@ +from __future__ import annotations + +import datetime +import http.client +import logging +import os +import re +import socket +import sys +import threading +import typing +import warnings +from http.client import HTTPConnection as _HTTPConnection +from http.client import HTTPException as HTTPException # noqa: F401 +from http.client import ResponseNotReady +from socket import timeout as SocketTimeout + +if typing.TYPE_CHECKING: + from .response import HTTPResponse + from .util.ssl_ import _TYPE_PEER_CERT_RET_DICT + from .util.ssltransport import SSLTransport + +from ._collections import HTTPHeaderDict +from .http2 import probe as http2_probe +from .util.response import assert_header_parsing +from .util.timeout import _DEFAULT_TIMEOUT, _TYPE_TIMEOUT, Timeout +from .util.util import to_str +from .util.wait import wait_for_read + +try: # Compiled with SSL? + import ssl + + BaseSSLError = ssl.SSLError +except (ImportError, AttributeError): + ssl = None # type: ignore[assignment] + + class BaseSSLError(BaseException): # type: ignore[no-redef] + pass + + +from ._base_connection import _TYPE_BODY +from ._base_connection import ProxyConfig as ProxyConfig +from ._base_connection import _ResponseOptions as _ResponseOptions +from ._version import __version__ +from .exceptions import ( + ConnectTimeoutError, + HeaderParsingError, + NameResolutionError, + NewConnectionError, + ProxyError, + SystemTimeWarning, +) +from .util import SKIP_HEADER, SKIPPABLE_HEADERS, connection, ssl_ +from .util.request import body_to_chunks +from .util.ssl_ import assert_fingerprint as _assert_fingerprint +from .util.ssl_ import ( + create_urllib3_context, + is_ipaddress, + resolve_cert_reqs, + resolve_ssl_version, + ssl_wrap_socket, +) +from .util.ssl_match_hostname import CertificateError, match_hostname +from .util.url import Url + +# Not a no-op, we're adding this to the namespace so it can be imported. +ConnectionError = ConnectionError +BrokenPipeError = BrokenPipeError + + +log = logging.getLogger(__name__) + +port_by_scheme = {"http": 80, "https": 443} + +# When it comes time to update this value as a part of regular maintenance +# (ie test_recent_date is failing) update it to ~6 months before the current date. +RECENT_DATE = datetime.date(2023, 6, 1) + +_CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]") + + +class HTTPConnection(_HTTPConnection): + """ + Based on :class:`http.client.HTTPConnection` but provides an extra constructor + backwards-compatibility layer between older and newer Pythons. + + Additional keyword parameters are used to configure attributes of the connection. + Accepted parameters include: + + - ``source_address``: Set the source address for the current connection. + - ``socket_options``: Set specific options on the underlying socket. If not specified, then + defaults are loaded from ``HTTPConnection.default_socket_options`` which includes disabling + Nagle's algorithm (sets TCP_NODELAY to 1) unless the connection is behind a proxy. + + For example, if you wish to enable TCP Keep Alive in addition to the defaults, + you might pass: + + .. code-block:: python + + HTTPConnection.default_socket_options + [ + (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), + ] + + Or you may want to disable the defaults by passing an empty list (e.g., ``[]``). + """ + + default_port: typing.ClassVar[int] = port_by_scheme["http"] # type: ignore[misc] + + #: Disable Nagle's algorithm by default. + #: ``[(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]`` + default_socket_options: typing.ClassVar[connection._TYPE_SOCKET_OPTIONS] = [ + (socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + ] + + #: Whether this connection verifies the host's certificate. + is_verified: bool = False + + #: Whether this proxy connection verified the proxy host's certificate. + # If no proxy is currently connected to the value will be ``None``. + proxy_is_verified: bool | None = None + + blocksize: int + source_address: tuple[str, int] | None + socket_options: connection._TYPE_SOCKET_OPTIONS | None + + _has_connected_to_proxy: bool + _response_options: _ResponseOptions | None + _tunnel_host: str | None + _tunnel_port: int | None + _tunnel_scheme: str | None + + def __init__( + self, + host: str, + port: int | None = None, + *, + timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, + source_address: tuple[str, int] | None = None, + blocksize: int = 16384, + socket_options: None | ( + connection._TYPE_SOCKET_OPTIONS + ) = default_socket_options, + proxy: Url | None = None, + proxy_config: ProxyConfig | None = None, + ) -> None: + super().__init__( + host=host, + port=port, + timeout=Timeout.resolve_default_timeout(timeout), + source_address=source_address, + blocksize=blocksize, + ) + self.socket_options = socket_options + self.proxy = proxy + self.proxy_config = proxy_config + + self._has_connected_to_proxy = False + self._response_options = None + self._tunnel_host: str | None = None + self._tunnel_port: int | None = None + self._tunnel_scheme: str | None = None + + @property + def host(self) -> str: + """ + Getter method to remove any trailing dots that indicate the hostname is an FQDN. + + In general, SSL certificates don't include the trailing dot indicating a + fully-qualified domain name, and thus, they don't validate properly when + checked against a domain name that includes the dot. In addition, some + servers may not expect to receive the trailing dot when provided. + + However, the hostname with trailing dot is critical to DNS resolution; doing a + lookup with the trailing dot will properly only resolve the appropriate FQDN, + whereas a lookup without a trailing dot will search the system's search domain + list. Thus, it's important to keep the original host around for use only in + those cases where it's appropriate (i.e., when doing DNS lookup to establish the + actual TCP connection across which we're going to send HTTP requests). + """ + return self._dns_host.rstrip(".") + + @host.setter + def host(self, value: str) -> None: + """ + Setter for the `host` property. + + We assume that only urllib3 uses the _dns_host attribute; httplib itself + only uses `host`, and it seems reasonable that other libraries follow suit. + """ + self._dns_host = value + + def _new_conn(self) -> socket.socket: + """Establish a socket connection and set nodelay settings on it. + + :return: New socket connection. + """ + try: + sock = connection.create_connection( + (self._dns_host, self.port), + self.timeout, + source_address=self.source_address, + socket_options=self.socket_options, + ) + except socket.gaierror as e: + raise NameResolutionError(self.host, self, e) from e + except SocketTimeout as e: + raise ConnectTimeoutError( + self, + f"Connection to {self.host} timed out. (connect timeout={self.timeout})", + ) from e + + except OSError as e: + raise NewConnectionError( + self, f"Failed to establish a new connection: {e}" + ) from e + + sys.audit("http.client.connect", self, self.host, self.port) + + return sock + + def set_tunnel( + self, + host: str, + port: int | None = None, + headers: typing.Mapping[str, str] | None = None, + scheme: str = "http", + ) -> None: + if scheme not in ("http", "https"): + raise ValueError( + f"Invalid proxy scheme for tunneling: {scheme!r}, must be either 'http' or 'https'" + ) + super().set_tunnel(host, port=port, headers=headers) + self._tunnel_scheme = scheme + + if sys.version_info < (3, 11, 4): + + def _tunnel(self) -> None: + _MAXLINE = http.client._MAXLINE # type: ignore[attr-defined] + connect = b"CONNECT %s:%d HTTP/1.0\r\n" % ( # type: ignore[str-format] + self._tunnel_host.encode("ascii"), # type: ignore[union-attr] + self._tunnel_port, + ) + headers = [connect] + for header, value in self._tunnel_headers.items(): # type: ignore[attr-defined] + headers.append(f"{header}: {value}\r\n".encode("latin-1")) + headers.append(b"\r\n") + # Making a single send() call instead of one per line encourages + # the host OS to use a more optimal packet size instead of + # potentially emitting a series of small packets. + self.send(b"".join(headers)) + del headers + + response = self.response_class(self.sock, method=self._method) # type: ignore[attr-defined] + try: + (version, code, message) = response._read_status() # type: ignore[attr-defined] + + if code != http.HTTPStatus.OK: + self.close() + raise OSError(f"Tunnel connection failed: {code} {message.strip()}") + while True: + line = response.fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise http.client.LineTooLong("header line") + if not line: + # for sites which EOF without sending a trailer + break + if line in (b"\r\n", b"\n", b""): + break + + if self.debuglevel > 0: + print("header:", line.decode()) + finally: + response.close() + + def connect(self) -> None: + self.sock = self._new_conn() + if self._tunnel_host: + # If we're tunneling it means we're connected to our proxy. + self._has_connected_to_proxy = True + + # TODO: Fix tunnel so it doesn't depend on self.sock state. + self._tunnel() + + # If there's a proxy to be connected to we are fully connected. + # This is set twice (once above and here) due to forwarding proxies + # not using tunnelling. + self._has_connected_to_proxy = bool(self.proxy) + + if self._has_connected_to_proxy: + self.proxy_is_verified = False + + @property + def is_closed(self) -> bool: + return self.sock is None + + @property + def is_connected(self) -> bool: + if self.sock is None: + return False + return not wait_for_read(self.sock, timeout=0.0) + + @property + def has_connected_to_proxy(self) -> bool: + return self._has_connected_to_proxy + + @property + def proxy_is_forwarding(self) -> bool: + """ + Return True if a forwarding proxy is configured, else return False + """ + return bool(self.proxy) and self._tunnel_host is None + + @property + def proxy_is_tunneling(self) -> bool: + """ + Return True if a tunneling proxy is configured, else return False + """ + return self._tunnel_host is not None + + def close(self) -> None: + try: + super().close() + finally: + # Reset all stateful properties so connection + # can be re-used without leaking prior configs. + self.sock = None + self.is_verified = False + self.proxy_is_verified = None + self._has_connected_to_proxy = False + self._response_options = None + self._tunnel_host = None + self._tunnel_port = None + self._tunnel_scheme = None + + def putrequest( + self, + method: str, + url: str, + skip_host: bool = False, + skip_accept_encoding: bool = False, + ) -> None: + """""" + # Empty docstring because the indentation of CPython's implementation + # is broken but we don't want this method in our documentation. + match = _CONTAINS_CONTROL_CHAR_RE.search(method) + if match: + raise ValueError( + f"Method cannot contain non-token characters {method!r} (found at least {match.group()!r})" + ) + + return super().putrequest( + method, url, skip_host=skip_host, skip_accept_encoding=skip_accept_encoding + ) + + def putheader(self, header: str, *values: str) -> None: # type: ignore[override] + """""" + if not any(isinstance(v, str) and v == SKIP_HEADER for v in values): + super().putheader(header, *values) + elif to_str(header.lower()) not in SKIPPABLE_HEADERS: + skippable_headers = "', '".join( + [str.title(header) for header in sorted(SKIPPABLE_HEADERS)] + ) + raise ValueError( + f"urllib3.util.SKIP_HEADER only supports '{skippable_headers}'" + ) + + # `request` method's signature intentionally violates LSP. + # urllib3's API is different from `http.client.HTTPConnection` and the subclassing is only incidental. + def request( # type: ignore[override] + self, + method: str, + url: str, + body: _TYPE_BODY | None = None, + headers: typing.Mapping[str, str] | None = None, + *, + chunked: bool = False, + preload_content: bool = True, + decode_content: bool = True, + enforce_content_length: bool = True, + ) -> None: + # Update the inner socket's timeout value to send the request. + # This only triggers if the connection is re-used. + if self.sock is not None: + self.sock.settimeout(self.timeout) + + # Store these values to be fed into the HTTPResponse + # object later. TODO: Remove this in favor of a real + # HTTP lifecycle mechanism. + + # We have to store these before we call .request() + # because sometimes we can still salvage a response + # off the wire even if we aren't able to completely + # send the request body. + self._response_options = _ResponseOptions( + request_method=method, + request_url=url, + preload_content=preload_content, + decode_content=decode_content, + enforce_content_length=enforce_content_length, + ) + + if headers is None: + headers = {} + header_keys = frozenset(to_str(k.lower()) for k in headers) + skip_accept_encoding = "accept-encoding" in header_keys + skip_host = "host" in header_keys + self.putrequest( + method, url, skip_accept_encoding=skip_accept_encoding, skip_host=skip_host + ) + + # Transform the body into an iterable of sendall()-able chunks + # and detect if an explicit Content-Length is doable. + chunks_and_cl = body_to_chunks(body, method=method, blocksize=self.blocksize) + chunks = chunks_and_cl.chunks + content_length = chunks_and_cl.content_length + + # When chunked is explicit set to 'True' we respect that. + if chunked: + if "transfer-encoding" not in header_keys: + self.putheader("Transfer-Encoding", "chunked") + else: + # Detect whether a framing mechanism is already in use. If so + # we respect that value, otherwise we pick chunked vs content-length + # depending on the type of 'body'. + if "content-length" in header_keys: + chunked = False + elif "transfer-encoding" in header_keys: + chunked = True + + # Otherwise we go off the recommendation of 'body_to_chunks()'. + else: + chunked = False + if content_length is None: + if chunks is not None: + chunked = True + self.putheader("Transfer-Encoding", "chunked") + else: + self.putheader("Content-Length", str(content_length)) + + # Now that framing headers are out of the way we send all the other headers. + if "user-agent" not in header_keys: + self.putheader("User-Agent", _get_default_user_agent()) + for header, value in headers.items(): + self.putheader(header, value) + self.endheaders() + + # If we're given a body we start sending that in chunks. + if chunks is not None: + for chunk in chunks: + # Sending empty chunks isn't allowed for TE: chunked + # as it indicates the end of the body. + if not chunk: + continue + if isinstance(chunk, str): + chunk = chunk.encode("utf-8") + if chunked: + self.send(b"%x\r\n%b\r\n" % (len(chunk), chunk)) + else: + self.send(chunk) + + # Regardless of whether we have a body or not, if we're in + # chunked mode we want to send an explicit empty chunk. + if chunked: + self.send(b"0\r\n\r\n") + + def request_chunked( + self, + method: str, + url: str, + body: _TYPE_BODY | None = None, + headers: typing.Mapping[str, str] | None = None, + ) -> None: + """ + Alternative to the common request method, which sends the + body with chunked encoding and not as one block + """ + warnings.warn( + "HTTPConnection.request_chunked() is deprecated and will be removed " + "in urllib3 v2.1.0. Instead use HTTPConnection.request(..., chunked=True).", + category=DeprecationWarning, + stacklevel=2, + ) + self.request(method, url, body=body, headers=headers, chunked=True) + + def getresponse( # type: ignore[override] + self, + ) -> HTTPResponse: + """ + Get the response from the server. + + If the HTTPConnection is in the correct state, returns an instance of HTTPResponse or of whatever object is returned by the response_class variable. + + If a request has not been sent or if a previous response has not be handled, ResponseNotReady is raised. If the HTTP response indicates that the connection should be closed, then it will be closed before the response is returned. When the connection is closed, the underlying socket is closed. + """ + # Raise the same error as http.client.HTTPConnection + if self._response_options is None: + raise ResponseNotReady() + + # Reset this attribute for being used again. + resp_options = self._response_options + self._response_options = None + + # Since the connection's timeout value may have been updated + # we need to set the timeout on the socket. + self.sock.settimeout(self.timeout) + + # This is needed here to avoid circular import errors + from .response import HTTPResponse + + # Save a reference to the shutdown function before ownership is passed + # to httplib_response + # TODO should we implement it everywhere? + _shutdown = getattr(self.sock, "shutdown", None) + + # Get the response from http.client.HTTPConnection + httplib_response = super().getresponse() + + try: + assert_header_parsing(httplib_response.msg) + except (HeaderParsingError, TypeError) as hpe: + log.warning( + "Failed to parse headers (url=%s): %s", + _url_from_connection(self, resp_options.request_url), + hpe, + exc_info=True, + ) + + headers = HTTPHeaderDict(httplib_response.msg.items()) + + response = HTTPResponse( + body=httplib_response, + headers=headers, + status=httplib_response.status, + version=httplib_response.version, + version_string=getattr(self, "_http_vsn_str", "HTTP/?"), + reason=httplib_response.reason, + preload_content=resp_options.preload_content, + decode_content=resp_options.decode_content, + original_response=httplib_response, + enforce_content_length=resp_options.enforce_content_length, + request_method=resp_options.request_method, + request_url=resp_options.request_url, + sock_shutdown=_shutdown, + ) + return response + + +class HTTPSConnection(HTTPConnection): + """ + Many of the parameters to this constructor are passed to the underlying SSL + socket by means of :py:func:`urllib3.util.ssl_wrap_socket`. + """ + + default_port = port_by_scheme["https"] # type: ignore[misc] + + cert_reqs: int | str | None = None + ca_certs: str | None = None + ca_cert_dir: str | None = None + ca_cert_data: None | str | bytes = None + ssl_version: int | str | None = None + ssl_minimum_version: int | None = None + ssl_maximum_version: int | None = None + assert_fingerprint: str | None = None + _connect_callback: typing.Callable[..., None] | None = None + + def __init__( + self, + host: str, + port: int | None = None, + *, + timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, + source_address: tuple[str, int] | None = None, + blocksize: int = 16384, + socket_options: None | ( + connection._TYPE_SOCKET_OPTIONS + ) = HTTPConnection.default_socket_options, + proxy: Url | None = None, + proxy_config: ProxyConfig | None = None, + cert_reqs: int | str | None = None, + assert_hostname: None | str | typing.Literal[False] = None, + assert_fingerprint: str | None = None, + server_hostname: str | None = None, + ssl_context: ssl.SSLContext | None = None, + ca_certs: str | None = None, + ca_cert_dir: str | None = None, + ca_cert_data: None | str | bytes = None, + ssl_minimum_version: int | None = None, + ssl_maximum_version: int | None = None, + ssl_version: int | str | None = None, # Deprecated + cert_file: str | None = None, + key_file: str | None = None, + key_password: str | None = None, + ) -> None: + super().__init__( + host, + port=port, + timeout=timeout, + source_address=source_address, + blocksize=blocksize, + socket_options=socket_options, + proxy=proxy, + proxy_config=proxy_config, + ) + + self.key_file = key_file + self.cert_file = cert_file + self.key_password = key_password + self.ssl_context = ssl_context + self.server_hostname = server_hostname + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + self.ssl_version = ssl_version + self.ssl_minimum_version = ssl_minimum_version + self.ssl_maximum_version = ssl_maximum_version + self.ca_certs = ca_certs and os.path.expanduser(ca_certs) + self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir) + self.ca_cert_data = ca_cert_data + + # cert_reqs depends on ssl_context so calculate last. + if cert_reqs is None: + if self.ssl_context is not None: + cert_reqs = self.ssl_context.verify_mode + else: + cert_reqs = resolve_cert_reqs(None) + self.cert_reqs = cert_reqs + self._connect_callback = None + + def set_cert( + self, + key_file: str | None = None, + cert_file: str | None = None, + cert_reqs: int | str | None = None, + key_password: str | None = None, + ca_certs: str | None = None, + assert_hostname: None | str | typing.Literal[False] = None, + assert_fingerprint: str | None = None, + ca_cert_dir: str | None = None, + ca_cert_data: None | str | bytes = None, + ) -> None: + """ + This method should only be called once, before the connection is used. + """ + warnings.warn( + "HTTPSConnection.set_cert() is deprecated and will be removed " + "in urllib3 v2.1.0. Instead provide the parameters to the " + "HTTPSConnection constructor.", + category=DeprecationWarning, + stacklevel=2, + ) + + # If cert_reqs is not provided we'll assume CERT_REQUIRED unless we also + # have an SSLContext object in which case we'll use its verify_mode. + if cert_reqs is None: + if self.ssl_context is not None: + cert_reqs = self.ssl_context.verify_mode + else: + cert_reqs = resolve_cert_reqs(None) + + self.key_file = key_file + self.cert_file = cert_file + self.cert_reqs = cert_reqs + self.key_password = key_password + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + self.ca_certs = ca_certs and os.path.expanduser(ca_certs) + self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir) + self.ca_cert_data = ca_cert_data + + def connect(self) -> None: + # Today we don't need to be doing this step before the /actual/ socket + # connection, however in the future we'll need to decide whether to + # create a new socket or re-use an existing "shared" socket as a part + # of the HTTP/2 handshake dance. + if self._tunnel_host is not None and self._tunnel_port is not None: + probe_http2_host = self._tunnel_host + probe_http2_port = self._tunnel_port + else: + probe_http2_host = self.host + probe_http2_port = self.port + + # Check if the target origin supports HTTP/2. + # If the value comes back as 'None' it means that the current thread + # is probing for HTTP/2 support. Otherwise, we're waiting for another + # probe to complete, or we get a value right away. + target_supports_http2: bool | None + if "h2" in ssl_.ALPN_PROTOCOLS: + target_supports_http2 = http2_probe.acquire_and_get( + host=probe_http2_host, port=probe_http2_port + ) + else: + # If HTTP/2 isn't going to be offered it doesn't matter if + # the target supports HTTP/2. Don't want to make a probe. + target_supports_http2 = False + + if self._connect_callback is not None: + self._connect_callback( + "before connect", + thread_id=threading.get_ident(), + target_supports_http2=target_supports_http2, + ) + + try: + sock: socket.socket | ssl.SSLSocket + self.sock = sock = self._new_conn() + server_hostname: str = self.host + tls_in_tls = False + + # Do we need to establish a tunnel? + if self.proxy_is_tunneling: + # We're tunneling to an HTTPS origin so need to do TLS-in-TLS. + if self._tunnel_scheme == "https": + # _connect_tls_proxy will verify and assign proxy_is_verified + self.sock = sock = self._connect_tls_proxy(self.host, sock) + tls_in_tls = True + elif self._tunnel_scheme == "http": + self.proxy_is_verified = False + + # If we're tunneling it means we're connected to our proxy. + self._has_connected_to_proxy = True + + self._tunnel() + # Override the host with the one we're requesting data from. + server_hostname = typing.cast(str, self._tunnel_host) + + if self.server_hostname is not None: + server_hostname = self.server_hostname + + is_time_off = datetime.date.today() < RECENT_DATE + if is_time_off: + warnings.warn( + ( + f"System time is way off (before {RECENT_DATE}). This will probably " + "lead to SSL verification errors" + ), + SystemTimeWarning, + ) + + # Remove trailing '.' from fqdn hostnames to allow certificate validation + server_hostname_rm_dot = server_hostname.rstrip(".") + + sock_and_verified = _ssl_wrap_socket_and_match_hostname( + sock=sock, + cert_reqs=self.cert_reqs, + ssl_version=self.ssl_version, + ssl_minimum_version=self.ssl_minimum_version, + ssl_maximum_version=self.ssl_maximum_version, + ca_certs=self.ca_certs, + ca_cert_dir=self.ca_cert_dir, + ca_cert_data=self.ca_cert_data, + cert_file=self.cert_file, + key_file=self.key_file, + key_password=self.key_password, + server_hostname=server_hostname_rm_dot, + ssl_context=self.ssl_context, + tls_in_tls=tls_in_tls, + assert_hostname=self.assert_hostname, + assert_fingerprint=self.assert_fingerprint, + ) + self.sock = sock_and_verified.socket + + # If an error occurs during connection/handshake we may need to release + # our lock so another connection can probe the origin. + except BaseException: + if self._connect_callback is not None: + self._connect_callback( + "after connect failure", + thread_id=threading.get_ident(), + target_supports_http2=target_supports_http2, + ) + + if target_supports_http2 is None: + http2_probe.set_and_release( + host=probe_http2_host, port=probe_http2_port, supports_http2=None + ) + raise + + # If this connection doesn't know if the origin supports HTTP/2 + # we report back to the HTTP/2 probe our result. + if target_supports_http2 is None: + supports_http2 = sock_and_verified.socket.selected_alpn_protocol() == "h2" + http2_probe.set_and_release( + host=probe_http2_host, + port=probe_http2_port, + supports_http2=supports_http2, + ) + + # Forwarding proxies can never have a verified target since + # the proxy is the one doing the verification. Should instead + # use a CONNECT tunnel in order to verify the target. + # See: https://github.com/urllib3/urllib3/issues/3267. + if self.proxy_is_forwarding: + self.is_verified = False + else: + self.is_verified = sock_and_verified.is_verified + + # If there's a proxy to be connected to we are fully connected. + # This is set twice (once above and here) due to forwarding proxies + # not using tunnelling. + self._has_connected_to_proxy = bool(self.proxy) + + # Set `self.proxy_is_verified` unless it's already set while + # establishing a tunnel. + if self._has_connected_to_proxy and self.proxy_is_verified is None: + self.proxy_is_verified = sock_and_verified.is_verified + + def _connect_tls_proxy(self, hostname: str, sock: socket.socket) -> ssl.SSLSocket: + """ + Establish a TLS connection to the proxy using the provided SSL context. + """ + # `_connect_tls_proxy` is called when self._tunnel_host is truthy. + proxy_config = typing.cast(ProxyConfig, self.proxy_config) + ssl_context = proxy_config.ssl_context + sock_and_verified = _ssl_wrap_socket_and_match_hostname( + sock, + cert_reqs=self.cert_reqs, + ssl_version=self.ssl_version, + ssl_minimum_version=self.ssl_minimum_version, + ssl_maximum_version=self.ssl_maximum_version, + ca_certs=self.ca_certs, + ca_cert_dir=self.ca_cert_dir, + ca_cert_data=self.ca_cert_data, + server_hostname=hostname, + ssl_context=ssl_context, + assert_hostname=proxy_config.assert_hostname, + assert_fingerprint=proxy_config.assert_fingerprint, + # Features that aren't implemented for proxies yet: + cert_file=None, + key_file=None, + key_password=None, + tls_in_tls=False, + ) + self.proxy_is_verified = sock_and_verified.is_verified + return sock_and_verified.socket # type: ignore[return-value] + + +class _WrappedAndVerifiedSocket(typing.NamedTuple): + """ + Wrapped socket and whether the connection is + verified after the TLS handshake + """ + + socket: ssl.SSLSocket | SSLTransport + is_verified: bool + + +def _ssl_wrap_socket_and_match_hostname( + sock: socket.socket, + *, + cert_reqs: None | str | int, + ssl_version: None | str | int, + ssl_minimum_version: int | None, + ssl_maximum_version: int | None, + cert_file: str | None, + key_file: str | None, + key_password: str | None, + ca_certs: str | None, + ca_cert_dir: str | None, + ca_cert_data: None | str | bytes, + assert_hostname: None | str | typing.Literal[False], + assert_fingerprint: str | None, + server_hostname: str | None, + ssl_context: ssl.SSLContext | None, + tls_in_tls: bool = False, +) -> _WrappedAndVerifiedSocket: + """Logic for constructing an SSLContext from all TLS parameters, passing + that down into ssl_wrap_socket, and then doing certificate verification + either via hostname or fingerprint. This function exists to guarantee + that both proxies and targets have the same behavior when connecting via TLS. + """ + default_ssl_context = False + if ssl_context is None: + default_ssl_context = True + context = create_urllib3_context( + ssl_version=resolve_ssl_version(ssl_version), + ssl_minimum_version=ssl_minimum_version, + ssl_maximum_version=ssl_maximum_version, + cert_reqs=resolve_cert_reqs(cert_reqs), + ) + else: + context = ssl_context + + context.verify_mode = resolve_cert_reqs(cert_reqs) + + # In some cases, we want to verify hostnames ourselves + if ( + # `ssl` can't verify fingerprints or alternate hostnames + assert_fingerprint + or assert_hostname + # assert_hostname can be set to False to disable hostname checking + or assert_hostname is False + # We still support OpenSSL 1.0.2, which prevents us from verifying + # hostnames easily: https://github.com/pyca/pyopenssl/pull/933 + or ssl_.IS_PYOPENSSL + or not ssl_.HAS_NEVER_CHECK_COMMON_NAME + ): + context.check_hostname = False + + # Try to load OS default certs if none are given. We need to do the hasattr() check + # for custom pyOpenSSL SSLContext objects because they don't support + # load_default_certs(). + if ( + not ca_certs + and not ca_cert_dir + and not ca_cert_data + and default_ssl_context + and hasattr(context, "load_default_certs") + ): + context.load_default_certs() + + # Ensure that IPv6 addresses are in the proper format and don't have a + # scope ID. Python's SSL module fails to recognize scoped IPv6 addresses + # and interprets them as DNS hostnames. + if server_hostname is not None: + normalized = server_hostname.strip("[]") + if "%" in normalized: + normalized = normalized[: normalized.rfind("%")] + if is_ipaddress(normalized): + server_hostname = normalized + + ssl_sock = ssl_wrap_socket( + sock=sock, + keyfile=key_file, + certfile=cert_file, + key_password=key_password, + ca_certs=ca_certs, + ca_cert_dir=ca_cert_dir, + ca_cert_data=ca_cert_data, + server_hostname=server_hostname, + ssl_context=context, + tls_in_tls=tls_in_tls, + ) + + try: + if assert_fingerprint: + _assert_fingerprint( + ssl_sock.getpeercert(binary_form=True), assert_fingerprint + ) + elif ( + context.verify_mode != ssl.CERT_NONE + and not context.check_hostname + and assert_hostname is not False + ): + cert: _TYPE_PEER_CERT_RET_DICT = ssl_sock.getpeercert() # type: ignore[assignment] + + # Need to signal to our match_hostname whether to use 'commonName' or not. + # If we're using our own constructed SSLContext we explicitly set 'False' + # because PyPy hard-codes 'True' from SSLContext.hostname_checks_common_name. + if default_ssl_context: + hostname_checks_common_name = False + else: + hostname_checks_common_name = ( + getattr(context, "hostname_checks_common_name", False) or False + ) + + _match_hostname( + cert, + assert_hostname or server_hostname, # type: ignore[arg-type] + hostname_checks_common_name, + ) + + return _WrappedAndVerifiedSocket( + socket=ssl_sock, + is_verified=context.verify_mode == ssl.CERT_REQUIRED + or bool(assert_fingerprint), + ) + except BaseException: + ssl_sock.close() + raise + + +def _match_hostname( + cert: _TYPE_PEER_CERT_RET_DICT | None, + asserted_hostname: str, + hostname_checks_common_name: bool = False, +) -> None: + # Our upstream implementation of ssl.match_hostname() + # only applies this normalization to IP addresses so it doesn't + # match DNS SANs so we do the same thing! + stripped_hostname = asserted_hostname.strip("[]") + if is_ipaddress(stripped_hostname): + asserted_hostname = stripped_hostname + + try: + match_hostname(cert, asserted_hostname, hostname_checks_common_name) + except CertificateError as e: + log.warning( + "Certificate did not match expected hostname: %s. Certificate: %s", + asserted_hostname, + cert, + ) + # Add cert to exception and reraise so client code can inspect + # the cert when catching the exception, if they want to + e._peer_cert = cert # type: ignore[attr-defined] + raise + + +def _wrap_proxy_error(err: Exception, proxy_scheme: str | None) -> ProxyError: + # Look for the phrase 'wrong version number', if found + # then we should warn the user that we're very sure that + # this proxy is HTTP-only and they have a configuration issue. + error_normalized = " ".join(re.split("[^a-z]", str(err).lower())) + is_likely_http_proxy = ( + "wrong version number" in error_normalized + or "unknown protocol" in error_normalized + or "record layer failure" in error_normalized + ) + http_proxy_warning = ( + ". Your proxy appears to only use HTTP and not HTTPS, " + "try changing your proxy URL to be HTTP. See: " + "https://urllib3.readthedocs.io/en/latest/advanced-usage.html" + "#https-proxy-error-http-proxy" + ) + new_err = ProxyError( + f"Unable to connect to proxy" + f"{http_proxy_warning if is_likely_http_proxy and proxy_scheme == 'https' else ''}", + err, + ) + new_err.__cause__ = err + return new_err + + +def _get_default_user_agent() -> str: + return f"python-urllib3/{__version__}" + + +class DummyConnection: + """Used to detect a failed ConnectionCls import.""" + + +if not ssl: + HTTPSConnection = DummyConnection # type: ignore[misc, assignment] # noqa: F811 + + +VerifiedHTTPSConnection = HTTPSConnection + + +def _url_from_connection( + conn: HTTPConnection | HTTPSConnection, path: str | None = None +) -> str: + """Returns the URL from a given connection. This is mainly used for testing and logging.""" + + scheme = "https" if isinstance(conn, HTTPSConnection) else "http" + + return Url(scheme=scheme, host=conn.host, port=conn.port, path=path).url diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/connectionpool.py b/apigw-private-cdn-acm/acm-certificate/urllib3/connectionpool.py new file mode 100644 index 000000000..3a0685b4c --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/connectionpool.py @@ -0,0 +1,1178 @@ +from __future__ import annotations + +import errno +import logging +import queue +import sys +import typing +import warnings +import weakref +from socket import timeout as SocketTimeout +from types import TracebackType + +from ._base_connection import _TYPE_BODY +from ._collections import HTTPHeaderDict +from ._request_methods import RequestMethods +from .connection import ( + BaseSSLError, + BrokenPipeError, + DummyConnection, + HTTPConnection, + HTTPException, + HTTPSConnection, + ProxyConfig, + _wrap_proxy_error, +) +from .connection import port_by_scheme as port_by_scheme +from .exceptions import ( + ClosedPoolError, + EmptyPoolError, + FullPoolError, + HostChangedError, + InsecureRequestWarning, + LocationValueError, + MaxRetryError, + NewConnectionError, + ProtocolError, + ProxyError, + ReadTimeoutError, + SSLError, + TimeoutError, +) +from .response import BaseHTTPResponse +from .util.connection import is_connection_dropped +from .util.proxy import connection_requires_http_tunnel +from .util.request import _TYPE_BODY_POSITION, set_file_position +from .util.retry import Retry +from .util.ssl_match_hostname import CertificateError +from .util.timeout import _DEFAULT_TIMEOUT, _TYPE_DEFAULT, Timeout +from .util.url import Url, _encode_target +from .util.url import _normalize_host as normalize_host +from .util.url import parse_url +from .util.util import to_str + +if typing.TYPE_CHECKING: + import ssl + + from typing_extensions import Self + + from ._base_connection import BaseHTTPConnection, BaseHTTPSConnection + +log = logging.getLogger(__name__) + +_TYPE_TIMEOUT = typing.Union[Timeout, float, _TYPE_DEFAULT, None] + + +# Pool objects +class ConnectionPool: + """ + Base class for all connection pools, such as + :class:`.HTTPConnectionPool` and :class:`.HTTPSConnectionPool`. + + .. note:: + ConnectionPool.urlopen() does not normalize or percent-encode target URIs + which is useful if your target server doesn't support percent-encoded + target URIs. + """ + + scheme: str | None = None + QueueCls = queue.LifoQueue + + def __init__(self, host: str, port: int | None = None) -> None: + if not host: + raise LocationValueError("No host specified.") + + self.host = _normalize_host(host, scheme=self.scheme) + self.port = port + + # This property uses 'normalize_host()' (not '_normalize_host()') + # to avoid removing square braces around IPv6 addresses. + # This value is sent to `HTTPConnection.set_tunnel()` if called + # because square braces are required for HTTP CONNECT tunneling. + self._tunnel_host = normalize_host(host, scheme=self.scheme).lower() + + def __str__(self) -> str: + return f"{type(self).__name__}(host={self.host!r}, port={self.port!r})" + + def __enter__(self) -> Self: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> typing.Literal[False]: + self.close() + # Return False to re-raise any potential exceptions + return False + + def close(self) -> None: + """ + Close all pooled connections and disable the pool. + """ + + +# This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252 +_blocking_errnos = {errno.EAGAIN, errno.EWOULDBLOCK} + + +class HTTPConnectionPool(ConnectionPool, RequestMethods): + """ + Thread-safe connection pool for one host. + + :param host: + Host used for this HTTP Connection (e.g. "localhost"), passed into + :class:`http.client.HTTPConnection`. + + :param port: + Port used for this HTTP Connection (None is equivalent to 80), passed + into :class:`http.client.HTTPConnection`. + + :param timeout: + Socket timeout in seconds for each individual connection. This can + be a float or integer, which sets the timeout for the HTTP request, + or an instance of :class:`urllib3.util.Timeout` which gives you more + fine-grained control over request timeouts. After the constructor has + been parsed, this is always a `urllib3.util.Timeout` object. + + :param maxsize: + Number of connections to save that can be reused. More than 1 is useful + in multithreaded situations. If ``block`` is set to False, more + connections will be created but they will not be saved once they've + been used. + + :param block: + If set to True, no more than ``maxsize`` connections will be used at + a time. When no free connections are available, the call will block + until a connection has been released. This is a useful side effect for + particular multithreaded situations where one does not want to use more + than maxsize connections per host to prevent flooding. + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + + :param retries: + Retry configuration to use by default with requests in this pool. + + :param _proxy: + Parsed proxy URL, should not be used directly, instead, see + :class:`urllib3.ProxyManager` + + :param _proxy_headers: + A dictionary with proxy headers, should not be used directly, + instead, see :class:`urllib3.ProxyManager` + + :param \\**conn_kw: + Additional parameters are used to create fresh :class:`urllib3.connection.HTTPConnection`, + :class:`urllib3.connection.HTTPSConnection` instances. + """ + + scheme = "http" + ConnectionCls: type[BaseHTTPConnection] | type[BaseHTTPSConnection] = HTTPConnection + + def __init__( + self, + host: str, + port: int | None = None, + timeout: _TYPE_TIMEOUT | None = _DEFAULT_TIMEOUT, + maxsize: int = 1, + block: bool = False, + headers: typing.Mapping[str, str] | None = None, + retries: Retry | bool | int | None = None, + _proxy: Url | None = None, + _proxy_headers: typing.Mapping[str, str] | None = None, + _proxy_config: ProxyConfig | None = None, + **conn_kw: typing.Any, + ): + ConnectionPool.__init__(self, host, port) + RequestMethods.__init__(self, headers) + + if not isinstance(timeout, Timeout): + timeout = Timeout.from_float(timeout) + + if retries is None: + retries = Retry.DEFAULT + + self.timeout = timeout + self.retries = retries + + self.pool: queue.LifoQueue[typing.Any] | None = self.QueueCls(maxsize) + self.block = block + + self.proxy = _proxy + self.proxy_headers = _proxy_headers or {} + self.proxy_config = _proxy_config + + # Fill the queue up so that doing get() on it will block properly + for _ in range(maxsize): + self.pool.put(None) + + # These are mostly for testing and debugging purposes. + self.num_connections = 0 + self.num_requests = 0 + self.conn_kw = conn_kw + + if self.proxy: + # Enable Nagle's algorithm for proxies, to avoid packet fragmentation. + # We cannot know if the user has added default socket options, so we cannot replace the + # list. + self.conn_kw.setdefault("socket_options", []) + + self.conn_kw["proxy"] = self.proxy + self.conn_kw["proxy_config"] = self.proxy_config + + # Do not pass 'self' as callback to 'finalize'. + # Then the 'finalize' would keep an endless living (leak) to self. + # By just passing a reference to the pool allows the garbage collector + # to free self if nobody else has a reference to it. + pool = self.pool + + # Close all the HTTPConnections in the pool before the + # HTTPConnectionPool object is garbage collected. + weakref.finalize(self, _close_pool_connections, pool) + + def _new_conn(self) -> BaseHTTPConnection: + """ + Return a fresh :class:`HTTPConnection`. + """ + self.num_connections += 1 + log.debug( + "Starting new HTTP connection (%d): %s:%s", + self.num_connections, + self.host, + self.port or "80", + ) + + conn = self.ConnectionCls( + host=self.host, + port=self.port, + timeout=self.timeout.connect_timeout, + **self.conn_kw, + ) + return conn + + def _get_conn(self, timeout: float | None = None) -> BaseHTTPConnection: + """ + Get a connection. Will return a pooled connection if one is available. + + If no connections are available and :prop:`.block` is ``False``, then a + fresh connection is returned. + + :param timeout: + Seconds to wait before giving up and raising + :class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and + :prop:`.block` is ``True``. + """ + conn = None + + if self.pool is None: + raise ClosedPoolError(self, "Pool is closed.") + + try: + conn = self.pool.get(block=self.block, timeout=timeout) + + except AttributeError: # self.pool is None + raise ClosedPoolError(self, "Pool is closed.") from None # Defensive: + + except queue.Empty: + if self.block: + raise EmptyPoolError( + self, + "Pool is empty and a new connection can't be opened due to blocking mode.", + ) from None + pass # Oh well, we'll create a new connection then + + # If this is a persistent connection, check if it got disconnected + if conn and is_connection_dropped(conn): + log.debug("Resetting dropped connection: %s", self.host) + conn.close() + + return conn or self._new_conn() + + def _put_conn(self, conn: BaseHTTPConnection | None) -> None: + """ + Put a connection back into the pool. + + :param conn: + Connection object for the current host and port as returned by + :meth:`._new_conn` or :meth:`._get_conn`. + + If the pool is already full, the connection is closed and discarded + because we exceeded maxsize. If connections are discarded frequently, + then maxsize should be increased. + + If the pool is closed, then the connection will be closed and discarded. + """ + if self.pool is not None: + try: + self.pool.put(conn, block=False) + return # Everything is dandy, done. + except AttributeError: + # self.pool is None. + pass + except queue.Full: + # Connection never got put back into the pool, close it. + if conn: + conn.close() + + if self.block: + # This should never happen if you got the conn from self._get_conn + raise FullPoolError( + self, + "Pool reached maximum size and no more connections are allowed.", + ) from None + + log.warning( + "Connection pool is full, discarding connection: %s. Connection pool size: %s", + self.host, + self.pool.qsize(), + ) + + # Connection never got put back into the pool, close it. + if conn: + conn.close() + + def _validate_conn(self, conn: BaseHTTPConnection) -> None: + """ + Called right before a request is made, after the socket is created. + """ + + def _prepare_proxy(self, conn: BaseHTTPConnection) -> None: + # Nothing to do for HTTP connections. + pass + + def _get_timeout(self, timeout: _TYPE_TIMEOUT) -> Timeout: + """Helper that always returns a :class:`urllib3.util.Timeout`""" + if timeout is _DEFAULT_TIMEOUT: + return self.timeout.clone() + + if isinstance(timeout, Timeout): + return timeout.clone() + else: + # User passed us an int/float. This is for backwards compatibility, + # can be removed later + return Timeout.from_float(timeout) + + def _raise_timeout( + self, + err: BaseSSLError | OSError | SocketTimeout, + url: str, + timeout_value: _TYPE_TIMEOUT | None, + ) -> None: + """Is the error actually a timeout? Will raise a ReadTimeout or pass""" + + if isinstance(err, SocketTimeout): + raise ReadTimeoutError( + self, url, f"Read timed out. (read timeout={timeout_value})" + ) from err + + # See the above comment about EAGAIN in Python 3. + if hasattr(err, "errno") and err.errno in _blocking_errnos: + raise ReadTimeoutError( + self, url, f"Read timed out. (read timeout={timeout_value})" + ) from err + + def _make_request( + self, + conn: BaseHTTPConnection, + method: str, + url: str, + body: _TYPE_BODY | None = None, + headers: typing.Mapping[str, str] | None = None, + retries: Retry | None = None, + timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, + chunked: bool = False, + response_conn: BaseHTTPConnection | None = None, + preload_content: bool = True, + decode_content: bool = True, + enforce_content_length: bool = True, + ) -> BaseHTTPResponse: + """ + Perform a request on a given urllib connection object taken from our + pool. + + :param conn: + a connection from one of our connection pools + + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + + :param url: + The URL to perform the request on. + + :param body: + Data to send in the request body, either :class:`str`, :class:`bytes`, + an iterable of :class:`str`/:class:`bytes`, or a file-like object. + + :param headers: + Dictionary of custom headers to send, such as User-Agent, + If-None-Match, etc. If None, pool headers are used. If provided, + these headers completely replace any pool-specific headers. + + :param retries: + Configure the number of retries to allow before raising a + :class:`~urllib3.exceptions.MaxRetryError` exception. + + Pass ``None`` to retry until you receive a response. Pass a + :class:`~urllib3.util.retry.Retry` object for fine-grained control + over different types of retries. + Pass an integer number to retry connection errors that many times, + but no other types of errors. Pass zero to never retry. + + If ``False``, then retries are disabled and any exception is raised + immediately. Also, instead of raising a MaxRetryError on redirects, + the redirect response will be returned. + + :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. + + :param timeout: + If specified, overrides the default timeout for this one + request. It may be a float (in seconds) or an instance of + :class:`urllib3.util.Timeout`. + + :param chunked: + If True, urllib3 will send the body using chunked transfer + encoding. Otherwise, urllib3 will send the body using the standard + content-length form. Defaults to False. + + :param response_conn: + Set this to ``None`` if you will handle releasing the connection or + set the connection to have the response release it. + + :param preload_content: + If True, the response's body will be preloaded during construction. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param enforce_content_length: + Enforce content length checking. Body returned by server must match + value of Content-Length header, if present. Otherwise, raise error. + """ + self.num_requests += 1 + + timeout_obj = self._get_timeout(timeout) + timeout_obj.start_connect() + conn.timeout = Timeout.resolve_default_timeout(timeout_obj.connect_timeout) + + try: + # Trigger any extra validation we need to do. + try: + self._validate_conn(conn) + except (SocketTimeout, BaseSSLError) as e: + self._raise_timeout(err=e, url=url, timeout_value=conn.timeout) + raise + + # _validate_conn() starts the connection to an HTTPS proxy + # so we need to wrap errors with 'ProxyError' here too. + except ( + OSError, + NewConnectionError, + TimeoutError, + BaseSSLError, + CertificateError, + SSLError, + ) as e: + new_e: Exception = e + if isinstance(e, (BaseSSLError, CertificateError)): + new_e = SSLError(e) + # If the connection didn't successfully connect to it's proxy + # then there + if isinstance( + new_e, (OSError, NewConnectionError, TimeoutError, SSLError) + ) and (conn and conn.proxy and not conn.has_connected_to_proxy): + new_e = _wrap_proxy_error(new_e, conn.proxy.scheme) + raise new_e + + # conn.request() calls http.client.*.request, not the method in + # urllib3.request. It also calls makefile (recv) on the socket. + try: + conn.request( + method, + url, + body=body, + headers=headers, + chunked=chunked, + preload_content=preload_content, + decode_content=decode_content, + enforce_content_length=enforce_content_length, + ) + + # We are swallowing BrokenPipeError (errno.EPIPE) since the server is + # legitimately able to close the connection after sending a valid response. + # With this behaviour, the received response is still readable. + except BrokenPipeError: + pass + except OSError as e: + # MacOS/Linux + # EPROTOTYPE and ECONNRESET are needed on macOS + # https://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/ + # Condition changed later to emit ECONNRESET instead of only EPROTOTYPE. + if e.errno != errno.EPROTOTYPE and e.errno != errno.ECONNRESET: + raise + + # Reset the timeout for the recv() on the socket + read_timeout = timeout_obj.read_timeout + + if not conn.is_closed: + # In Python 3 socket.py will catch EAGAIN and return None when you + # try and read into the file pointer created by http.client, which + # instead raises a BadStatusLine exception. Instead of catching + # the exception and assuming all BadStatusLine exceptions are read + # timeouts, check for a zero timeout before making the request. + if read_timeout == 0: + raise ReadTimeoutError( + self, url, f"Read timed out. (read timeout={read_timeout})" + ) + conn.timeout = read_timeout + + # Receive the response from the server + try: + response = conn.getresponse() + except (BaseSSLError, OSError) as e: + self._raise_timeout(err=e, url=url, timeout_value=read_timeout) + raise + + # Set properties that are used by the pooling layer. + response.retries = retries + response._connection = response_conn # type: ignore[attr-defined] + response._pool = self # type: ignore[attr-defined] + + log.debug( + '%s://%s:%s "%s %s %s" %s %s', + self.scheme, + self.host, + self.port, + method, + url, + response.version_string, + response.status, + response.length_remaining, + ) + + return response + + def close(self) -> None: + """ + Close all pooled connections and disable the pool. + """ + if self.pool is None: + return + # Disable access to the pool + old_pool, self.pool = self.pool, None + + # Close all the HTTPConnections in the pool. + _close_pool_connections(old_pool) + + def is_same_host(self, url: str) -> bool: + """ + Check if the given ``url`` is a member of the same host as this + connection pool. + """ + if url.startswith("/"): + return True + + # TODO: Add optional support for socket.gethostbyname checking. + scheme, _, host, port, *_ = parse_url(url) + scheme = scheme or "http" + if host is not None: + host = _normalize_host(host, scheme=scheme) + + # Use explicit default port for comparison when none is given + if self.port and not port: + port = port_by_scheme.get(scheme) + elif not self.port and port == port_by_scheme.get(scheme): + port = None + + return (scheme, host, port) == (self.scheme, self.host, self.port) + + def urlopen( # type: ignore[override] + self, + method: str, + url: str, + body: _TYPE_BODY | None = None, + headers: typing.Mapping[str, str] | None = None, + retries: Retry | bool | int | None = None, + redirect: bool = True, + assert_same_host: bool = True, + timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, + pool_timeout: int | None = None, + release_conn: bool | None = None, + chunked: bool = False, + body_pos: _TYPE_BODY_POSITION | None = None, + preload_content: bool = True, + decode_content: bool = True, + **response_kw: typing.Any, + ) -> BaseHTTPResponse: + """ + Get a connection from the pool and perform an HTTP request. This is the + lowest level call for making a request, so you'll need to specify all + the raw details. + + .. note:: + + More commonly, it's appropriate to use a convenience method + such as :meth:`request`. + + .. note:: + + `release_conn` will only behave as expected if + `preload_content=False` because we want to make + `preload_content=False` the default behaviour someday soon without + breaking backwards compatibility. + + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + + :param url: + The URL to perform the request on. + + :param body: + Data to send in the request body, either :class:`str`, :class:`bytes`, + an iterable of :class:`str`/:class:`bytes`, or a file-like object. + + :param headers: + Dictionary of custom headers to send, such as User-Agent, + If-None-Match, etc. If None, pool headers are used. If provided, + these headers completely replace any pool-specific headers. + + :param retries: + Configure the number of retries to allow before raising a + :class:`~urllib3.exceptions.MaxRetryError` exception. + + If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a + :class:`~urllib3.util.retry.Retry` object for fine-grained control + over different types of retries. + Pass an integer number to retry connection errors that many times, + but no other types of errors. Pass zero to never retry. + + If ``False``, then retries are disabled and any exception is raised + immediately. Also, instead of raising a MaxRetryError on redirects, + the redirect response will be returned. + + :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. + + :param redirect: + If True, automatically handle redirects (status codes 301, 302, + 303, 307, 308). Each redirect counts as a retry. Disabling retries + will disable redirect, too. + + :param assert_same_host: + If ``True``, will make sure that the host of the pool requests is + consistent else will raise HostChangedError. When ``False``, you can + use the pool on an HTTP proxy and request foreign hosts. + + :param timeout: + If specified, overrides the default timeout for this one + request. It may be a float (in seconds) or an instance of + :class:`urllib3.util.Timeout`. + + :param pool_timeout: + If set and the pool is set to block=True, then this method will + block for ``pool_timeout`` seconds and raise EmptyPoolError if no + connection is available within the time period. + + :param bool preload_content: + If True, the response's body will be preloaded into memory. + + :param bool decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param release_conn: + If False, then the urlopen call will not release the connection + back into the pool once a response is received (but will release if + you read the entire contents of the response such as when + `preload_content=True`). This is useful if you're not preloading + the response's content immediately. You will need to call + ``r.release_conn()`` on the response ``r`` to return the connection + back into the pool. If None, it takes the value of ``preload_content`` + which defaults to ``True``. + + :param bool chunked: + If True, urllib3 will send the body using chunked transfer + encoding. Otherwise, urllib3 will send the body using the standard + content-length form. Defaults to False. + + :param int body_pos: + Position to seek to in file-like body in the event of a retry or + redirect. Typically this won't need to be set because urllib3 will + auto-populate the value when needed. + """ + parsed_url = parse_url(url) + destination_scheme = parsed_url.scheme + + if headers is None: + headers = self.headers + + if not isinstance(retries, Retry): + retries = Retry.from_int(retries, redirect=redirect, default=self.retries) + + if release_conn is None: + release_conn = preload_content + + # Check host + if assert_same_host and not self.is_same_host(url): + raise HostChangedError(self, url, retries) + + # Ensure that the URL we're connecting to is properly encoded + if url.startswith("/"): + url = to_str(_encode_target(url)) + else: + url = to_str(parsed_url.url) + + conn = None + + # Track whether `conn` needs to be released before + # returning/raising/recursing. Update this variable if necessary, and + # leave `release_conn` constant throughout the function. That way, if + # the function recurses, the original value of `release_conn` will be + # passed down into the recursive call, and its value will be respected. + # + # See issue #651 [1] for details. + # + # [1] + release_this_conn = release_conn + + http_tunnel_required = connection_requires_http_tunnel( + self.proxy, self.proxy_config, destination_scheme + ) + + # Merge the proxy headers. Only done when not using HTTP CONNECT. We + # have to copy the headers dict so we can safely change it without those + # changes being reflected in anyone else's copy. + if not http_tunnel_required: + headers = headers.copy() # type: ignore[attr-defined] + headers.update(self.proxy_headers) # type: ignore[union-attr] + + # Must keep the exception bound to a separate variable or else Python 3 + # complains about UnboundLocalError. + err = None + + # Keep track of whether we cleanly exited the except block. This + # ensures we do proper cleanup in finally. + clean_exit = False + + # Rewind body position, if needed. Record current position + # for future rewinds in the event of a redirect/retry. + body_pos = set_file_position(body, body_pos) + + try: + # Request a connection from the queue. + timeout_obj = self._get_timeout(timeout) + conn = self._get_conn(timeout=pool_timeout) + + conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] + + # Is this a closed/new connection that requires CONNECT tunnelling? + if self.proxy is not None and http_tunnel_required and conn.is_closed: + try: + self._prepare_proxy(conn) + except (BaseSSLError, OSError, SocketTimeout) as e: + self._raise_timeout( + err=e, url=self.proxy.url, timeout_value=conn.timeout + ) + raise + + # If we're going to release the connection in ``finally:``, then + # the response doesn't need to know about the connection. Otherwise + # it will also try to release it and we'll have a double-release + # mess. + response_conn = conn if not release_conn else None + + # Make the request on the HTTPConnection object + response = self._make_request( + conn, + method, + url, + timeout=timeout_obj, + body=body, + headers=headers, + chunked=chunked, + retries=retries, + response_conn=response_conn, + preload_content=preload_content, + decode_content=decode_content, + **response_kw, + ) + + # Everything went great! + clean_exit = True + + except EmptyPoolError: + # Didn't get a connection from the pool, no need to clean up + clean_exit = True + release_this_conn = False + raise + + except ( + TimeoutError, + HTTPException, + OSError, + ProtocolError, + BaseSSLError, + SSLError, + CertificateError, + ProxyError, + ) as e: + # Discard the connection for these exceptions. It will be + # replaced during the next _get_conn() call. + clean_exit = False + new_e: Exception = e + if isinstance(e, (BaseSSLError, CertificateError)): + new_e = SSLError(e) + if isinstance( + new_e, + ( + OSError, + NewConnectionError, + TimeoutError, + SSLError, + HTTPException, + ), + ) and (conn and conn.proxy and not conn.has_connected_to_proxy): + new_e = _wrap_proxy_error(new_e, conn.proxy.scheme) + elif isinstance(new_e, (OSError, HTTPException)): + new_e = ProtocolError("Connection aborted.", new_e) + + retries = retries.increment( + method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2] + ) + retries.sleep() + + # Keep track of the error for the retry warning. + err = e + + finally: + if not clean_exit: + # We hit some kind of exception, handled or otherwise. We need + # to throw the connection away unless explicitly told not to. + # Close the connection, set the variable to None, and make sure + # we put the None back in the pool to avoid leaking it. + if conn: + conn.close() + conn = None + release_this_conn = True + + if release_this_conn: + # Put the connection back to be reused. If the connection is + # expired then it will be None, which will get replaced with a + # fresh connection during _get_conn. + self._put_conn(conn) + + if not conn: + # Try again + log.warning( + "Retrying (%r) after connection broken by '%r': %s", retries, err, url + ) + return self.urlopen( + method, + url, + body, + headers, + retries, + redirect, + assert_same_host, + timeout=timeout, + pool_timeout=pool_timeout, + release_conn=release_conn, + chunked=chunked, + body_pos=body_pos, + preload_content=preload_content, + decode_content=decode_content, + **response_kw, + ) + + # Handle redirect? + redirect_location = redirect and response.get_redirect_location() + if redirect_location: + if response.status == 303: + # Change the method according to RFC 9110, Section 15.4.4. + method = "GET" + # And lose the body not to transfer anything sensitive. + body = None + headers = HTTPHeaderDict(headers)._prepare_for_method_change() + + try: + retries = retries.increment(method, url, response=response, _pool=self) + except MaxRetryError: + if retries.raise_on_redirect: + response.drain_conn() + raise + return response + + response.drain_conn() + retries.sleep_for_retry(response) + log.debug("Redirecting %s -> %s", url, redirect_location) + return self.urlopen( + method, + redirect_location, + body, + headers, + retries=retries, + redirect=redirect, + assert_same_host=assert_same_host, + timeout=timeout, + pool_timeout=pool_timeout, + release_conn=release_conn, + chunked=chunked, + body_pos=body_pos, + preload_content=preload_content, + decode_content=decode_content, + **response_kw, + ) + + # Check if we should retry the HTTP response. + has_retry_after = bool(response.headers.get("Retry-After")) + if retries.is_retry(method, response.status, has_retry_after): + try: + retries = retries.increment(method, url, response=response, _pool=self) + except MaxRetryError: + if retries.raise_on_status: + response.drain_conn() + raise + return response + + response.drain_conn() + retries.sleep(response) + log.debug("Retry: %s", url) + return self.urlopen( + method, + url, + body, + headers, + retries=retries, + redirect=redirect, + assert_same_host=assert_same_host, + timeout=timeout, + pool_timeout=pool_timeout, + release_conn=release_conn, + chunked=chunked, + body_pos=body_pos, + preload_content=preload_content, + decode_content=decode_content, + **response_kw, + ) + + return response + + +class HTTPSConnectionPool(HTTPConnectionPool): + """ + Same as :class:`.HTTPConnectionPool`, but HTTPS. + + :class:`.HTTPSConnection` uses one of ``assert_fingerprint``, + ``assert_hostname`` and ``host`` in this order to verify connections. + If ``assert_hostname`` is False, no verification is done. + + The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs``, + ``ca_cert_dir``, ``ssl_version``, ``key_password`` are only used if :mod:`ssl` + is available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade + the connection socket into an SSL socket. + """ + + scheme = "https" + ConnectionCls: type[BaseHTTPSConnection] = HTTPSConnection + + def __init__( + self, + host: str, + port: int | None = None, + timeout: _TYPE_TIMEOUT | None = _DEFAULT_TIMEOUT, + maxsize: int = 1, + block: bool = False, + headers: typing.Mapping[str, str] | None = None, + retries: Retry | bool | int | None = None, + _proxy: Url | None = None, + _proxy_headers: typing.Mapping[str, str] | None = None, + key_file: str | None = None, + cert_file: str | None = None, + cert_reqs: int | str | None = None, + key_password: str | None = None, + ca_certs: str | None = None, + ssl_version: int | str | None = None, + ssl_minimum_version: ssl.TLSVersion | None = None, + ssl_maximum_version: ssl.TLSVersion | None = None, + assert_hostname: str | typing.Literal[False] | None = None, + assert_fingerprint: str | None = None, + ca_cert_dir: str | None = None, + **conn_kw: typing.Any, + ) -> None: + super().__init__( + host, + port, + timeout, + maxsize, + block, + headers, + retries, + _proxy, + _proxy_headers, + **conn_kw, + ) + + self.key_file = key_file + self.cert_file = cert_file + self.cert_reqs = cert_reqs + self.key_password = key_password + self.ca_certs = ca_certs + self.ca_cert_dir = ca_cert_dir + self.ssl_version = ssl_version + self.ssl_minimum_version = ssl_minimum_version + self.ssl_maximum_version = ssl_maximum_version + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + + def _prepare_proxy(self, conn: HTTPSConnection) -> None: # type: ignore[override] + """Establishes a tunnel connection through HTTP CONNECT.""" + if self.proxy and self.proxy.scheme == "https": + tunnel_scheme = "https" + else: + tunnel_scheme = "http" + + conn.set_tunnel( + scheme=tunnel_scheme, + host=self._tunnel_host, + port=self.port, + headers=self.proxy_headers, + ) + conn.connect() + + def _new_conn(self) -> BaseHTTPSConnection: + """ + Return a fresh :class:`urllib3.connection.HTTPConnection`. + """ + self.num_connections += 1 + log.debug( + "Starting new HTTPS connection (%d): %s:%s", + self.num_connections, + self.host, + self.port or "443", + ) + + if not self.ConnectionCls or self.ConnectionCls is DummyConnection: # type: ignore[comparison-overlap] + raise ImportError( + "Can't connect to HTTPS URL because the SSL module is not available." + ) + + actual_host: str = self.host + actual_port = self.port + if self.proxy is not None and self.proxy.host is not None: + actual_host = self.proxy.host + actual_port = self.proxy.port + + return self.ConnectionCls( + host=actual_host, + port=actual_port, + timeout=self.timeout.connect_timeout, + cert_file=self.cert_file, + key_file=self.key_file, + key_password=self.key_password, + cert_reqs=self.cert_reqs, + ca_certs=self.ca_certs, + ca_cert_dir=self.ca_cert_dir, + assert_hostname=self.assert_hostname, + assert_fingerprint=self.assert_fingerprint, + ssl_version=self.ssl_version, + ssl_minimum_version=self.ssl_minimum_version, + ssl_maximum_version=self.ssl_maximum_version, + **self.conn_kw, + ) + + def _validate_conn(self, conn: BaseHTTPConnection) -> None: + """ + Called right before a request is made, after the socket is created. + """ + super()._validate_conn(conn) + + # Force connect early to allow us to validate the connection. + if conn.is_closed: + conn.connect() + + # TODO revise this, see https://github.com/urllib3/urllib3/issues/2791 + if not conn.is_verified and not conn.proxy_is_verified: + warnings.warn( + ( + f"Unverified HTTPS request is being made to host '{conn.host}'. " + "Adding certificate verification is strongly advised. See: " + "https://urllib3.readthedocs.io/en/latest/advanced-usage.html" + "#tls-warnings" + ), + InsecureRequestWarning, + ) + + +def connection_from_url(url: str, **kw: typing.Any) -> HTTPConnectionPool: + """ + Given a url, return an :class:`.ConnectionPool` instance of its host. + + This is a shortcut for not having to parse out the scheme, host, and port + of the url before creating an :class:`.ConnectionPool` instance. + + :param url: + Absolute URL string that must include the scheme. Port is optional. + + :param \\**kw: + Passes additional parameters to the constructor of the appropriate + :class:`.ConnectionPool`. Useful for specifying things like + timeout, maxsize, headers, etc. + + Example:: + + >>> conn = connection_from_url('http://google.com/') + >>> r = conn.request('GET', '/') + """ + scheme, _, host, port, *_ = parse_url(url) + scheme = scheme or "http" + port = port or port_by_scheme.get(scheme, 80) + if scheme == "https": + return HTTPSConnectionPool(host, port=port, **kw) # type: ignore[arg-type] + else: + return HTTPConnectionPool(host, port=port, **kw) # type: ignore[arg-type] + + +@typing.overload +def _normalize_host(host: None, scheme: str | None) -> None: ... + + +@typing.overload +def _normalize_host(host: str, scheme: str | None) -> str: ... + + +def _normalize_host(host: str | None, scheme: str | None) -> str | None: + """ + Normalize hosts for comparisons and use with sockets. + """ + + host = normalize_host(host, scheme) + + # httplib doesn't like it when we include brackets in IPv6 addresses + # Specifically, if we include brackets but also pass the port then + # httplib crazily doubles up the square brackets on the Host header. + # Instead, we need to make sure we never pass ``None`` as the port. + # However, for backward compatibility reasons we can't actually + # *assert* that. See http://bugs.python.org/issue28539 + if host and host.startswith("[") and host.endswith("]"): + host = host[1:-1] + return host + + +def _url_from_pool( + pool: HTTPConnectionPool | HTTPSConnectionPool, path: str | None = None +) -> str: + """Returns the URL from a given connection pool. This is mainly used for testing and logging.""" + return Url(scheme=pool.scheme, host=pool.host, port=pool.port, path=path).url + + +def _close_pool_connections(pool: queue.LifoQueue[typing.Any]) -> None: + """Drains a queue of connections and closes each one.""" + try: + while True: + conn = pool.get(block=False) + if conn: + conn.close() + except queue.Empty: + pass # Done. diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/__init__.py b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/__pycache__/__init__.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37e20a5ae0c432124d83450a24e0a7c6e491c6ba GIT binary patch literal 212 zcmXwzJr2S!3`QG%B!tw1FchOgU_l&#i9KpdNFz#{IxZ62gF~>ea|-sZoB;I#Boe&A zexJR3T^No7$K&}@e!uI@cf zZBmN)d{M{C>w$Apl&)sk%%Lpoz-SXuf=W_!6vv$NSV5svFc-?J5*jRAnnPBVgzhYa fE;R`;HJ5g@K2`gskQ*Gj4!)!H^64|iuy7Kh#j5B>1IY z*f{PvZVeaUL@vMw3s(f=Sh=)i~dVZ`M0Sl{dt!*x9cU;)Te0E z<=?5+(w}#!zgsV%rZyNwAy9O(AyC|ctdot6+(}oUWV1neuR&=?=3U;o20W|EH=%sq zvi^N)&-(MEaMI=9um4t4StBZ4)x*6ig8F$*R%CYSiARMqO5oZdRlIJ~f1_8k<>- z23Eu6pU|PKru;EAr9V$@#9qi(c2X~+rtVr+R7>bjl-)$oy-Vv!y`-AbYINPB-g&jO z{>-V@eUI8t=(W^TzS<{uFyoI{jbLf2%1_f!@u$@=NRsbOzQ`ai24Z z{Yb54seMSbu+&3=4S{tmwLh>i(8^K+6s2~09ynR-{~fh`{dw}h1Y{E> zuv+b?)uGioR0pXe-@m}7fRFVxIBsmR!onZuKjSRimn2qlD&FnlN= zoDPkijl{w}VfaimA)HfcOyji}nTVVZ#gfA52pWhul4l}9A{mN>LtXce9F*P|E7n6~&5EvS07fw$lg;;!ANS+BLh3QDk`G^n}=|5it>s#}a~C2W<<9xTCEtnKfh#J{A`y;<53Fh$cqk=gwhT zk#Jj^&*5Nmi$x;g1ja%DnV5)AGk{?Bq47vUh{iCtiHS&fyTj2YoYDYwDk!W=MiMlo z>1gtduyKoTgKtACl^GRhCX?}TF*JE*hKikw#-it@&IucRUB2#iVN8sl1Hj_|IAFwT zM8mOAcF9fDl4E~-I)XX2XRS^+f?60XppxB7JEkp6pNV2krz2R>2!mJhj2Ho6qnLDZ zVn#R<5$Ux94G2?{!kN%{nkZH?l#HH_pukvUT9{PlEk+)nLd`IM^hkV47!Ac#P!Ocf zDU)6aGXgEP0RZLm38V3Fq~r8NeDv)0?bu6+GY*G<(2U8jMeP6#qLW&i8a!6aOCZ2t zmEuBZ6oU*UBf@AzOh(6|qbz+UGI|!1Xvgp-CLG(xredSpPknw$oWM5h@{Pu0Nillb zr?u^i#y$sF1f#KJJeVnUN?DJY_>?GQ_7x4?p=@pe`Pk><(U@>9L|qB{hlh^ik{xG*XU}ZjylK1>SkkHNmd?zQcV=(~ z*%|tTwP90Z5lt^a6a6wL+gxHHQY;@pwCI%mqwmQioo_Dkx3OvFBFEOqsbG%+jbyW@=>`sm>FJBWdd^15&z-g z!@Y+O1;M?}Zwzjf3p0t}VE^#`!+ontY*I^XQcE}w9|;Z}4uTJ!-y~=K=#q`-7R!_M zK6u#A3U;XlS#MZjrHt~cAnON>DElRTuXv5&ta!a?gcIeJE=a0-t)qKY;hOrn7V5;)Y6 z!FS*AP^(3*3Z4&5M8n`HL506YVxv(Y-nmE;dq%C^3vNPtlSqK}| z+Dd2V=B=-lWb4vB5(~#61nP@JJoNO8km1#ND8MP-KBAwcaWOg`Bzi$umJNKd6N45v zP(+Z-g>?nxQAF~0Vm%@TYcIe{Q0~lva%~36jrV{u?K6fEzlFqeWSuh{cK6G*BZSPwPXD_6xyKjW&tve)Z@9o0MMFU^3VaaH8 zI~F;k-SJ@|XKsGa>Hf_v7yE9bbn^1US5df0vaZh*?$iq}8aZ3LLP<2rj?QQ-Y>yv9 z0(;yX;7QwzVXu#HFl}-nEc*!8%=YXEr|!X+VZ<ppAs4_8Ckk7~lP+@wrR5D>wgfcq{l+nk)wBD&$lth0hvm)DfOgY6H5+Xao&>W#P zI+*s>6X+cnz)&FZ_=JanAJ8CasH`No2ercRQEe(NV5iO+b%R8yi(XMeV91J0A@RBg6YTwn6t~T6Y*CoC9!4pqUY6_`!V;oC0hLJ+W{A z>Id}_h2#VU5zJAUNJ7xsY6W}-7_ti_my)VS_zs08YdV-7jTd7SBgrW-CJd3XlZcK3 zX(7G>O93rr3Sez0%aAw|pTZiVrNr4NY4<({?H4T&{q&HuQG#5Rw#Imzycl7-g~b~? zjPuj(%n2g~b!V;1ya{7-4OY`G&8DPkser-6#W?IzjVkL6>brD=&-Y&6?}VUaO=)IU zz2b(r}V6!?zRm2jJ9hUsk~%qq)RWh%RzVF3w)MXtLTX zep0pOvSq>Jeg45K56*2#d)nqbZ41@)-!jha`vd1(L8{t!xo@Gm;l*7q?7HTiuikj0 z?|TPdIry4szPn$l?ti`*Yl~z2zA9Dmm7%4eBMG zRLMrr6WO9*;KwdTe}rFUs0f~HQ7{{-S1dMjHs@^ki%()Mv(EQCb!>7M4=q?dlC>I{3r=s^StmK`u1?Q8TT-T$)eMFN zO>A#|=`o<`b3oF3>_SyBhyVa_P%=08HGxZib3zkh^P!qb0P>+6gf0*aC7hteU;#v; zUQO%ItX>2?S52wCsD@k|LYWeVPUQ&71u|wDF^v*|f+7?!j+nX)M+}2do}EDWm>F-) z{wB38{TVP-5y`suXqxr%YDyiAM-wmA90;9eB1>7b!RT@WND<&Ha5VmU5WB3>r10m2 z6Gdu9R=E;2Pk){uy@`cx6MAR_RE#G`G-APDsiyR2fFCic5LHJLFvN^K#%4}=j`1p~ zB(j_^#7r=8n=cGH9%51eNSG!MXWI>7P!;3nqhXQ&K>QddRb&wS)`XA@rE^^PqaKyG z31t2zjGBTf2-~P`1kJWeGFl6A1wn+Y!x_tpLbb=DF-4{Y^}d(flVw;8jg5hxXOCaV zsH>2esa!;ekhzTwZcSoHHuen#RLFh=eg(1 z0yl_Nqg^`AZ#9nbAnJ~RBSKF&EJh&TxAG!*G}mg74ZaPG=p+bfGeWIw-#H$Mfrp5@ zBlWG*~g^Yz5l?%$rdWovlbH}X#j z6H0ucs)ld%$Zk;jY$;uKWJ%~-P>zY(a(RA8%VxlFDk2way39~Kxesd_mP`7k6f0~* zd&lfta#fb8@FC1j3{4Dyye&R1Tc<-}4APNoJQtc|)K&HnC|Jh{ zrYa?=sufE{?SL7Q9u)=~Jd%Mj7^i(Q5`j(yu^CK~Vk1h)d_>_1X5x8?1d&031*THS z#j8LrPN2wN;V)4DNCU(+&Q+FnHcQUtdFR@TeTz1axn!ZReTBuV3=@zZL#*?Dg19 z-^h{?*~^^4Y@zWLUp(~D@~}K&v;2|gIw@1POu=f2beWCN;3L|Jv~PTI$&Ifoh^DgO6s~W%}R;c2X+|+7&Zu~ zdofTiP^u1Q6Yz}^`l^Ab1t7;S^&#;bcf5#ps1l9~6X-9K-jHpT8sV~RhtLmn+tfIB z-8jU=&wVf;IiNpf`WB1PkX%YeKO$T~F*H6N2?rzbu>|b&(RdKDWkR;XY!Qcw*=mAG zFETMEK8{+fswg7G2oE8cf?u%j<5({VqkZ`bIQi84G9qVSbA)Lwu6oT^-3#S4Uv(}t zZ@X!0Sg5F+HGQ>U!CNzH`kG=$UqP}p$Pg7{0u!FOA)jWX3Q^76bsj>vGIPrqP6lJ~ z>%2IHHWCEbjN#z|l5*+F2`GgdX!vD#eUT#}_Q^|6rriyayJ6nll(IFg7V!uJ*jhe| z#N9?5;J3qA8A7uo+%DdalDQ#Z=zy^_VbFI1ghhfzPEhr}5SA7t@(6}1B*47zuQjtX zeoB*vh@8MfOd^uaY}Lglk5Rk0eJq^QC)#4qgwP@jWS z049m7+>j46jgX!3`%QbS;q!>=TxG$ zqCYVwxHm!y&JRo4?Kwf+ME8N8Cdca4+3c}#NuiJ25B_AX&IuUn7{UKUmHNW3=_qOr z2gei4rB45?rt;_d8`SsuQ=Op-VRdE0Skn_tYPl>U3045D=RwKreMg#uvQCiI+3MeS zy_(g&^e12-Fc_>=^Ze@Y)C@e~d}AIl?KBi}U7A@ad!MK}LaSxyy5Xn)jBufFgalJC zCdlXghxak`6KP5x*N{9dMnYi$2aF;+D`sc(_&t^U*u~y3aeKSaTE;kpY=VEqdD)s_ zda@D66|yTZljwzV!DK;qh4Zp8E)|vDps(zUE9Jzip1Sl@+Pz+Kub+2!eAoNE>Q}1M8;7KgL-X#Tcf3`1ipsQV>m>I& zsoQ!t7zlTai*uvOOV_G8GLr$E-8Dy{n_@pnror!BdPkX z`I7Ee8&a+vKPNNL&W{s&0Mswk2;5xVKEe2(8unU^uQxX#e#6@1Mb4W7<-fVRr@Fu1 z_`^ybKYm!>fcQsT^}cH3kE+c`uaF%y*0J}OVjaH}+c1JeGW>dflCE7*E`f zZJ0)kIcy_qpJ;5uJS2V*ILi2g`0JGVG9s1w+lc@&k1}zV-d&>THz*P*BFZX$l_Dbe z;@2qpEsCC@=rTn_!^JBUk>DdfOA+lt@wX|0yv&KuA%YEfiqfpb-=P#E(InXE6#94Z zOZKj&&}@KxM5c*W6PYfx@6^b2``e!OYvGh<*NrjBvn%D=^^ry)??;|1{)NeNMLzPp z^|O)Z&p-S5xn#<_<=T14yX98Vmd{R}tLwPmuiIB={6WKBv+?!DCd6-;L7wZ3Z`M)% zn>#_CYmGnj^7!$?+6IbuSMRGd{;1N7G}(T&0HUlYO52dQo1&CYwbQM0&73%c%Bp(j zNNBtsS!|Qg{>e7RiNA*oxnkwU(5sQ3PlB9OvXs3wl6%eE_`KVfviTJKBzqRbWH1wc z>5oyB^pm@4C^X-kkUf*nsGAH!E;O9bSWG@v!erw-7Hg29Jh^^N>(B>#SJ{{xJaBNS z1hv$NA)-jVh91KpC;;SMr0&ab2>o*c~vhJGxnF+Pk* z9fwNLt{W61No!$7eoesQs1q-_kVMRfML4i#$(V(jj5$qja!C~G1F&&sn){m~2{Ykl)x2xc2Uy6vf=Gq|*;L-KSiamIqm+urK5x9x3j+qLfR?6|(;Rnwn1zwbNj_cULhKl3c;Ij}r|T z+!w2eRP>e_f6!y!>omUMY(V;r_NHF9@lCfG=@qoVf*K5qh@;Q}IJs2lPIo$_q~6wq$EN6WzML6|_vP$JHuI@WG49^$tU$sTA6 z!H4|=!~Ma%hYt513=I5Azsihgab-smUbPdnUNBHooMS4p(n>=alFL@Ea3(uS3p;>@ zu&`z2vyO$rif?vZO@8Bn`NC$fsI+ID@bM8u|R=TixHMt@@VSxSt68A8taV-egDmjKoU#B*Y5GU4|TKBoFeo8ipUKTZ(&`$APM z_j`3c)yDr&-BWISz1)oC3YCU94_iKveTFA6`y!=;{9RtnE9z*$gcO_YMI=7kX8p{{8~SBVD4fbI6iLIZ7{h7KxqBPXM3Sp_0<<>dl3d>d%+k}su+X1BzM=md-JU6Z{e=u z@y;InTW2}3_}y1_r#+h_&!+Eg{od|ZcBi`zOI?RkM@Qy8$5O6iXrQ{~nkl_*+uQ55 z&9B>@UbjnHw<}e-J5{kK<=uO`uJeXzzHajeW@C}!i@6$=HNy4T&v8^y|8Y!8u4Jnq z#*^{U_=M`l&kodc>62{Dct7TH-Awkg1gJ6wD9vWJO>%FWcW+PGw%=nWXHe%ep%$No zNN^f~iw|+-oS<%MG8?OEj#1fxZ0@0n$ygBX8#wuoMaJXFD7^N=;$gIsQGH~GUL;!s zlFME?U6z$o5v>Np`_9o>%b&3>HclCJ+*XBZl>%XQ!zm+%X0aBX#7to?@!ei7aG}R zAGo@;<2q>~c|srlqmQcYZkZ`FMMFt{49`MQeO)RNAr^_Yicr=#k=O=Kc%f;G;zHGV z%DO<&MT*F-Et2VksmV<075|Wal03v1J>zQPYxMIiivBZ21r*sRDx`=Gx5Stl(Q$d= ztN8V0?j6$soB*$FTeLgOwRcL}7R`8qxD;0}S}A4Y>YLa*_(nJiKXf8*xq>%0FWXG! z%4L_=T(P{V%)E2i$D2EsEq3#^<#LO;e!0kG-or1uj7U06X3t_F*R*cYSZH>@agjam z*w=q(#_wf;H}CkF#bDl{43x$=ia#xY=~KY19}If6_X7MAn6H9pK1m)5%vV9hQ_*_T z>epPrly)eF{{r)5$SOy5nNNe3XFqArTQ}qJpqI<%`H=BufN3WCpXvnx?*(HJNu?~1H) z1dWmvc_k-H^44t%cvhARl)^*9(b_Ef0O;uNVa?ztJRpS52_elJgLzvppA5xOI747? zGZo~8?lGM@CBzxSho>-Ag=54d?ovnL#OnYH7H|nKmY}P_%(t8FwL(C9Ei!oiKMpE;~gC}@K#9@1eb|C(6!IJI36D*UW5oY3mxQ~1#+((?s zBY@>s5Y#gQw5{=B3NxvNZ#F*%Ta2J^{Cu_$0aAB;>+Tx+NVv6Hg?`Q;Zpu zWe2V&9#gK*%f*8OLj!{&gTcVakt2uw!~M7^x#}um@nFyK)rD4GCsd7(3m9WI>t*Ct zuGH2(Gg8e{=37|X1TFbR?si4%wRKWO7dgk=F0Fq4;FW{v(iW){V%T>It{2RgZowP7 z>OE7}G;6wPtG>Nv-OG=?^jLaLzqF>Ga%yvOZrN&A3pBK$*p{n8;%)+sDuVFhPf%*L zjHLp(V%6j_Z@x`)Bj$6FyMv?2U%T{cDO-&)nC$(p$%z}-V6r`-@|%2AN72L>y_!&y;AGm`PM$k-Ji1cuU;b)%CimQN8)Z9CZBmur&tO#(;cN% zHBVnflQLH_>1XB&xG1+7=w1Vy66m85>Z>9Z9(0R?t`>>^17lmU%72dx@qZ%vKFyij zYq82U*E9A@_Oz`=ven$I-Ew0}s@-+-!Na#~M^>-5wl$&reyVBb+oEhCD`;}z$XI9! z&cK;ffkWY$MDB`;OXyN=UA2;TtN$NqibR|trK?kHlWc9b)Jt#KD5ou_VtdWDy6P8S z)dkWl01)5vD=zqa5_+c)0~7hAwgKJ3OIrZOJ@Ft~An(N}u1FG#g}!?TSz<3m3Len( zN28PYd_<7s;|$rAtx8@Zd--LjUO15lC$iqYM!EW>u~}%Vm!TuxN<({rF?buJG>)Cb#c`vEf=!~ll;#@K7WUN zh8xYPiIfJVW*&(VPECeSf<>+YS@9Tx%_l^DqVy!xrRQDUhJJwt<+ZD@IB)Miq+R$8 zRDk`)#koo(SWL^RpMUhqqjOv5%hu2CTW}Vy%3Cy;?IX+{J#c9t?OHFn)?eFq)3sy4 zT?UU;934DwzhX}pbxK8@-?hGK`M2&{MSEa-Eo%Jeebs?THCd17ChL8#J^p$mRexx{ zWH1#NPPvAe&3XhjYm(Ofu*cBj<6igG?QJ){;i}%-Vtk{;jC6iPxQb~#X8d%v+-%w~ zY&_i$+anXQAJ%1l?jP(q;gM0$R})TD5MG9{&KxXH3byHU8|fUl`Q{J)xzCs zQc!4Atw>KIRbEm^2)}pp&vCk(H>Oh0+3R26*jKctaKL0%u!b zm2U8rnTd$_k7!kVnpS!FpgQ`N1Q{pcO7T-iGfW@NAX7}qT zzCm(rxKVM_wSB?umE29Yy$y5gzTKbpZj!v47V2AGeCma#u1(L^Z@s)S7t&*$tT1&cZ*Nx-1T)S5vJNR{C(ED1?>zh;c1M?*ZQb&%aTt^u(@Mnm@ z7x!BCI=MHTb-i}u8?Dv7CgYnXGtw(`T+L&|_pj{JeVrPVSqlCQ337(o8 zM(`0LRY<|5!Zn#og>;b2`ANjd33+cgYY5p4*-^k>40n)87@(ue;2Bd_vb zAAbIkE03hhTBNd;Yy7pXe^J);{YPf)snUnYoXzgsl6U8|%6WHJ%GUKy|6t_G_VWz2 ze!Z>7Wg6Agd^AjH0GD670Sc9^(|l4<0l>~~56w{kr9*oZVwMrJN}of}#7+=dVIi;B zkdKaPpAk{p32#L^WOQU<#H^bb)Lzw+>=e}OClxOz=o}$t9d zm>YCCpNwWGljkmHc9|2cY756h>PXpnrJ9{zKqGZ6Cx8#^0c@>V(5%TRf}f4t@#1{9 zXw@;PV^E>RJl`ACb^_YT*@!jc-(&5u4o)-w9;D#kqZZ9S?ndpkmdNlg>xpJH%fD7l z=}*SLtU3G(V}L&o>o=Ew!7qTFaOnQ(7u=^I37)~%CK6{tXCusIeHI-sk}lJ?IMfSL zq*y49h-83}UC~4^IvG;#c`A%UQ$lc$3TT|1NWh55tV-U52TwOkeVKNwKLsxKx#U0+g*9J^V?l%ccD zt2V#7F;%*Ag_BdW|oQP*E)e6wYG1ejcWa zzIab-n-i!z`c|&)9*A;egUbnOxon+Iv87oR9>A+{hYrGb$cgMkU1un^zd#`!6s_Z}L~ z-3EZ(O6zzYc{is-B?c+3qahOrSICb4BJg6v%!XGx`dR@m$`Csc)zVPf=obwI=fjLa zyhrn7Q2z;~Zc{|Yeu#+l5Cw_`Df%;t{u~ir5r52imC3zO2wSG_7_;#Xl0{dqn^Nk2 zgvSM^`k@mX@aje2!ZI`jZt=gV`I{8|A1(FIlp3N)YZ2lsm3Gja7%!vG4Jh@P%EDUE zOPj=EyuVP)4xqF8e>AH_)4pMRKhPysQ%nDqdLy?Zl*Qy#05G*cbiA}J4IECW=dqv*IClW71t`SGbijUcO8!1 zS-nEDpTAR5wurNGKh-O#S+ugGjq{)$ODZSxlw1}J=5F*`+qkfM83+t2IhIPYoJTA>Ifc0abGQes&@=hYZEeVHWFYN0^X- zk5h-y(t}hOenm+q#S;en5>-)P#-_g-Ae+FN96+^3h8>Ql@fc zR2f9yM}-+)vTaY;2xJ(iTr%x2WVleKxP#!^9FY^uJp|FCj{*bP82<~Eqk$?lHqp2R z`bjqvl~lKuV!iw+-nI@gl%cQmj!of%S@>eF2+qXetFFoy(S118R{Y#t+20ybKvJBY z#Xb@!5){Pk)PlXAeG?g{u(B0j1Hnh6$CcApi{jBD8=`T=+6s$ZhJuh-EGwe8T);f% zdiVGD9vm2YNZdh%2pHtYg7Y2>R1wy*KYXi*_5~R8`AuEwXKg*%C4#+&2KtAF<-+XD z^BZNC^0i#$Te-?PGrmup^~q#>>cDy?l%NkDiq$k05-mhJQ4&e(lI^|y{$YGRcc@=> z9_#lH?0ZD{QNZ#K9~mAvJk)bYdv~P2-!Cig{QXBq2K+d8uFllk*E4V^IIxet#Y@G4 z)PlH3otSa?;9NrdJL>fTiW(?tqG%08EfkT0DZWe5Um}vt%C~r}$^^YkAX$M|h5J`fIM_ zU9NV~WabOrHEn@}#k+sPIex+wyvvop%eB1ARs9X;xns1ajb8kJ*VF{c;exooE#-LN zq7`(=Y^P7lrcG6nsp{%OFCKj1V7g|rRI_=(WK&)=NT!CltuOC*X-B$gr_{7_!DLOF z$|Y0zRqKn+7o6#e4N}F1MXPCzA;lG6-i=GMyx{{EXL8PVrHUHU#wN+wblrNx`aS0> z&eX2K^tvHw-Oz$>^LNf(Kb!XLmwfwErn1YU>GC!S|4r-PGdezFO`47ED}zrDUf!x` zK5Y`d)kecDlhDQV^G{xRGVS$AUSIx9@Sw9#pG{jjBufXx>I&bY)m)2NRf05k?&s6K zLCH6G(|7o0&5^f#hhGZMg{~g`-C@ah`0bh_DD{Djt6MYo@XIG&I&q`pwc`2O-q*($ zOwO+yeEQ(!+BtA3!$W`!XQ)GyWtS89U=4m+xUw1r?AK~v<>yPcUv$lm&U4$}!KIS% z7tg+M_S%E5_RN>>zF2tKIM40=blF&I0A%Rtp|q)4GBu~x?!d&A-xZRnB30F?{ifwl z)oi?RNUGVBH}kdKQq9p7Zx(E|b1uo&e(m#;ZP#msl5OaY+B)^N`t_p6*@d~+&($q) zPTsIswPJKAzu+hb-0j{wj*1V=274vO@2vd5YDCILDZ2?NeEc*sCz=EGg06ix>LlBP zulXd~5p59al!m05y{|nc)dW_Io+e9gax=Bx8Hg>`y0t;OG3aK_TayAx(IxLIGs*>{ z6jzF&S_{(_@7osdRolF!;i7TbV&fa(kHR<$;x{d?C{#d^Nyo%(TpehDkxgCQp&~^ zc^2)Ia&VASoRo5L7RQGLNPV<8?&fSB=>B}cvWYhrT%GwDhsUBB8NXQa^IYvwo?Y&H Z&T>@Xe%w`fbelyIijQtKO5Hr-{|iS+)VKfu literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/__pycache__/socks.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/__pycache__/socks.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ec448afdac2c990dffb58971ebcda64f8100c51 GIT binary patch literal 8431 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 k{%=$aAU_f=_{l#B7tWAh_ None: + # override connection classes to use emscripten specific classes + # n.b. mypy complains about the overriding of classes below + # if it isn't ignored + HTTPConnectionPool.ConnectionCls = EmscriptenHTTPConnection + HTTPSConnectionPool.ConnectionCls = EmscriptenHTTPSConnection + urllib3.connection.HTTPConnection = EmscriptenHTTPConnection # type: ignore[misc,assignment] + urllib3.connection.HTTPSConnection = EmscriptenHTTPSConnection # type: ignore[misc,assignment] diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/__init__.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8528bd403e7a4accfbc2ee0096e80417bab156b3 GIT binary patch literal 922 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 Tu5xXwvAuV=$*P%f>W%z=0q%&^ literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/fetch.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/fetch.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea9fb098107a1a8ee17d8a7fd316d37c037666da GIT binary patch literal 28647 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 YA+$Opdd2e9Hj`NPw{Ejo&M4;p0j1EK8UO$Q literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/request.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/request.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39ceba82593436be425d9963c531044212a4dfff GIT binary patch literal 1488 zcmZux-)kII6uz@F`+Jj3YBr`xO~lv?9ArO z-9Umupbsi2)`#HVkQedQzryOiY%d6cNXc8u3I(4$XC~W5^unI|edo-cd(U_7y@QdF z0>kmcPd~SAr5O8z$Z(_+pbb_K95S2P+A3SoKr;!aR#PiF=qm;o$aULTO|N7iW3o+s zidC7No@REYjyY-6lZipLm96EDiPbb!bb=t1j`YGHs-;xE;Yi2zohVZ2rYHQyv7UTa z;2ZZpxWnJMyL{h0O%zW?LbSox2oBjM1I=cTvNg~z;|4bkTfd5t7#T52L)y-uKYPkD zb`Dvd*k-oMHgk4iNrSvyL~kknW&{fMD6(?Q#-M1ABRdzfN&A&)_Nf6S`&D})Mk96w zMqBCHlp4R&j$H6MQUvQ_rz;|PoWoU=9!XG{wvgLlL+M@c*Y+z7&y^pc|4kFk$L43| zS{MkG={VrDqrb;rRzD0GTVZ1l1uQp2)9Lz>Hyu}ou(v<@?^G(gEu4mc2&fOJsvkO1 zWu?~^VOMS_%oF-*v?1KEA-Ed`xLfIx>cc@2Bi9DE5gf7)&GljA%zRHIYqb=dL#zs})A6L^d;6lMDL%9k80A zPo-Epu61*9r?Vv&>o;!hEZ*90*6Xq*x87QC7jU#9Ys2bzo$JzpmXOyU@CV!V`eMuS zy)CP=hq?zA%8u-YMHK_O#fx59kTh$)v!@D?kUSAkUHDHs=U+yts;GkIfc39g-C}h+%Y`x$K<7C}pG?fu0#< z(7}z52TYK2lFTfbOBAkf9??VLaz|3fx>7`(AF-q)k_7TYL)R?2i{=aVd#U_zwVy9N ze82z3+`+q#ORx8gx&CbRVEJ)jre{>2%wGC&`Ip(HgZIAtq-QMkE0c)s^^D2>%*BJX zN6S6q;$McAUU;6-(&v-4XqmNIj%sgqQ7x<;=)9`pi`Pp;K-VTIY>aO?QGB-o;nGV7 z)RAPj^Mp(?NmFkpYQ7DN=+p2Q(cL-GHBI}CRiCoCKiRdD3`-TCr$)5%Ck)L%NBWFt Goai6Uk9V{H literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/response.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/__pycache__/response.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c75bcf5042d2ba256864158b848a30d93f5827ae GIT binary patch literal 12873 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 mAY*=PrSI7ksd None: + self.host = host + self.port = port + self.timeout = timeout if isinstance(timeout, float) else 0.0 + self.scheme = "http" + self._closed = True + self._response = None + # ignore these things because we don't + # have control over that stuff + self.proxy = None + self.proxy_config = None + self.blocksize = blocksize + self.source_address = None + self.socket_options = None + self.is_verified = False + + def set_tunnel( + self, + host: str, + port: int | None = 0, + headers: typing.Mapping[str, str] | None = None, + scheme: str = "http", + ) -> None: + pass + + def connect(self) -> None: + pass + + def request( + self, + method: str, + url: str, + body: _TYPE_BODY | None = None, + headers: typing.Mapping[str, str] | None = None, + # We know *at least* botocore is depending on the order of the + # first 3 parameters so to be safe we only mark the later ones + # as keyword-only to ensure we have space to extend. + *, + chunked: bool = False, + preload_content: bool = True, + decode_content: bool = True, + enforce_content_length: bool = True, + ) -> None: + self._closed = False + if url.startswith("/"): + # no scheme / host / port included, make a full url + url = f"{self.scheme}://{self.host}:{self.port}" + url + request = EmscriptenRequest( + url=url, + method=method, + timeout=self.timeout if self.timeout else 0, + decode_content=decode_content, + ) + request.set_body(body) + if headers: + for k, v in headers.items(): + request.set_header(k, v) + self._response = None + try: + if not preload_content: + self._response = send_streaming_request(request) + if self._response is None: + self._response = send_request(request) + except _TimeoutError as e: + raise TimeoutError(e.message) from e + except _RequestError as e: + raise HTTPException(e.message) from e + + def getresponse(self) -> BaseHTTPResponse: + if self._response is not None: + return EmscriptenHttpResponseWrapper( + internal_response=self._response, + url=self._response.request.url, + connection=self, + ) + else: + raise ResponseNotReady() + + def close(self) -> None: + self._closed = True + self._response = None + + @property + def is_closed(self) -> bool: + """Whether the connection either is brand new or has been previously closed. + If this property is True then both ``is_connected`` and ``has_connected_to_proxy`` + properties must be False. + """ + return self._closed + + @property + def is_connected(self) -> bool: + """Whether the connection is actively connected to any origin (proxy or target)""" + return True + + @property + def has_connected_to_proxy(self) -> bool: + """Whether the connection has successfully connected to its proxy. + This returns False if no proxy is in use. Used to determine whether + errors are coming from the proxy layer or from tunnelling to the target origin. + """ + return False + + +class EmscriptenHTTPSConnection(EmscriptenHTTPConnection): + default_port = port_by_scheme["https"] + # all this is basically ignored, as browser handles https + cert_reqs: int | str | None = None + ca_certs: str | None = None + ca_cert_dir: str | None = None + ca_cert_data: None | str | bytes = None + cert_file: str | None + key_file: str | None + key_password: str | None + ssl_context: typing.Any | None + ssl_version: int | str | None = None + ssl_minimum_version: int | None = None + ssl_maximum_version: int | None = None + assert_hostname: None | str | typing.Literal[False] + assert_fingerprint: str | None = None + + def __init__( + self, + host: str, + port: int = 0, + *, + timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, + source_address: tuple[str, int] | None = None, + blocksize: int = 16384, + socket_options: ( + None | _TYPE_SOCKET_OPTIONS + ) = HTTPConnection.default_socket_options, + proxy: Url | None = None, + proxy_config: ProxyConfig | None = None, + cert_reqs: int | str | None = None, + assert_hostname: None | str | typing.Literal[False] = None, + assert_fingerprint: str | None = None, + server_hostname: str | None = None, + ssl_context: typing.Any | None = None, + ca_certs: str | None = None, + ca_cert_dir: str | None = None, + ca_cert_data: None | str | bytes = None, + ssl_minimum_version: int | None = None, + ssl_maximum_version: int | None = None, + ssl_version: int | str | None = None, # Deprecated + cert_file: str | None = None, + key_file: str | None = None, + key_password: str | None = None, + ) -> None: + super().__init__( + host, + port=port, + timeout=timeout, + source_address=source_address, + blocksize=blocksize, + socket_options=socket_options, + proxy=proxy, + proxy_config=proxy_config, + ) + self.scheme = "https" + + self.key_file = key_file + self.cert_file = cert_file + self.key_password = key_password + self.ssl_context = ssl_context + self.server_hostname = server_hostname + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + self.ssl_version = ssl_version + self.ssl_minimum_version = ssl_minimum_version + self.ssl_maximum_version = ssl_maximum_version + self.ca_certs = ca_certs and os.path.expanduser(ca_certs) + self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir) + self.ca_cert_data = ca_cert_data + + self.cert_reqs = None + + # The browser will automatically verify all requests. + # We have no control over that setting. + self.is_verified = True + + def set_cert( + self, + key_file: str | None = None, + cert_file: str | None = None, + cert_reqs: int | str | None = None, + key_password: str | None = None, + ca_certs: str | None = None, + assert_hostname: None | str | typing.Literal[False] = None, + assert_fingerprint: str | None = None, + ca_cert_dir: str | None = None, + ca_cert_data: None | str | bytes = None, + ) -> None: + pass + + +# verify that this class implements BaseHTTP(s) connection correctly +if typing.TYPE_CHECKING: + _supports_http_protocol: BaseHTTPConnection = EmscriptenHTTPConnection("", 0) + _supports_https_protocol: BaseHTTPSConnection = EmscriptenHTTPSConnection("", 0) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/emscripten_fetch_worker.js b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/emscripten_fetch_worker.js new file mode 100644 index 000000000..243b86222 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/emscripten_fetch_worker.js @@ -0,0 +1,110 @@ +let Status = { + SUCCESS_HEADER: -1, + SUCCESS_EOF: -2, + ERROR_TIMEOUT: -3, + ERROR_EXCEPTION: -4, +}; + +let connections = {}; +let nextConnectionID = 1; +const encoder = new TextEncoder(); + +self.addEventListener("message", async function (event) { + if (event.data.close) { + let connectionID = event.data.close; + delete connections[connectionID]; + return; + } else if (event.data.getMore) { + let connectionID = event.data.getMore; + let { curOffset, value, reader, intBuffer, byteBuffer } = + connections[connectionID]; + // if we still have some in buffer, then just send it back straight away + if (!value || curOffset >= value.length) { + // read another buffer if required + try { + let readResponse = await reader.read(); + + if (readResponse.done) { + // read everything - clear connection and return + delete connections[connectionID]; + Atomics.store(intBuffer, 0, Status.SUCCESS_EOF); + Atomics.notify(intBuffer, 0); + // finished reading successfully + // return from event handler + return; + } + curOffset = 0; + connections[connectionID].value = readResponse.value; + value = readResponse.value; + } catch (error) { + console.log("Request exception:", error); + let errorBytes = encoder.encode(error.message); + let written = errorBytes.length; + byteBuffer.set(errorBytes); + intBuffer[1] = written; + Atomics.store(intBuffer, 0, Status.ERROR_EXCEPTION); + Atomics.notify(intBuffer, 0); + } + } + + // send as much buffer as we can + let curLen = value.length - curOffset; + if (curLen > byteBuffer.length) { + curLen = byteBuffer.length; + } + byteBuffer.set(value.subarray(curOffset, curOffset + curLen), 0); + + Atomics.store(intBuffer, 0, curLen); // store current length in bytes + Atomics.notify(intBuffer, 0); + curOffset += curLen; + connections[connectionID].curOffset = curOffset; + + return; + } else { + // start fetch + let connectionID = nextConnectionID; + nextConnectionID += 1; + const intBuffer = new Int32Array(event.data.buffer); + const byteBuffer = new Uint8Array(event.data.buffer, 8); + try { + const response = await fetch(event.data.url, event.data.fetchParams); + // return the headers first via textencoder + var headers = []; + for (const pair of response.headers.entries()) { + headers.push([pair[0], pair[1]]); + } + let headerObj = { + headers: headers, + status: response.status, + connectionID, + }; + const headerText = JSON.stringify(headerObj); + let headerBytes = encoder.encode(headerText); + let written = headerBytes.length; + byteBuffer.set(headerBytes); + intBuffer[1] = written; + // make a connection + connections[connectionID] = { + reader: response.body.getReader(), + intBuffer: intBuffer, + byteBuffer: byteBuffer, + value: undefined, + curOffset: 0, + }; + // set header ready + Atomics.store(intBuffer, 0, Status.SUCCESS_HEADER); + Atomics.notify(intBuffer, 0); + // all fetching after this goes through a new postmessage call with getMore + // this allows for parallel requests + } catch (error) { + console.log("Request exception:", error); + let errorBytes = encoder.encode(error.message); + let written = errorBytes.length; + byteBuffer.set(errorBytes); + intBuffer[1] = written; + Atomics.store(intBuffer, 0, Status.ERROR_EXCEPTION); + Atomics.notify(intBuffer, 0); + } + } +}); +self.postMessage({ inited: true }); diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/fetch.py b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/fetch.py new file mode 100644 index 000000000..a514306e1 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/fetch.py @@ -0,0 +1,708 @@ +""" +Support for streaming http requests in emscripten. + +A few caveats - + +If your browser (or Node.js) has WebAssembly JavaScript Promise Integration enabled +https://github.com/WebAssembly/js-promise-integration/blob/main/proposals/js-promise-integration/Overview.md +*and* you launch pyodide using `pyodide.runPythonAsync`, this will fetch data using the +JavaScript asynchronous fetch api (wrapped via `pyodide.ffi.call_sync`). In this case +timeouts and streaming should just work. + +Otherwise, it uses a combination of XMLHttpRequest and a web-worker for streaming. + +This approach has several caveats: + +Firstly, you can't do streaming http in the main UI thread, because atomics.wait isn't allowed. +Streaming only works if you're running pyodide in a web worker. + +Secondly, this uses an extra web worker and SharedArrayBuffer to do the asynchronous fetch +operation, so it requires that you have crossOriginIsolation enabled, by serving over https +(or from localhost) with the two headers below set: + + Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp + +You can tell if cross origin isolation is successfully enabled by looking at the global crossOriginIsolated variable in +JavaScript console. If it isn't, streaming requests will fallback to XMLHttpRequest, i.e. getting the whole +request into a buffer and then returning it. it shows a warning in the JavaScript console in this case. + +Finally, the webworker which does the streaming fetch is created on initial import, but will only be started once +control is returned to javascript. Call `await wait_for_streaming_ready()` to wait for streaming fetch. + +NB: in this code, there are a lot of JavaScript objects. They are named js_* +to make it clear what type of object they are. +""" + +from __future__ import annotations + +import io +import json +from email.parser import Parser +from importlib.resources import files +from typing import TYPE_CHECKING, Any + +import js # type: ignore[import-not-found] +from pyodide.ffi import ( # type: ignore[import-not-found] + JsArray, + JsException, + JsProxy, + to_js, +) + +if TYPE_CHECKING: + from typing_extensions import Buffer + +from .request import EmscriptenRequest +from .response import EmscriptenResponse + +""" +There are some headers that trigger unintended CORS preflight requests. +See also https://github.com/koenvo/pyodide-http/issues/22 +""" +HEADERS_TO_IGNORE = ("user-agent",) + +SUCCESS_HEADER = -1 +SUCCESS_EOF = -2 +ERROR_TIMEOUT = -3 +ERROR_EXCEPTION = -4 + +_STREAMING_WORKER_CODE = ( + files(__package__) + .joinpath("emscripten_fetch_worker.js") + .read_text(encoding="utf-8") +) + + +class _RequestError(Exception): + def __init__( + self, + message: str | None = None, + *, + request: EmscriptenRequest | None = None, + response: EmscriptenResponse | None = None, + ): + self.request = request + self.response = response + self.message = message + super().__init__(self.message) + + +class _StreamingError(_RequestError): + pass + + +class _TimeoutError(_RequestError): + pass + + +def _obj_from_dict(dict_val: dict[str, Any]) -> JsProxy: + return to_js(dict_val, dict_converter=js.Object.fromEntries) + + +class _ReadStream(io.RawIOBase): + def __init__( + self, + int_buffer: JsArray, + byte_buffer: JsArray, + timeout: float, + worker: JsProxy, + connection_id: int, + request: EmscriptenRequest, + ): + self.int_buffer = int_buffer + self.byte_buffer = byte_buffer + self.read_pos = 0 + self.read_len = 0 + self.connection_id = connection_id + self.worker = worker + self.timeout = int(1000 * timeout) if timeout > 0 else None + self.is_live = True + self._is_closed = False + self.request: EmscriptenRequest | None = request + + def __del__(self) -> None: + self.close() + + # this is compatible with _base_connection + def is_closed(self) -> bool: + return self._is_closed + + # for compatibility with RawIOBase + @property + def closed(self) -> bool: + return self.is_closed() + + def close(self) -> None: + if self.is_closed(): + return + self.read_len = 0 + self.read_pos = 0 + self.int_buffer = None + self.byte_buffer = None + self._is_closed = True + self.request = None + if self.is_live: + self.worker.postMessage(_obj_from_dict({"close": self.connection_id})) + self.is_live = False + super().close() + + def readable(self) -> bool: + return True + + def writable(self) -> bool: + return False + + def seekable(self) -> bool: + return False + + def readinto(self, byte_obj: Buffer) -> int: + if not self.int_buffer: + raise _StreamingError( + "No buffer for stream in _ReadStream.readinto", + request=self.request, + response=None, + ) + if self.read_len == 0: + # wait for the worker to send something + js.Atomics.store(self.int_buffer, 0, ERROR_TIMEOUT) + self.worker.postMessage(_obj_from_dict({"getMore": self.connection_id})) + if ( + js.Atomics.wait(self.int_buffer, 0, ERROR_TIMEOUT, self.timeout) + == "timed-out" + ): + raise _TimeoutError + data_len = self.int_buffer[0] + if data_len > 0: + self.read_len = data_len + self.read_pos = 0 + elif data_len == ERROR_EXCEPTION: + string_len = self.int_buffer[1] + # decode the error string + js_decoder = js.TextDecoder.new() + json_str = js_decoder.decode(self.byte_buffer.slice(0, string_len)) + raise _StreamingError( + f"Exception thrown in fetch: {json_str}", + request=self.request, + response=None, + ) + else: + # EOF, free the buffers and return zero + # and free the request + self.is_live = False + self.close() + return 0 + # copy from int32array to python bytes + ret_length = min(self.read_len, len(memoryview(byte_obj))) + subarray = self.byte_buffer.subarray( + self.read_pos, self.read_pos + ret_length + ).to_py() + memoryview(byte_obj)[0:ret_length] = subarray + self.read_len -= ret_length + self.read_pos += ret_length + return ret_length + + +class _StreamingFetcher: + def __init__(self) -> None: + # make web-worker and data buffer on startup + self.streaming_ready = False + + js_data_blob = js.Blob.new( + to_js([_STREAMING_WORKER_CODE], create_pyproxies=False), + _obj_from_dict({"type": "application/javascript"}), + ) + + def promise_resolver(js_resolve_fn: JsProxy, js_reject_fn: JsProxy) -> None: + def onMsg(e: JsProxy) -> None: + self.streaming_ready = True + js_resolve_fn(e) + + def onErr(e: JsProxy) -> None: + js_reject_fn(e) # Defensive: never happens in ci + + self.js_worker.onmessage = onMsg + self.js_worker.onerror = onErr + + js_data_url = js.URL.createObjectURL(js_data_blob) + self.js_worker = js.globalThis.Worker.new(js_data_url) + self.js_worker_ready_promise = js.globalThis.Promise.new(promise_resolver) + + def send(self, request: EmscriptenRequest) -> EmscriptenResponse: + headers = { + k: v for k, v in request.headers.items() if k not in HEADERS_TO_IGNORE + } + + body = request.body + fetch_data = {"headers": headers, "body": to_js(body), "method": request.method} + # start the request off in the worker + timeout = int(1000 * request.timeout) if request.timeout > 0 else None + js_shared_buffer = js.SharedArrayBuffer.new(1048576) + js_int_buffer = js.Int32Array.new(js_shared_buffer) + js_byte_buffer = js.Uint8Array.new(js_shared_buffer, 8) + + js.Atomics.store(js_int_buffer, 0, ERROR_TIMEOUT) + js.Atomics.notify(js_int_buffer, 0) + js_absolute_url = js.URL.new(request.url, js.location).href + self.js_worker.postMessage( + _obj_from_dict( + { + "buffer": js_shared_buffer, + "url": js_absolute_url, + "fetchParams": fetch_data, + } + ) + ) + # wait for the worker to send something + js.Atomics.wait(js_int_buffer, 0, ERROR_TIMEOUT, timeout) + if js_int_buffer[0] == ERROR_TIMEOUT: + raise _TimeoutError( + "Timeout connecting to streaming request", + request=request, + response=None, + ) + elif js_int_buffer[0] == SUCCESS_HEADER: + # got response + # header length is in second int of intBuffer + string_len = js_int_buffer[1] + # decode the rest to a JSON string + js_decoder = js.TextDecoder.new() + # this does a copy (the slice) because decode can't work on shared array + # for some silly reason + json_str = js_decoder.decode(js_byte_buffer.slice(0, string_len)) + # get it as an object + response_obj = json.loads(json_str) + return EmscriptenResponse( + request=request, + status_code=response_obj["status"], + headers=response_obj["headers"], + body=_ReadStream( + js_int_buffer, + js_byte_buffer, + request.timeout, + self.js_worker, + response_obj["connectionID"], + request, + ), + ) + elif js_int_buffer[0] == ERROR_EXCEPTION: + string_len = js_int_buffer[1] + # decode the error string + js_decoder = js.TextDecoder.new() + json_str = js_decoder.decode(js_byte_buffer.slice(0, string_len)) + raise _StreamingError( + f"Exception thrown in fetch: {json_str}", request=request, response=None + ) + else: + raise _StreamingError( + f"Unknown status from worker in fetch: {js_int_buffer[0]}", + request=request, + response=None, + ) + + +class _JSPIReadStream(io.RawIOBase): + """ + A read stream that uses pyodide.ffi.run_sync to read from a JavaScript fetch + response. This requires support for WebAssembly JavaScript Promise Integration + in the containing browser, and for pyodide to be launched via runPythonAsync. + + :param js_read_stream: + The JavaScript stream reader + + :param timeout: + Timeout in seconds + + :param request: + The request we're handling + + :param response: + The response this stream relates to + + :param js_abort_controller: + A JavaScript AbortController object, used for timeouts + """ + + def __init__( + self, + js_read_stream: Any, + timeout: float, + request: EmscriptenRequest, + response: EmscriptenResponse, + js_abort_controller: Any, # JavaScript AbortController for timeouts + ): + self.js_read_stream = js_read_stream + self.timeout = timeout + self._is_closed = False + self._is_done = False + self.request: EmscriptenRequest | None = request + self.response: EmscriptenResponse | None = response + self.current_buffer = None + self.current_buffer_pos = 0 + self.js_abort_controller = js_abort_controller + + def __del__(self) -> None: + self.close() + + # this is compatible with _base_connection + def is_closed(self) -> bool: + return self._is_closed + + # for compatibility with RawIOBase + @property + def closed(self) -> bool: + return self.is_closed() + + def close(self) -> None: + if self.is_closed(): + return + self.read_len = 0 + self.read_pos = 0 + self.js_read_stream.cancel() + self.js_read_stream = None + self._is_closed = True + self._is_done = True + self.request = None + self.response = None + super().close() + + def readable(self) -> bool: + return True + + def writable(self) -> bool: + return False + + def seekable(self) -> bool: + return False + + def _get_next_buffer(self) -> bool: + result_js = _run_sync_with_timeout( + self.js_read_stream.read(), + self.timeout, + self.js_abort_controller, + request=self.request, + response=self.response, + ) + if result_js.done: + self._is_done = True + return False + else: + self.current_buffer = result_js.value.to_py() + self.current_buffer_pos = 0 + return True + + def readinto(self, byte_obj: Buffer) -> int: + if self.current_buffer is None: + if not self._get_next_buffer() or self.current_buffer is None: + self.close() + return 0 + ret_length = min( + len(byte_obj), len(self.current_buffer) - self.current_buffer_pos + ) + byte_obj[0:ret_length] = self.current_buffer[ + self.current_buffer_pos : self.current_buffer_pos + ret_length + ] + self.current_buffer_pos += ret_length + if self.current_buffer_pos == len(self.current_buffer): + self.current_buffer = None + return ret_length + + +# check if we are in a worker or not +def is_in_browser_main_thread() -> bool: + return hasattr(js, "window") and hasattr(js, "self") and js.self == js.window + + +def is_cross_origin_isolated() -> bool: + return hasattr(js, "crossOriginIsolated") and js.crossOriginIsolated + + +def is_in_node() -> bool: + return ( + hasattr(js, "process") + and hasattr(js.process, "release") + and hasattr(js.process.release, "name") + and js.process.release.name == "node" + ) + + +def is_worker_available() -> bool: + return hasattr(js, "Worker") and hasattr(js, "Blob") + + +_fetcher: _StreamingFetcher | None = None + +if is_worker_available() and ( + (is_cross_origin_isolated() and not is_in_browser_main_thread()) + and (not is_in_node()) +): + _fetcher = _StreamingFetcher() +else: + _fetcher = None + + +NODE_JSPI_ERROR = ( + "urllib3 only works in Node.js with pyodide.runPythonAsync" + " and requires the flag --experimental-wasm-stack-switching in " + " versions of node <24." +) + + +def send_streaming_request(request: EmscriptenRequest) -> EmscriptenResponse | None: + if has_jspi(): + return send_jspi_request(request, True) + elif is_in_node(): + raise _RequestError( + message=NODE_JSPI_ERROR, + request=request, + response=None, + ) + + if _fetcher and streaming_ready(): + return _fetcher.send(request) + else: + _show_streaming_warning() + return None + + +_SHOWN_TIMEOUT_WARNING = False + + +def _show_timeout_warning() -> None: + global _SHOWN_TIMEOUT_WARNING + if not _SHOWN_TIMEOUT_WARNING: + _SHOWN_TIMEOUT_WARNING = True + message = "Warning: Timeout is not available on main browser thread" + js.console.warn(message) + + +_SHOWN_STREAMING_WARNING = False + + +def _show_streaming_warning() -> None: + global _SHOWN_STREAMING_WARNING + if not _SHOWN_STREAMING_WARNING: + _SHOWN_STREAMING_WARNING = True + message = "Can't stream HTTP requests because: \n" + if not is_cross_origin_isolated(): + message += " Page is not cross-origin isolated\n" + if is_in_browser_main_thread(): + message += " Python is running in main browser thread\n" + if not is_worker_available(): + message += " Worker or Blob classes are not available in this environment." # Defensive: this is always False in browsers that we test in + if streaming_ready() is False: + message += """ Streaming fetch worker isn't ready. If you want to be sure that streaming fetch +is working, you need to call: 'await urllib3.contrib.emscripten.fetch.wait_for_streaming_ready()`""" + from js import console + + console.warn(message) + + +def send_request(request: EmscriptenRequest) -> EmscriptenResponse: + if has_jspi(): + return send_jspi_request(request, False) + elif is_in_node(): + raise _RequestError( + message=NODE_JSPI_ERROR, + request=request, + response=None, + ) + try: + js_xhr = js.XMLHttpRequest.new() + + if not is_in_browser_main_thread(): + js_xhr.responseType = "arraybuffer" + if request.timeout: + js_xhr.timeout = int(request.timeout * 1000) + else: + js_xhr.overrideMimeType("text/plain; charset=ISO-8859-15") + if request.timeout: + # timeout isn't available on the main thread - show a warning in console + # if it is set + _show_timeout_warning() + + js_xhr.open(request.method, request.url, False) + for name, value in request.headers.items(): + if name.lower() not in HEADERS_TO_IGNORE: + js_xhr.setRequestHeader(name, value) + + js_xhr.send(to_js(request.body)) + + headers = dict(Parser().parsestr(js_xhr.getAllResponseHeaders())) + + if not is_in_browser_main_thread(): + body = js_xhr.response.to_py().tobytes() + else: + body = js_xhr.response.encode("ISO-8859-15") + return EmscriptenResponse( + status_code=js_xhr.status, headers=headers, body=body, request=request + ) + except JsException as err: + if err.name == "TimeoutError": + raise _TimeoutError(err.message, request=request) + elif err.name == "NetworkError": + raise _RequestError(err.message, request=request) + else: + # general http error + raise _RequestError(err.message, request=request) + + +def send_jspi_request( + request: EmscriptenRequest, streaming: bool +) -> EmscriptenResponse: + """ + Send a request using WebAssembly JavaScript Promise Integration + to wrap the asynchronous JavaScript fetch api (experimental). + + :param request: + Request to send + + :param streaming: + Whether to stream the response + + :return: The response object + :rtype: EmscriptenResponse + """ + timeout = request.timeout + js_abort_controller = js.AbortController.new() + headers = {k: v for k, v in request.headers.items() if k not in HEADERS_TO_IGNORE} + req_body = request.body + fetch_data = { + "headers": headers, + "body": to_js(req_body), + "method": request.method, + "signal": js_abort_controller.signal, + } + # Call JavaScript fetch (async api, returns a promise) + fetcher_promise_js = js.fetch(request.url, _obj_from_dict(fetch_data)) + # Now suspend WebAssembly until we resolve that promise + # or time out. + response_js = _run_sync_with_timeout( + fetcher_promise_js, + timeout, + js_abort_controller, + request=request, + response=None, + ) + headers = {} + header_iter = response_js.headers.entries() + while True: + iter_value_js = header_iter.next() + if getattr(iter_value_js, "done", False): + break + else: + headers[str(iter_value_js.value[0])] = str(iter_value_js.value[1]) + status_code = response_js.status + body: bytes | io.RawIOBase = b"" + + response = EmscriptenResponse( + status_code=status_code, headers=headers, body=b"", request=request + ) + if streaming: + # get via inputstream + if response_js.body is not None: + # get a reader from the fetch response + body_stream_js = response_js.body.getReader() + body = _JSPIReadStream( + body_stream_js, timeout, request, response, js_abort_controller + ) + else: + # get directly via arraybuffer + # n.b. this is another async JavaScript call. + body = _run_sync_with_timeout( + response_js.arrayBuffer(), + timeout, + js_abort_controller, + request=request, + response=response, + ).to_py() + response.body = body + return response + + +def _run_sync_with_timeout( + promise: Any, + timeout: float, + js_abort_controller: Any, + request: EmscriptenRequest | None, + response: EmscriptenResponse | None, +) -> Any: + """ + Await a JavaScript promise synchronously with a timeout which is implemented + via the AbortController + + :param promise: + Javascript promise to await + + :param timeout: + Timeout in seconds + + :param js_abort_controller: + A JavaScript AbortController object, used on timeout + + :param request: + The request being handled + + :param response: + The response being handled (if it exists yet) + + :raises _TimeoutError: If the request times out + :raises _RequestError: If the request raises a JavaScript exception + + :return: The result of awaiting the promise. + """ + timer_id = None + if timeout > 0: + timer_id = js.setTimeout( + js_abort_controller.abort.bind(js_abort_controller), int(timeout * 1000) + ) + try: + from pyodide.ffi import run_sync + + # run_sync here uses WebAssembly JavaScript Promise Integration to + # suspend python until the JavaScript promise resolves. + return run_sync(promise) + except JsException as err: + if err.name == "AbortError": + raise _TimeoutError( + message="Request timed out", request=request, response=response + ) + else: + raise _RequestError(message=err.message, request=request, response=response) + finally: + if timer_id is not None: + js.clearTimeout(timer_id) + + +def has_jspi() -> bool: + """ + Return true if jspi can be used. + + This requires both browser support and also WebAssembly + to be in the correct state - i.e. that the javascript + call into python was async not sync. + + :return: True if jspi can be used. + :rtype: bool + """ + try: + from pyodide.ffi import can_run_sync, run_sync # noqa: F401 + + return bool(can_run_sync()) + except ImportError: + return False + + +def streaming_ready() -> bool | None: + if _fetcher: + return _fetcher.streaming_ready + else: + return None # no fetcher, return None to signify that + + +async def wait_for_streaming_ready() -> bool: + if _fetcher: + await _fetcher.js_worker_ready_promise + return True + else: + return False diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/request.py b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/request.py new file mode 100644 index 000000000..e692e692b --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/request.py @@ -0,0 +1,22 @@ +from __future__ import annotations + +from dataclasses import dataclass, field + +from ..._base_connection import _TYPE_BODY + + +@dataclass +class EmscriptenRequest: + method: str + url: str + params: dict[str, str] | None = None + body: _TYPE_BODY | None = None + headers: dict[str, str] = field(default_factory=dict) + timeout: float = 0 + decode_content: bool = True + + def set_header(self, name: str, value: str) -> None: + self.headers[name.capitalize()] = value + + def set_body(self, body: _TYPE_BODY | None) -> None: + self.body = body diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/response.py b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/response.py new file mode 100644 index 000000000..b32b40237 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/emscripten/response.py @@ -0,0 +1,285 @@ +from __future__ import annotations + +import json as _json +import logging +import typing +from contextlib import contextmanager +from dataclasses import dataclass +from http.client import HTTPException as HTTPException +from io import BytesIO, IOBase + +from ...exceptions import InvalidHeader, TimeoutError +from ...response import BaseHTTPResponse +from ...util.retry import Retry +from .request import EmscriptenRequest + +if typing.TYPE_CHECKING: + from ..._base_connection import BaseHTTPConnection, BaseHTTPSConnection + +log = logging.getLogger(__name__) + + +@dataclass +class EmscriptenResponse: + status_code: int + headers: dict[str, str] + body: IOBase | bytes + request: EmscriptenRequest + + +class EmscriptenHttpResponseWrapper(BaseHTTPResponse): + def __init__( + self, + internal_response: EmscriptenResponse, + url: str | None = None, + connection: BaseHTTPConnection | BaseHTTPSConnection | None = None, + ): + self._pool = None # set by pool class + self._body = None + self._response = internal_response + self._url = url + self._connection = connection + self._closed = False + super().__init__( + headers=internal_response.headers, + status=internal_response.status_code, + request_url=url, + version=0, + version_string="HTTP/?", + reason="", + decode_content=True, + ) + self.length_remaining = self._init_length(self._response.request.method) + self.length_is_certain = False + + @property + def url(self) -> str | None: + return self._url + + @url.setter + def url(self, url: str | None) -> None: + self._url = url + + @property + def connection(self) -> BaseHTTPConnection | BaseHTTPSConnection | None: + return self._connection + + @property + def retries(self) -> Retry | None: + return self._retries + + @retries.setter + def retries(self, retries: Retry | None) -> None: + # Override the request_url if retries has a redirect location. + self._retries = retries + + def stream( + self, amt: int | None = 2**16, decode_content: bool | None = None + ) -> typing.Generator[bytes]: + """ + A generator wrapper for the read() method. A call will block until + ``amt`` bytes have been read from the connection or until the + connection is closed. + + :param amt: + How much of the content to read. The generator will return up to + much data per iteration, but may return less. This is particularly + likely when using compressed data. However, the empty string will + never be returned. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + while True: + data = self.read(amt=amt, decode_content=decode_content) + + if data: + yield data + else: + break + + def _init_length(self, request_method: str | None) -> int | None: + length: int | None + content_length: str | None = self.headers.get("content-length") + + if content_length is not None: + try: + # RFC 7230 section 3.3.2 specifies multiple content lengths can + # be sent in a single Content-Length header + # (e.g. Content-Length: 42, 42). This line ensures the values + # are all valid ints and that as long as the `set` length is 1, + # all values are the same. Otherwise, the header is invalid. + lengths = {int(val) for val in content_length.split(",")} + if len(lengths) > 1: + raise InvalidHeader( + "Content-Length contained multiple " + "unmatching values (%s)" % content_length + ) + length = lengths.pop() + except ValueError: + length = None + else: + if length < 0: + length = None + + else: # if content_length is None + length = None + + # Check for responses that shouldn't include a body + if ( + self.status in (204, 304) + or 100 <= self.status < 200 + or request_method == "HEAD" + ): + length = 0 + + return length + + def read( + self, + amt: int | None = None, + decode_content: bool | None = None, # ignored because browser decodes always + cache_content: bool = False, + ) -> bytes: + if ( + self._closed + or self._response is None + or (isinstance(self._response.body, IOBase) and self._response.body.closed) + ): + return b"" + + with self._error_catcher(): + # body has been preloaded as a string by XmlHttpRequest + if not isinstance(self._response.body, IOBase): + self.length_remaining = len(self._response.body) + self.length_is_certain = True + # wrap body in IOStream + self._response.body = BytesIO(self._response.body) + if amt is not None and amt >= 0: + # don't cache partial content + cache_content = False + data = self._response.body.read(amt) + if self.length_remaining is not None: + self.length_remaining = max(self.length_remaining - len(data), 0) + if (self.length_is_certain and self.length_remaining == 0) or len( + data + ) < amt: + # definitely finished reading, close response stream + self._response.body.close() + return typing.cast(bytes, data) + else: # read all we can (and cache it) + data = self._response.body.read() + if cache_content: + self._body = data + if self.length_remaining is not None: + self.length_remaining = max(self.length_remaining - len(data), 0) + if len(data) == 0 or ( + self.length_is_certain and self.length_remaining == 0 + ): + # definitely finished reading, close response stream + self._response.body.close() + return typing.cast(bytes, data) + + def read_chunked( + self, + amt: int | None = None, + decode_content: bool | None = None, + ) -> typing.Generator[bytes]: + # chunked is handled by browser + while True: + bytes = self.read(amt, decode_content) + if not bytes: + break + yield bytes + + def release_conn(self) -> None: + if not self._pool or not self._connection: + return None + + self._pool._put_conn(self._connection) + self._connection = None + + def drain_conn(self) -> None: + self.close() + + @property + def data(self) -> bytes: + if self._body: + return self._body + else: + return self.read(cache_content=True) + + def json(self) -> typing.Any: + """ + Deserializes the body of the HTTP response as a Python object. + + The body of the HTTP response must be encoded using UTF-8, as per + `RFC 8529 Section 8.1 `_. + + To use a custom JSON decoder pass the result of :attr:`HTTPResponse.data` to + your custom decoder instead. + + If the body of the HTTP response is not decodable to UTF-8, a + `UnicodeDecodeError` will be raised. If the body of the HTTP response is not a + valid JSON document, a `json.JSONDecodeError` will be raised. + + Read more :ref:`here `. + + :returns: The body of the HTTP response as a Python object. + """ + data = self.data.decode("utf-8") + return _json.loads(data) + + def close(self) -> None: + if not self._closed: + if isinstance(self._response.body, IOBase): + self._response.body.close() + if self._connection: + self._connection.close() + self._connection = None + self._closed = True + + @contextmanager + def _error_catcher(self) -> typing.Generator[None]: + """ + Catch Emscripten specific exceptions thrown by fetch.py, + instead re-raising urllib3 variants, so that low-level exceptions + are not leaked in the high-level api. + + On exit, release the connection back to the pool. + """ + from .fetch import _RequestError, _TimeoutError # avoid circular import + + clean_exit = False + + try: + yield + # If no exception is thrown, we should avoid cleaning up + # unnecessarily. + clean_exit = True + except _TimeoutError as e: + raise TimeoutError(str(e)) + except _RequestError as e: + raise HTTPException(str(e)) + finally: + # If we didn't terminate cleanly, we need to throw away our + # connection. + if not clean_exit: + # The response may not be closed but we're not going to use it + # anymore so close it now + if ( + isinstance(self._response.body, IOBase) + and not self._response.body.closed + ): + self._response.body.close() + # release the connection back to the pool + self.release_conn() + else: + # If we have read everything from the response stream, + # return the connection back to the pool. + if ( + isinstance(self._response.body, IOBase) + and self._response.body.closed + ): + self.release_conn() diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/pyopenssl.py b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/pyopenssl.py new file mode 100644 index 000000000..ed6543066 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/pyopenssl.py @@ -0,0 +1,554 @@ +""" +Module for using pyOpenSSL as a TLS backend. This module was relevant before +the standard library ``ssl`` module supported SNI, but now that we've dropped +support for Python 2.7 all relevant Python versions support SNI so +**this module is no longer recommended**. + +This needs the following packages installed: + +* `pyOpenSSL`_ (tested with 16.0.0) +* `cryptography`_ (minimum 1.3.4, from pyopenssl) +* `idna`_ (minimum 2.0) + +However, pyOpenSSL depends on cryptography, so while we use all three directly here we +end up having relatively few packages required. + +You can install them with the following command: + +.. code-block:: bash + + $ python -m pip install pyopenssl cryptography idna + +To activate certificate checking, call +:func:`~urllib3.contrib.pyopenssl.inject_into_urllib3` from your Python code +before you begin making HTTP requests. This can be done in a ``sitecustomize`` +module, or at any other time before your application begins using ``urllib3``, +like this: + +.. code-block:: python + + try: + import urllib3.contrib.pyopenssl + urllib3.contrib.pyopenssl.inject_into_urllib3() + except ImportError: + pass + +.. _pyopenssl: https://www.pyopenssl.org +.. _cryptography: https://cryptography.io +.. _idna: https://github.com/kjd/idna +""" + +from __future__ import annotations + +import OpenSSL.SSL # type: ignore[import-untyped] +from cryptography import x509 + +try: + from cryptography.x509 import UnsupportedExtension # type: ignore[attr-defined] +except ImportError: + # UnsupportedExtension is gone in cryptography >= 2.1.0 + class UnsupportedExtension(Exception): # type: ignore[no-redef] + pass + + +import logging +import ssl +import typing +from io import BytesIO +from socket import socket as socket_cls +from socket import timeout + +from .. import util + +if typing.TYPE_CHECKING: + from OpenSSL.crypto import X509 # type: ignore[import-untyped] + + +__all__ = ["inject_into_urllib3", "extract_from_urllib3"] + +# Map from urllib3 to PyOpenSSL compatible parameter-values. +_openssl_versions: dict[int, int] = { + util.ssl_.PROTOCOL_TLS: OpenSSL.SSL.SSLv23_METHOD, # type: ignore[attr-defined] + util.ssl_.PROTOCOL_TLS_CLIENT: OpenSSL.SSL.SSLv23_METHOD, # type: ignore[attr-defined] + ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, +} + +if hasattr(ssl, "PROTOCOL_TLSv1_1") and hasattr(OpenSSL.SSL, "TLSv1_1_METHOD"): + _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD + +if hasattr(ssl, "PROTOCOL_TLSv1_2") and hasattr(OpenSSL.SSL, "TLSv1_2_METHOD"): + _openssl_versions[ssl.PROTOCOL_TLSv1_2] = OpenSSL.SSL.TLSv1_2_METHOD + + +_stdlib_to_openssl_verify = { + ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE, + ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER, + ssl.CERT_REQUIRED: OpenSSL.SSL.VERIFY_PEER + + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT, +} +_openssl_to_stdlib_verify = {v: k for k, v in _stdlib_to_openssl_verify.items()} + +# The SSLvX values are the most likely to be missing in the future +# but we check them all just to be sure. +_OP_NO_SSLv2_OR_SSLv3: int = getattr(OpenSSL.SSL, "OP_NO_SSLv2", 0) | getattr( + OpenSSL.SSL, "OP_NO_SSLv3", 0 +) +_OP_NO_TLSv1: int = getattr(OpenSSL.SSL, "OP_NO_TLSv1", 0) +_OP_NO_TLSv1_1: int = getattr(OpenSSL.SSL, "OP_NO_TLSv1_1", 0) +_OP_NO_TLSv1_2: int = getattr(OpenSSL.SSL, "OP_NO_TLSv1_2", 0) +_OP_NO_TLSv1_3: int = getattr(OpenSSL.SSL, "OP_NO_TLSv1_3", 0) + +_openssl_to_ssl_minimum_version: dict[int, int] = { + ssl.TLSVersion.MINIMUM_SUPPORTED: _OP_NO_SSLv2_OR_SSLv3, + ssl.TLSVersion.TLSv1: _OP_NO_SSLv2_OR_SSLv3, + ssl.TLSVersion.TLSv1_1: _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1, + ssl.TLSVersion.TLSv1_2: _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1 | _OP_NO_TLSv1_1, + ssl.TLSVersion.TLSv1_3: ( + _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1 | _OP_NO_TLSv1_1 | _OP_NO_TLSv1_2 + ), + ssl.TLSVersion.MAXIMUM_SUPPORTED: ( + _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1 | _OP_NO_TLSv1_1 | _OP_NO_TLSv1_2 + ), +} +_openssl_to_ssl_maximum_version: dict[int, int] = { + ssl.TLSVersion.MINIMUM_SUPPORTED: ( + _OP_NO_SSLv2_OR_SSLv3 + | _OP_NO_TLSv1 + | _OP_NO_TLSv1_1 + | _OP_NO_TLSv1_2 + | _OP_NO_TLSv1_3 + ), + ssl.TLSVersion.TLSv1: ( + _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1_1 | _OP_NO_TLSv1_2 | _OP_NO_TLSv1_3 + ), + ssl.TLSVersion.TLSv1_1: _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1_2 | _OP_NO_TLSv1_3, + ssl.TLSVersion.TLSv1_2: _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1_3, + ssl.TLSVersion.TLSv1_3: _OP_NO_SSLv2_OR_SSLv3, + ssl.TLSVersion.MAXIMUM_SUPPORTED: _OP_NO_SSLv2_OR_SSLv3, +} + +# OpenSSL will only write 16K at a time +SSL_WRITE_BLOCKSIZE = 16384 + +orig_util_SSLContext = util.ssl_.SSLContext + + +log = logging.getLogger(__name__) + + +def inject_into_urllib3() -> None: + "Monkey-patch urllib3 with PyOpenSSL-backed SSL-support." + + _validate_dependencies_met() + + util.SSLContext = PyOpenSSLContext # type: ignore[assignment] + util.ssl_.SSLContext = PyOpenSSLContext # type: ignore[assignment] + util.IS_PYOPENSSL = True + util.ssl_.IS_PYOPENSSL = True + + +def extract_from_urllib3() -> None: + "Undo monkey-patching by :func:`inject_into_urllib3`." + + util.SSLContext = orig_util_SSLContext + util.ssl_.SSLContext = orig_util_SSLContext + util.IS_PYOPENSSL = False + util.ssl_.IS_PYOPENSSL = False + + +def _validate_dependencies_met() -> None: + """ + Verifies that PyOpenSSL's package-level dependencies have been met. + Throws `ImportError` if they are not met. + """ + # Method added in `cryptography==1.1`; not available in older versions + from cryptography.x509.extensions import Extensions + + if getattr(Extensions, "get_extension_for_class", None) is None: + raise ImportError( + "'cryptography' module missing required functionality. " + "Try upgrading to v1.3.4 or newer." + ) + + # pyOpenSSL 0.14 and above use cryptography for OpenSSL bindings. The _x509 + # attribute is only present on those versions. + from OpenSSL.crypto import X509 + + x509 = X509() + if getattr(x509, "_x509", None) is None: + raise ImportError( + "'pyOpenSSL' module missing required functionality. " + "Try upgrading to v0.14 or newer." + ) + + +def _dnsname_to_stdlib(name: str) -> str | None: + """ + Converts a dNSName SubjectAlternativeName field to the form used by the + standard library on the given Python version. + + Cryptography produces a dNSName as a unicode string that was idna-decoded + from ASCII bytes. We need to idna-encode that string to get it back, and + then on Python 3 we also need to convert to unicode via UTF-8 (the stdlib + uses PyUnicode_FromStringAndSize on it, which decodes via UTF-8). + + If the name cannot be idna-encoded then we return None signalling that + the name given should be skipped. + """ + + def idna_encode(name: str) -> bytes | None: + """ + Borrowed wholesale from the Python Cryptography Project. It turns out + that we can't just safely call `idna.encode`: it can explode for + wildcard names. This avoids that problem. + """ + import idna + + try: + for prefix in ["*.", "."]: + if name.startswith(prefix): + name = name[len(prefix) :] + return prefix.encode("ascii") + idna.encode(name) + return idna.encode(name) + except idna.core.IDNAError: + return None + + # Don't send IPv6 addresses through the IDNA encoder. + if ":" in name: + return name + + encoded_name = idna_encode(name) + if encoded_name is None: + return None + return encoded_name.decode("utf-8") + + +def get_subj_alt_name(peer_cert: X509) -> list[tuple[str, str]]: + """ + Given an PyOpenSSL certificate, provides all the subject alternative names. + """ + cert = peer_cert.to_cryptography() + + # We want to find the SAN extension. Ask Cryptography to locate it (it's + # faster than looping in Python) + try: + ext = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName).value + except x509.ExtensionNotFound: + # No such extension, return the empty list. + return [] + except ( + x509.DuplicateExtension, + UnsupportedExtension, + x509.UnsupportedGeneralNameType, + UnicodeError, + ) as e: + # A problem has been found with the quality of the certificate. Assume + # no SAN field is present. + log.warning( + "A problem was encountered with the certificate that prevented " + "urllib3 from finding the SubjectAlternativeName field. This can " + "affect certificate validation. The error was %s", + e, + ) + return [] + + # We want to return dNSName and iPAddress fields. We need to cast the IPs + # back to strings because the match_hostname function wants them as + # strings. + # Sadly the DNS names need to be idna encoded and then, on Python 3, UTF-8 + # decoded. This is pretty frustrating, but that's what the standard library + # does with certificates, and so we need to attempt to do the same. + # We also want to skip over names which cannot be idna encoded. + names = [ + ("DNS", name) + for name in map(_dnsname_to_stdlib, ext.get_values_for_type(x509.DNSName)) + if name is not None + ] + names.extend( + ("IP Address", str(name)) for name in ext.get_values_for_type(x509.IPAddress) + ) + + return names + + +class WrappedSocket: + """API-compatibility wrapper for Python OpenSSL's Connection-class.""" + + def __init__( + self, + connection: OpenSSL.SSL.Connection, + socket: socket_cls, + suppress_ragged_eofs: bool = True, + ) -> None: + self.connection = connection + self.socket = socket + self.suppress_ragged_eofs = suppress_ragged_eofs + self._io_refs = 0 + self._closed = False + + def fileno(self) -> int: + return self.socket.fileno() + + # Copy-pasted from Python 3.5 source code + def _decref_socketios(self) -> None: + if self._io_refs > 0: + self._io_refs -= 1 + if self._closed: + self.close() + + def recv(self, *args: typing.Any, **kwargs: typing.Any) -> bytes: + try: + data = self.connection.recv(*args, **kwargs) + except OpenSSL.SSL.SysCallError as e: + if self.suppress_ragged_eofs and e.args == (-1, "Unexpected EOF"): + return b"" + else: + raise OSError(e.args[0], str(e)) from e + except OpenSSL.SSL.ZeroReturnError: + if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN: + return b"" + else: + raise + except OpenSSL.SSL.WantReadError as e: + if not util.wait_for_read(self.socket, self.socket.gettimeout()): + raise timeout("The read operation timed out") from e + else: + return self.recv(*args, **kwargs) + + # TLS 1.3 post-handshake authentication + except OpenSSL.SSL.Error as e: + raise ssl.SSLError(f"read error: {e!r}") from e + else: + return data # type: ignore[no-any-return] + + def recv_into(self, *args: typing.Any, **kwargs: typing.Any) -> int: + try: + return self.connection.recv_into(*args, **kwargs) # type: ignore[no-any-return] + except OpenSSL.SSL.SysCallError as e: + if self.suppress_ragged_eofs and e.args == (-1, "Unexpected EOF"): + return 0 + else: + raise OSError(e.args[0], str(e)) from e + except OpenSSL.SSL.ZeroReturnError: + if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN: + return 0 + else: + raise + except OpenSSL.SSL.WantReadError as e: + if not util.wait_for_read(self.socket, self.socket.gettimeout()): + raise timeout("The read operation timed out") from e + else: + return self.recv_into(*args, **kwargs) + + # TLS 1.3 post-handshake authentication + except OpenSSL.SSL.Error as e: + raise ssl.SSLError(f"read error: {e!r}") from e + + def settimeout(self, timeout: float) -> None: + return self.socket.settimeout(timeout) + + def _send_until_done(self, data: bytes) -> int: + while True: + try: + return self.connection.send(data) # type: ignore[no-any-return] + except OpenSSL.SSL.WantWriteError as e: + if not util.wait_for_write(self.socket, self.socket.gettimeout()): + raise timeout() from e + continue + except OpenSSL.SSL.SysCallError as e: + raise OSError(e.args[0], str(e)) from e + + def sendall(self, data: bytes) -> None: + total_sent = 0 + while total_sent < len(data): + sent = self._send_until_done( + data[total_sent : total_sent + SSL_WRITE_BLOCKSIZE] + ) + total_sent += sent + + def shutdown(self, how: int) -> None: + try: + self.connection.shutdown() + except OpenSSL.SSL.Error as e: + raise ssl.SSLError(f"shutdown error: {e!r}") from e + + def close(self) -> None: + self._closed = True + if self._io_refs <= 0: + self._real_close() + + def _real_close(self) -> None: + try: + return self.connection.close() # type: ignore[no-any-return] + except OpenSSL.SSL.Error: + return + + def getpeercert( + self, binary_form: bool = False + ) -> dict[str, list[typing.Any]] | None: + x509 = self.connection.get_peer_certificate() + + if not x509: + return x509 # type: ignore[no-any-return] + + if binary_form: + return OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_ASN1, x509) # type: ignore[no-any-return] + + return { + "subject": ((("commonName", x509.get_subject().CN),),), # type: ignore[dict-item] + "subjectAltName": get_subj_alt_name(x509), + } + + def version(self) -> str: + return self.connection.get_protocol_version_name() # type: ignore[no-any-return] + + def selected_alpn_protocol(self) -> str | None: + alpn_proto = self.connection.get_alpn_proto_negotiated() + return alpn_proto.decode() if alpn_proto else None + + +WrappedSocket.makefile = socket_cls.makefile # type: ignore[attr-defined] + + +class PyOpenSSLContext: + """ + I am a wrapper class for the PyOpenSSL ``Context`` object. I am responsible + for translating the interface of the standard library ``SSLContext`` object + to calls into PyOpenSSL. + """ + + def __init__(self, protocol: int) -> None: + self.protocol = _openssl_versions[protocol] + self._ctx = OpenSSL.SSL.Context(self.protocol) + self._options = 0 + self.check_hostname = False + self._minimum_version: int = ssl.TLSVersion.MINIMUM_SUPPORTED + self._maximum_version: int = ssl.TLSVersion.MAXIMUM_SUPPORTED + + @property + def options(self) -> int: + return self._options + + @options.setter + def options(self, value: int) -> None: + self._options = value + self._set_ctx_options() + + @property + def verify_mode(self) -> int: + return _openssl_to_stdlib_verify[self._ctx.get_verify_mode()] + + @verify_mode.setter + def verify_mode(self, value: ssl.VerifyMode) -> None: + self._ctx.set_verify(_stdlib_to_openssl_verify[value], _verify_callback) + + def set_default_verify_paths(self) -> None: + self._ctx.set_default_verify_paths() + + def set_ciphers(self, ciphers: bytes | str) -> None: + if isinstance(ciphers, str): + ciphers = ciphers.encode("utf-8") + self._ctx.set_cipher_list(ciphers) + + def load_verify_locations( + self, + cafile: str | None = None, + capath: str | None = None, + cadata: bytes | None = None, + ) -> None: + if cafile is not None: + cafile = cafile.encode("utf-8") # type: ignore[assignment] + if capath is not None: + capath = capath.encode("utf-8") # type: ignore[assignment] + try: + self._ctx.load_verify_locations(cafile, capath) + if cadata is not None: + self._ctx.load_verify_locations(BytesIO(cadata)) + except OpenSSL.SSL.Error as e: + raise ssl.SSLError(f"unable to load trusted certificates: {e!r}") from e + + def load_cert_chain( + self, + certfile: str, + keyfile: str | None = None, + password: str | None = None, + ) -> None: + try: + self._ctx.use_certificate_chain_file(certfile) + if password is not None: + if not isinstance(password, bytes): + password = password.encode("utf-8") # type: ignore[assignment] + self._ctx.set_passwd_cb(lambda *_: password) + self._ctx.use_privatekey_file(keyfile or certfile) + except OpenSSL.SSL.Error as e: + raise ssl.SSLError(f"Unable to load certificate chain: {e!r}") from e + + def set_alpn_protocols(self, protocols: list[bytes | str]) -> None: + protocols = [util.util.to_bytes(p, "ascii") for p in protocols] + return self._ctx.set_alpn_protos(protocols) # type: ignore[no-any-return] + + def wrap_socket( + self, + sock: socket_cls, + server_side: bool = False, + do_handshake_on_connect: bool = True, + suppress_ragged_eofs: bool = True, + server_hostname: bytes | str | None = None, + ) -> WrappedSocket: + cnx = OpenSSL.SSL.Connection(self._ctx, sock) + + # If server_hostname is an IP, don't use it for SNI, per RFC6066 Section 3 + if server_hostname and not util.ssl_.is_ipaddress(server_hostname): + if isinstance(server_hostname, str): + server_hostname = server_hostname.encode("utf-8") + cnx.set_tlsext_host_name(server_hostname) + + cnx.set_connect_state() + + while True: + try: + cnx.do_handshake() + except OpenSSL.SSL.WantReadError as e: + if not util.wait_for_read(sock, sock.gettimeout()): + raise timeout("select timed out") from e + continue + except OpenSSL.SSL.Error as e: + raise ssl.SSLError(f"bad handshake: {e!r}") from e + break + + return WrappedSocket(cnx, sock) + + def _set_ctx_options(self) -> None: + self._ctx.set_options( + self._options + | _openssl_to_ssl_minimum_version[self._minimum_version] + | _openssl_to_ssl_maximum_version[self._maximum_version] + ) + + @property + def minimum_version(self) -> int: + return self._minimum_version + + @minimum_version.setter + def minimum_version(self, minimum_version: int) -> None: + self._minimum_version = minimum_version + self._set_ctx_options() + + @property + def maximum_version(self) -> int: + return self._maximum_version + + @maximum_version.setter + def maximum_version(self, maximum_version: int) -> None: + self._maximum_version = maximum_version + self._set_ctx_options() + + +def _verify_callback( + cnx: OpenSSL.SSL.Connection, + x509: X509, + err_no: int, + err_depth: int, + return_code: int, +) -> bool: + return err_no == 0 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/socks.py b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/socks.py new file mode 100644 index 000000000..c62b5e033 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/contrib/socks.py @@ -0,0 +1,228 @@ +""" +This module contains provisional support for SOCKS proxies from within +urllib3. This module supports SOCKS4, SOCKS4A (an extension of SOCKS4), and +SOCKS5. To enable its functionality, either install PySocks or install this +module with the ``socks`` extra. + +The SOCKS implementation supports the full range of urllib3 features. It also +supports the following SOCKS features: + +- SOCKS4A (``proxy_url='socks4a://...``) +- SOCKS4 (``proxy_url='socks4://...``) +- SOCKS5 with remote DNS (``proxy_url='socks5h://...``) +- SOCKS5 with local DNS (``proxy_url='socks5://...``) +- Usernames and passwords for the SOCKS proxy + +.. note:: + It is recommended to use ``socks5h://`` or ``socks4a://`` schemes in + your ``proxy_url`` to ensure that DNS resolution is done from the remote + server instead of client-side when connecting to a domain name. + +SOCKS4 supports IPv4 and domain names with the SOCKS4A extension. SOCKS5 +supports IPv4, IPv6, and domain names. + +When connecting to a SOCKS4 proxy the ``username`` portion of the ``proxy_url`` +will be sent as the ``userid`` section of the SOCKS request: + +.. code-block:: python + + proxy_url="socks4a://@proxy-host" + +When connecting to a SOCKS5 proxy the ``username`` and ``password`` portion +of the ``proxy_url`` will be sent as the username/password to authenticate +with the proxy: + +.. code-block:: python + + proxy_url="socks5h://:@proxy-host" + +""" + +from __future__ import annotations + +try: + import socks # type: ignore[import-not-found] +except ImportError: + import warnings + + from ..exceptions import DependencyWarning + + warnings.warn( + ( + "SOCKS support in urllib3 requires the installation of optional " + "dependencies: specifically, PySocks. For more information, see " + "https://urllib3.readthedocs.io/en/latest/advanced-usage.html#socks-proxies" + ), + DependencyWarning, + ) + raise + +import typing +from socket import timeout as SocketTimeout + +from ..connection import HTTPConnection, HTTPSConnection +from ..connectionpool import HTTPConnectionPool, HTTPSConnectionPool +from ..exceptions import ConnectTimeoutError, NewConnectionError +from ..poolmanager import PoolManager +from ..util.url import parse_url + +try: + import ssl +except ImportError: + ssl = None # type: ignore[assignment] + + +class _TYPE_SOCKS_OPTIONS(typing.TypedDict): + socks_version: int + proxy_host: str | None + proxy_port: str | None + username: str | None + password: str | None + rdns: bool + + +class SOCKSConnection(HTTPConnection): + """ + A plain-text HTTP connection that connects via a SOCKS proxy. + """ + + def __init__( + self, + _socks_options: _TYPE_SOCKS_OPTIONS, + *args: typing.Any, + **kwargs: typing.Any, + ) -> None: + self._socks_options = _socks_options + super().__init__(*args, **kwargs) + + def _new_conn(self) -> socks.socksocket: + """ + Establish a new connection via the SOCKS proxy. + """ + extra_kw: dict[str, typing.Any] = {} + if self.source_address: + extra_kw["source_address"] = self.source_address + + if self.socket_options: + extra_kw["socket_options"] = self.socket_options + + try: + conn = socks.create_connection( + (self.host, self.port), + proxy_type=self._socks_options["socks_version"], + proxy_addr=self._socks_options["proxy_host"], + proxy_port=self._socks_options["proxy_port"], + proxy_username=self._socks_options["username"], + proxy_password=self._socks_options["password"], + proxy_rdns=self._socks_options["rdns"], + timeout=self.timeout, + **extra_kw, + ) + + except SocketTimeout as e: + raise ConnectTimeoutError( + self, + f"Connection to {self.host} timed out. (connect timeout={self.timeout})", + ) from e + + except socks.ProxyError as e: + # This is fragile as hell, but it seems to be the only way to raise + # useful errors here. + if e.socket_err: + error = e.socket_err + if isinstance(error, SocketTimeout): + raise ConnectTimeoutError( + self, + f"Connection to {self.host} timed out. (connect timeout={self.timeout})", + ) from e + else: + # Adding `from e` messes with coverage somehow, so it's omitted. + # See #2386. + raise NewConnectionError( + self, f"Failed to establish a new connection: {error}" + ) + else: + raise NewConnectionError( + self, f"Failed to establish a new connection: {e}" + ) from e + + except OSError as e: # Defensive: PySocks should catch all these. + raise NewConnectionError( + self, f"Failed to establish a new connection: {e}" + ) from e + + return conn + + +# We don't need to duplicate the Verified/Unverified distinction from +# urllib3/connection.py here because the HTTPSConnection will already have been +# correctly set to either the Verified or Unverified form by that module. This +# means the SOCKSHTTPSConnection will automatically be the correct type. +class SOCKSHTTPSConnection(SOCKSConnection, HTTPSConnection): + pass + + +class SOCKSHTTPConnectionPool(HTTPConnectionPool): + ConnectionCls = SOCKSConnection + + +class SOCKSHTTPSConnectionPool(HTTPSConnectionPool): + ConnectionCls = SOCKSHTTPSConnection + + +class SOCKSProxyManager(PoolManager): + """ + A version of the urllib3 ProxyManager that routes connections via the + defined SOCKS proxy. + """ + + pool_classes_by_scheme = { + "http": SOCKSHTTPConnectionPool, + "https": SOCKSHTTPSConnectionPool, + } + + def __init__( + self, + proxy_url: str, + username: str | None = None, + password: str | None = None, + num_pools: int = 10, + headers: typing.Mapping[str, str] | None = None, + **connection_pool_kw: typing.Any, + ): + parsed = parse_url(proxy_url) + + if username is None and password is None and parsed.auth is not None: + split = parsed.auth.split(":") + if len(split) == 2: + username, password = split + if parsed.scheme == "socks5": + socks_version = socks.PROXY_TYPE_SOCKS5 + rdns = False + elif parsed.scheme == "socks5h": + socks_version = socks.PROXY_TYPE_SOCKS5 + rdns = True + elif parsed.scheme == "socks4": + socks_version = socks.PROXY_TYPE_SOCKS4 + rdns = False + elif parsed.scheme == "socks4a": + socks_version = socks.PROXY_TYPE_SOCKS4 + rdns = True + else: + raise ValueError(f"Unable to determine SOCKS version from {proxy_url}") + + self.proxy_url = proxy_url + + socks_options = { + "socks_version": socks_version, + "proxy_host": parsed.host, + "proxy_port": parsed.port, + "username": username, + "password": password, + "rdns": rdns, + } + connection_pool_kw["_socks_options"] = socks_options + + super().__init__(num_pools, headers, **connection_pool_kw) + + self.pool_classes_by_scheme = SOCKSProxyManager.pool_classes_by_scheme diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/exceptions.py b/apigw-private-cdn-acm/acm-certificate/urllib3/exceptions.py new file mode 100644 index 000000000..039457828 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/exceptions.py @@ -0,0 +1,327 @@ +from __future__ import annotations + +import socket +import typing +import warnings +from email.errors import MessageDefect +from http.client import IncompleteRead as httplib_IncompleteRead + +if typing.TYPE_CHECKING: + from .connection import HTTPConnection + from .connectionpool import ConnectionPool + from .response import HTTPResponse + from .util.retry import Retry + +# Base Exceptions + + +class HTTPError(Exception): + """Base exception used by this module.""" + + +class HTTPWarning(Warning): + """Base warning used by this module.""" + + +_TYPE_REDUCE_RESULT = tuple[typing.Callable[..., object], tuple[object, ...]] + + +class PoolError(HTTPError): + """Base exception for errors caused within a pool.""" + + def __init__(self, pool: ConnectionPool, message: str) -> None: + self.pool = pool + super().__init__(f"{pool}: {message}") + + def __reduce__(self) -> _TYPE_REDUCE_RESULT: + # For pickling purposes. + return self.__class__, (None, None) + + +class RequestError(PoolError): + """Base exception for PoolErrors that have associated URLs.""" + + def __init__(self, pool: ConnectionPool, url: str, message: str) -> None: + self.url = url + super().__init__(pool, message) + + def __reduce__(self) -> _TYPE_REDUCE_RESULT: + # For pickling purposes. + return self.__class__, (None, self.url, None) + + +class SSLError(HTTPError): + """Raised when SSL certificate fails in an HTTPS connection.""" + + +class ProxyError(HTTPError): + """Raised when the connection to a proxy fails.""" + + # The original error is also available as __cause__. + original_error: Exception + + def __init__(self, message: str, error: Exception) -> None: + super().__init__(message, error) + self.original_error = error + + +class DecodeError(HTTPError): + """Raised when automatic decoding based on Content-Type fails.""" + + +class ProtocolError(HTTPError): + """Raised when something unexpected happens mid-request/response.""" + + +#: Renamed to ProtocolError but aliased for backwards compatibility. +ConnectionError = ProtocolError + + +# Leaf Exceptions + + +class MaxRetryError(RequestError): + """Raised when the maximum number of retries is exceeded. + + :param pool: The connection pool + :type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool` + :param str url: The requested Url + :param reason: The underlying error + :type reason: :class:`Exception` + + """ + + def __init__( + self, pool: ConnectionPool, url: str, reason: Exception | None = None + ) -> None: + self.reason = reason + + message = f"Max retries exceeded with url: {url} (Caused by {reason!r})" + + super().__init__(pool, url, message) + + +class HostChangedError(RequestError): + """Raised when an existing pool gets a request for a foreign host.""" + + def __init__( + self, pool: ConnectionPool, url: str, retries: Retry | int = 3 + ) -> None: + message = f"Tried to open a foreign host with url: {url}" + super().__init__(pool, url, message) + self.retries = retries + + +class TimeoutStateError(HTTPError): + """Raised when passing an invalid state to a timeout""" + + +class TimeoutError(HTTPError): + """Raised when a socket timeout error occurs. + + Catching this error will catch both :exc:`ReadTimeoutErrors + ` and :exc:`ConnectTimeoutErrors `. + """ + + +class ReadTimeoutError(TimeoutError, RequestError): + """Raised when a socket timeout occurs while receiving data from a server""" + + +# This timeout error does not have a URL attached and needs to inherit from the +# base HTTPError +class ConnectTimeoutError(TimeoutError): + """Raised when a socket timeout occurs while connecting to a server""" + + +class NewConnectionError(ConnectTimeoutError, HTTPError): + """Raised when we fail to establish a new connection. Usually ECONNREFUSED.""" + + def __init__(self, conn: HTTPConnection, message: str) -> None: + self.conn = conn + super().__init__(f"{conn}: {message}") + + def __reduce__(self) -> _TYPE_REDUCE_RESULT: + # For pickling purposes. + return self.__class__, (None, None) + + @property + def pool(self) -> HTTPConnection: + warnings.warn( + "The 'pool' property is deprecated and will be removed " + "in urllib3 v2.1.0. Use 'conn' instead.", + DeprecationWarning, + stacklevel=2, + ) + + return self.conn + + +class NameResolutionError(NewConnectionError): + """Raised when host name resolution fails.""" + + def __init__(self, host: str, conn: HTTPConnection, reason: socket.gaierror): + message = f"Failed to resolve '{host}' ({reason})" + super().__init__(conn, message) + + def __reduce__(self) -> _TYPE_REDUCE_RESULT: + # For pickling purposes. + return self.__class__, (None, None, None) + + +class EmptyPoolError(PoolError): + """Raised when a pool runs out of connections and no more are allowed.""" + + +class FullPoolError(PoolError): + """Raised when we try to add a connection to a full pool in blocking mode.""" + + +class ClosedPoolError(PoolError): + """Raised when a request enters a pool after the pool has been closed.""" + + +class LocationValueError(ValueError, HTTPError): + """Raised when there is something wrong with a given URL input.""" + + +class LocationParseError(LocationValueError): + """Raised when get_host or similar fails to parse the URL input.""" + + def __init__(self, location: str) -> None: + message = f"Failed to parse: {location}" + super().__init__(message) + + self.location = location + + +class URLSchemeUnknown(LocationValueError): + """Raised when a URL input has an unsupported scheme.""" + + def __init__(self, scheme: str): + message = f"Not supported URL scheme {scheme}" + super().__init__(message) + + self.scheme = scheme + + +class ResponseError(HTTPError): + """Used as a container for an error reason supplied in a MaxRetryError.""" + + GENERIC_ERROR = "too many error responses" + SPECIFIC_ERROR = "too many {status_code} error responses" + + +class SecurityWarning(HTTPWarning): + """Warned when performing security reducing actions""" + + +class InsecureRequestWarning(SecurityWarning): + """Warned when making an unverified HTTPS request.""" + + +class NotOpenSSLWarning(SecurityWarning): + """Warned when using unsupported SSL library""" + + +class SystemTimeWarning(SecurityWarning): + """Warned when system time is suspected to be wrong""" + + +class InsecurePlatformWarning(SecurityWarning): + """Warned when certain TLS/SSL configuration is not available on a platform.""" + + +class DependencyWarning(HTTPWarning): + """ + Warned when an attempt is made to import a module with missing optional + dependencies. + """ + + +class ResponseNotChunked(ProtocolError, ValueError): + """Response needs to be chunked in order to read it as chunks.""" + + +class BodyNotHttplibCompatible(HTTPError): + """ + Body should be :class:`http.client.HTTPResponse` like + (have an fp attribute which returns raw chunks) for read_chunked(). + """ + + +class IncompleteRead(HTTPError, httplib_IncompleteRead): + """ + Response length doesn't match expected Content-Length + + Subclass of :class:`http.client.IncompleteRead` to allow int value + for ``partial`` to avoid creating large objects on streamed reads. + """ + + partial: int # type: ignore[assignment] + expected: int + + def __init__(self, partial: int, expected: int) -> None: + self.partial = partial + self.expected = expected + + def __repr__(self) -> str: + return "IncompleteRead(%i bytes read, %i more expected)" % ( + self.partial, + self.expected, + ) + + +class InvalidChunkLength(HTTPError, httplib_IncompleteRead): + """Invalid chunk length in a chunked response.""" + + def __init__(self, response: HTTPResponse, length: bytes) -> None: + self.partial: int = response.tell() # type: ignore[assignment] + self.expected: int | None = response.length_remaining + self.response = response + self.length = length + + def __repr__(self) -> str: + return "InvalidChunkLength(got length %r, %i bytes read)" % ( + self.length, + self.partial, + ) + + +class InvalidHeader(HTTPError): + """The header provided was somehow invalid.""" + + +class ProxySchemeUnknown(AssertionError, URLSchemeUnknown): + """ProxyManager does not support the supplied scheme""" + + # TODO(t-8ch): Stop inheriting from AssertionError in v2.0. + + def __init__(self, scheme: str | None) -> None: + # 'localhost' is here because our URL parser parses + # localhost:8080 -> scheme=localhost, remove if we fix this. + if scheme == "localhost": + scheme = None + if scheme is None: + message = "Proxy URL had no scheme, should start with http:// or https://" + else: + message = f"Proxy URL had unsupported scheme {scheme}, should use http:// or https://" + super().__init__(message) + + +class ProxySchemeUnsupported(ValueError): + """Fetching HTTPS resources through HTTPS proxies is unsupported""" + + +class HeaderParsingError(HTTPError): + """Raised by assert_header_parsing, but we convert it to a log.warning statement.""" + + def __init__( + self, defects: list[MessageDefect], unparsed_data: bytes | str | None + ) -> None: + message = f"{defects or 'Unknown'}, unparsed data: {unparsed_data!r}" + super().__init__(message) + + +class UnrewindableBodyError(HTTPError): + """urllib3 encountered an error when trying to rewind a body""" diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/fields.py b/apigw-private-cdn-acm/acm-certificate/urllib3/fields.py new file mode 100644 index 000000000..97c4730cf --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/fields.py @@ -0,0 +1,341 @@ +from __future__ import annotations + +import email.utils +import mimetypes +import typing + +_TYPE_FIELD_VALUE = typing.Union[str, bytes] +_TYPE_FIELD_VALUE_TUPLE = typing.Union[ + _TYPE_FIELD_VALUE, + tuple[str, _TYPE_FIELD_VALUE], + tuple[str, _TYPE_FIELD_VALUE, str], +] + + +def guess_content_type( + filename: str | None, default: str = "application/octet-stream" +) -> str: + """ + Guess the "Content-Type" of a file. + + :param filename: + The filename to guess the "Content-Type" of using :mod:`mimetypes`. + :param default: + If no "Content-Type" can be guessed, default to `default`. + """ + if filename: + return mimetypes.guess_type(filename)[0] or default + return default + + +def format_header_param_rfc2231(name: str, value: _TYPE_FIELD_VALUE) -> str: + """ + Helper function to format and quote a single header parameter using the + strategy defined in RFC 2231. + + Particularly useful for header parameters which might contain + non-ASCII values, like file names. This follows + `RFC 2388 Section 4.4 `_. + + :param name: + The name of the parameter, a string expected to be ASCII only. + :param value: + The value of the parameter, provided as ``bytes`` or `str``. + :returns: + An RFC-2231-formatted unicode string. + + .. deprecated:: 2.0.0 + Will be removed in urllib3 v2.1.0. This is not valid for + ``multipart/form-data`` header parameters. + """ + import warnings + + warnings.warn( + "'format_header_param_rfc2231' is deprecated and will be " + "removed in urllib3 v2.1.0. This is not valid for " + "multipart/form-data header parameters.", + DeprecationWarning, + stacklevel=2, + ) + + if isinstance(value, bytes): + value = value.decode("utf-8") + + if not any(ch in value for ch in '"\\\r\n'): + result = f'{name}="{value}"' + try: + result.encode("ascii") + except (UnicodeEncodeError, UnicodeDecodeError): + pass + else: + return result + + value = email.utils.encode_rfc2231(value, "utf-8") + value = f"{name}*={value}" + + return value + + +def format_multipart_header_param(name: str, value: _TYPE_FIELD_VALUE) -> str: + """ + Format and quote a single multipart header parameter. + + This follows the `WHATWG HTML Standard`_ as of 2021/06/10, matching + the behavior of current browser and curl versions. Values are + assumed to be UTF-8. The ``\\n``, ``\\r``, and ``"`` characters are + percent encoded. + + .. _WHATWG HTML Standard: + https://html.spec.whatwg.org/multipage/ + form-control-infrastructure.html#multipart-form-data + + :param name: + The name of the parameter, an ASCII-only ``str``. + :param value: + The value of the parameter, a ``str`` or UTF-8 encoded + ``bytes``. + :returns: + A string ``name="value"`` with the escaped value. + + .. versionchanged:: 2.0.0 + Matches the WHATWG HTML Standard as of 2021/06/10. Control + characters are no longer percent encoded. + + .. versionchanged:: 2.0.0 + Renamed from ``format_header_param_html5`` and + ``format_header_param``. The old names will be removed in + urllib3 v2.1.0. + """ + if isinstance(value, bytes): + value = value.decode("utf-8") + + # percent encode \n \r " + value = value.translate({10: "%0A", 13: "%0D", 34: "%22"}) + return f'{name}="{value}"' + + +def format_header_param_html5(name: str, value: _TYPE_FIELD_VALUE) -> str: + """ + .. deprecated:: 2.0.0 + Renamed to :func:`format_multipart_header_param`. Will be + removed in urllib3 v2.1.0. + """ + import warnings + + warnings.warn( + "'format_header_param_html5' has been renamed to " + "'format_multipart_header_param'. The old name will be " + "removed in urllib3 v2.1.0.", + DeprecationWarning, + stacklevel=2, + ) + return format_multipart_header_param(name, value) + + +def format_header_param(name: str, value: _TYPE_FIELD_VALUE) -> str: + """ + .. deprecated:: 2.0.0 + Renamed to :func:`format_multipart_header_param`. Will be + removed in urllib3 v2.1.0. + """ + import warnings + + warnings.warn( + "'format_header_param' has been renamed to " + "'format_multipart_header_param'. The old name will be " + "removed in urllib3 v2.1.0.", + DeprecationWarning, + stacklevel=2, + ) + return format_multipart_header_param(name, value) + + +class RequestField: + """ + A data container for request body parameters. + + :param name: + The name of this request field. Must be unicode. + :param data: + The data/value body. + :param filename: + An optional filename of the request field. Must be unicode. + :param headers: + An optional dict-like object of headers to initially use for the field. + + .. versionchanged:: 2.0.0 + The ``header_formatter`` parameter is deprecated and will + be removed in urllib3 v2.1.0. + """ + + def __init__( + self, + name: str, + data: _TYPE_FIELD_VALUE, + filename: str | None = None, + headers: typing.Mapping[str, str] | None = None, + header_formatter: typing.Callable[[str, _TYPE_FIELD_VALUE], str] | None = None, + ): + self._name = name + self._filename = filename + self.data = data + self.headers: dict[str, str | None] = {} + if headers: + self.headers = dict(headers) + + if header_formatter is not None: + import warnings + + warnings.warn( + "The 'header_formatter' parameter is deprecated and " + "will be removed in urllib3 v2.1.0.", + DeprecationWarning, + stacklevel=2, + ) + self.header_formatter = header_formatter + else: + self.header_formatter = format_multipart_header_param + + @classmethod + def from_tuples( + cls, + fieldname: str, + value: _TYPE_FIELD_VALUE_TUPLE, + header_formatter: typing.Callable[[str, _TYPE_FIELD_VALUE], str] | None = None, + ) -> RequestField: + """ + A :class:`~urllib3.fields.RequestField` factory from old-style tuple parameters. + + Supports constructing :class:`~urllib3.fields.RequestField` from + parameter of key/value strings AND key/filetuple. A filetuple is a + (filename, data, MIME type) tuple where the MIME type is optional. + For example:: + + 'foo': 'bar', + 'fakefile': ('foofile.txt', 'contents of foofile'), + 'realfile': ('barfile.txt', open('realfile').read()), + 'typedfile': ('bazfile.bin', open('bazfile').read(), 'image/jpeg'), + 'nonamefile': 'contents of nonamefile field', + + Field names and filenames must be unicode. + """ + filename: str | None + content_type: str | None + data: _TYPE_FIELD_VALUE + + if isinstance(value, tuple): + if len(value) == 3: + filename, data, content_type = value + else: + filename, data = value + content_type = guess_content_type(filename) + else: + filename = None + content_type = None + data = value + + request_param = cls( + fieldname, data, filename=filename, header_formatter=header_formatter + ) + request_param.make_multipart(content_type=content_type) + + return request_param + + def _render_part(self, name: str, value: _TYPE_FIELD_VALUE) -> str: + """ + Override this method to change how each multipart header + parameter is formatted. By default, this calls + :func:`format_multipart_header_param`. + + :param name: + The name of the parameter, an ASCII-only ``str``. + :param value: + The value of the parameter, a ``str`` or UTF-8 encoded + ``bytes``. + + :meta public: + """ + return self.header_formatter(name, value) + + def _render_parts( + self, + header_parts: ( + dict[str, _TYPE_FIELD_VALUE | None] + | typing.Sequence[tuple[str, _TYPE_FIELD_VALUE | None]] + ), + ) -> str: + """ + Helper function to format and quote a single header. + + Useful for single headers that are composed of multiple items. E.g., + 'Content-Disposition' fields. + + :param header_parts: + A sequence of (k, v) tuples or a :class:`dict` of (k, v) to format + as `k1="v1"; k2="v2"; ...`. + """ + iterable: typing.Iterable[tuple[str, _TYPE_FIELD_VALUE | None]] + + parts = [] + if isinstance(header_parts, dict): + iterable = header_parts.items() + else: + iterable = header_parts + + for name, value in iterable: + if value is not None: + parts.append(self._render_part(name, value)) + + return "; ".join(parts) + + def render_headers(self) -> str: + """ + Renders the headers for this request field. + """ + lines = [] + + sort_keys = ["Content-Disposition", "Content-Type", "Content-Location"] + for sort_key in sort_keys: + if self.headers.get(sort_key, False): + lines.append(f"{sort_key}: {self.headers[sort_key]}") + + for header_name, header_value in self.headers.items(): + if header_name not in sort_keys: + if header_value: + lines.append(f"{header_name}: {header_value}") + + lines.append("\r\n") + return "\r\n".join(lines) + + def make_multipart( + self, + content_disposition: str | None = None, + content_type: str | None = None, + content_location: str | None = None, + ) -> None: + """ + Makes this request field into a multipart request field. + + This method overrides "Content-Disposition", "Content-Type" and + "Content-Location" headers to the request parameter. + + :param content_disposition: + The 'Content-Disposition' of the request body. Defaults to 'form-data' + :param content_type: + The 'Content-Type' of the request body. + :param content_location: + The 'Content-Location' of the request body. + + """ + content_disposition = (content_disposition or "form-data") + "; ".join( + [ + "", + self._render_parts( + (("name", self._name), ("filename", self._filename)) + ), + ] + ) + + self.headers["Content-Disposition"] = content_disposition + self.headers["Content-Type"] = content_type + self.headers["Content-Location"] = content_location diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/filepost.py b/apigw-private-cdn-acm/acm-certificate/urllib3/filepost.py new file mode 100644 index 000000000..14f70b05b --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/filepost.py @@ -0,0 +1,89 @@ +from __future__ import annotations + +import binascii +import codecs +import os +import typing +from io import BytesIO + +from .fields import _TYPE_FIELD_VALUE_TUPLE, RequestField + +writer = codecs.lookup("utf-8")[3] + +_TYPE_FIELDS_SEQUENCE = typing.Sequence[ + typing.Union[tuple[str, _TYPE_FIELD_VALUE_TUPLE], RequestField] +] +_TYPE_FIELDS = typing.Union[ + _TYPE_FIELDS_SEQUENCE, + typing.Mapping[str, _TYPE_FIELD_VALUE_TUPLE], +] + + +def choose_boundary() -> str: + """ + Our embarrassingly-simple replacement for mimetools.choose_boundary. + """ + return binascii.hexlify(os.urandom(16)).decode() + + +def iter_field_objects(fields: _TYPE_FIELDS) -> typing.Iterable[RequestField]: + """ + Iterate over fields. + + Supports list of (k, v) tuples and dicts, and lists of + :class:`~urllib3.fields.RequestField`. + + """ + iterable: typing.Iterable[RequestField | tuple[str, _TYPE_FIELD_VALUE_TUPLE]] + + if isinstance(fields, typing.Mapping): + iterable = fields.items() + else: + iterable = fields + + for field in iterable: + if isinstance(field, RequestField): + yield field + else: + yield RequestField.from_tuples(*field) + + +def encode_multipart_formdata( + fields: _TYPE_FIELDS, boundary: str | None = None +) -> tuple[bytes, str]: + """ + Encode a dictionary of ``fields`` using the multipart/form-data MIME format. + + :param fields: + Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`). + Values are processed by :func:`urllib3.fields.RequestField.from_tuples`. + + :param boundary: + If not specified, then a random boundary will be generated using + :func:`urllib3.filepost.choose_boundary`. + """ + body = BytesIO() + if boundary is None: + boundary = choose_boundary() + + for field in iter_field_objects(fields): + body.write(f"--{boundary}\r\n".encode("latin-1")) + + writer(body).write(field.render_headers()) + data = field.data + + if isinstance(data, int): + data = str(data) # Backwards compatibility + + if isinstance(data, str): + writer(body).write(data) + else: + body.write(data) + + body.write(b"\r\n") + + body.write(f"--{boundary}--\r\n".encode("latin-1")) + + content_type = f"multipart/form-data; boundary={boundary}" + + return body.getvalue(), content_type diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/http2/__init__.py b/apigw-private-cdn-acm/acm-certificate/urllib3/http2/__init__.py new file mode 100644 index 000000000..133e1d8f2 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/http2/__init__.py @@ -0,0 +1,53 @@ +from __future__ import annotations + +from importlib.metadata import version + +__all__ = [ + "inject_into_urllib3", + "extract_from_urllib3", +] + +import typing + +orig_HTTPSConnection: typing.Any = None + + +def inject_into_urllib3() -> None: + # First check if h2 version is valid + h2_version = version("h2") + if not h2_version.startswith("4."): + raise ImportError( + "urllib3 v2 supports h2 version 4.x.x, currently " + f"the 'h2' module is compiled with {h2_version!r}. " + "See: https://github.com/urllib3/urllib3/issues/3290" + ) + + # Import here to avoid circular dependencies. + from .. import connection as urllib3_connection + from .. import util as urllib3_util + from ..connectionpool import HTTPSConnectionPool + from ..util import ssl_ as urllib3_util_ssl + from .connection import HTTP2Connection + + global orig_HTTPSConnection + orig_HTTPSConnection = urllib3_connection.HTTPSConnection + + HTTPSConnectionPool.ConnectionCls = HTTP2Connection + urllib3_connection.HTTPSConnection = HTTP2Connection # type: ignore[misc] + + # TODO: Offer 'http/1.1' as well, but for testing purposes this is handy. + urllib3_util.ALPN_PROTOCOLS = ["h2"] + urllib3_util_ssl.ALPN_PROTOCOLS = ["h2"] + + +def extract_from_urllib3() -> None: + from .. import connection as urllib3_connection + from .. import util as urllib3_util + from ..connectionpool import HTTPSConnectionPool + from ..util import ssl_ as urllib3_util_ssl + + HTTPSConnectionPool.ConnectionCls = orig_HTTPSConnection + urllib3_connection.HTTPSConnection = orig_HTTPSConnection # type: ignore[misc] + + urllib3_util.ALPN_PROTOCOLS = ["http/1.1"] + urllib3_util_ssl.ALPN_PROTOCOLS = ["http/1.1"] diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/http2/__pycache__/__init__.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/http2/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4586089507c33e952ae1585dc5e640b67ce3c3e2 GIT binary patch literal 1774 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 literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/http2/__pycache__/probe.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/http2/__pycache__/probe.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..81f952115907ded479b926d706d729addafc962a GIT binary patch literal 3809 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 literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/http2/connection.py b/apigw-private-cdn-acm/acm-certificate/urllib3/http2/connection.py new file mode 100644 index 000000000..f48614528 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/http2/connection.py @@ -0,0 +1,356 @@ +from __future__ import annotations + +import logging +import re +import threading +import types +import typing + +import h2.config # type: ignore[import-untyped] +import h2.connection # type: ignore[import-untyped] +import h2.events # type: ignore[import-untyped] + +from .._base_connection import _TYPE_BODY +from .._collections import HTTPHeaderDict +from ..connection import HTTPSConnection, _get_default_user_agent +from ..exceptions import ConnectionError +from ..response import BaseHTTPResponse + +orig_HTTPSConnection = HTTPSConnection + +T = typing.TypeVar("T") + +log = logging.getLogger(__name__) + +RE_IS_LEGAL_HEADER_NAME = re.compile(rb"^[!#$%&'*+\-.^_`|~0-9a-z]+$") +RE_IS_ILLEGAL_HEADER_VALUE = re.compile(rb"[\0\x00\x0a\x0d\r\n]|^[ \r\n\t]|[ \r\n\t]$") + + +def _is_legal_header_name(name: bytes) -> bool: + """ + "An implementation that validates fields according to the definitions in Sections + 5.1 and 5.5 of [HTTP] only needs an additional check that field names do not + include uppercase characters." (https://httpwg.org/specs/rfc9113.html#n-field-validity) + + `http.client._is_legal_header_name` does not validate the field name according to the + HTTP 1.1 spec, so we do that here, in addition to checking for uppercase characters. + + This does not allow for the `:` character in the header name, so should not + be used to validate pseudo-headers. + """ + return bool(RE_IS_LEGAL_HEADER_NAME.match(name)) + + +def _is_illegal_header_value(value: bytes) -> bool: + """ + "A field value MUST NOT contain the zero value (ASCII NUL, 0x00), line feed + (ASCII LF, 0x0a), or carriage return (ASCII CR, 0x0d) at any position. A field + value MUST NOT start or end with an ASCII whitespace character (ASCII SP or HTAB, + 0x20 or 0x09)." (https://httpwg.org/specs/rfc9113.html#n-field-validity) + """ + return bool(RE_IS_ILLEGAL_HEADER_VALUE.search(value)) + + +class _LockedObject(typing.Generic[T]): + """ + A wrapper class that hides a specific object behind a lock. + The goal here is to provide a simple way to protect access to an object + that cannot safely be simultaneously accessed from multiple threads. The + intended use of this class is simple: take hold of it with a context + manager, which returns the protected object. + """ + + __slots__ = ( + "lock", + "_obj", + ) + + def __init__(self, obj: T): + self.lock = threading.RLock() + self._obj = obj + + def __enter__(self) -> T: + self.lock.acquire() + return self._obj + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: types.TracebackType | None, + ) -> None: + self.lock.release() + + +class HTTP2Connection(HTTPSConnection): + def __init__( + self, host: str, port: int | None = None, **kwargs: typing.Any + ) -> None: + self._h2_conn = self._new_h2_conn() + self._h2_stream: int | None = None + self._headers: list[tuple[bytes, bytes]] = [] + + if "proxy" in kwargs or "proxy_config" in kwargs: # Defensive: + raise NotImplementedError("Proxies aren't supported with HTTP/2") + + super().__init__(host, port, **kwargs) + + if self._tunnel_host is not None: + raise NotImplementedError("Tunneling isn't supported with HTTP/2") + + def _new_h2_conn(self) -> _LockedObject[h2.connection.H2Connection]: + config = h2.config.H2Configuration(client_side=True) + return _LockedObject(h2.connection.H2Connection(config=config)) + + def connect(self) -> None: + super().connect() + with self._h2_conn as conn: + conn.initiate_connection() + if data_to_send := conn.data_to_send(): + self.sock.sendall(data_to_send) + + def putrequest( # type: ignore[override] + self, + method: str, + url: str, + **kwargs: typing.Any, + ) -> None: + """putrequest + This deviates from the HTTPConnection method signature since we never need to override + sending accept-encoding headers or the host header. + """ + if "skip_host" in kwargs: + raise NotImplementedError("`skip_host` isn't supported") + if "skip_accept_encoding" in kwargs: + raise NotImplementedError("`skip_accept_encoding` isn't supported") + + self._request_url = url or "/" + self._validate_path(url) # type: ignore[attr-defined] + + if ":" in self.host: + authority = f"[{self.host}]:{self.port or 443}" + else: + authority = f"{self.host}:{self.port or 443}" + + self._headers.append((b":scheme", b"https")) + self._headers.append((b":method", method.encode())) + self._headers.append((b":authority", authority.encode())) + self._headers.append((b":path", url.encode())) + + with self._h2_conn as conn: + self._h2_stream = conn.get_next_available_stream_id() + + def putheader(self, header: str | bytes, *values: str | bytes) -> None: + # TODO SKIPPABLE_HEADERS from urllib3 are ignored. + header = header.encode() if isinstance(header, str) else header + header = header.lower() # A lot of upstream code uses capitalized headers. + if not _is_legal_header_name(header): + raise ValueError(f"Illegal header name {str(header)}") + + for value in values: + value = value.encode() if isinstance(value, str) else value + if _is_illegal_header_value(value): + raise ValueError(f"Illegal header value {str(value)}") + self._headers.append((header, value)) + + def endheaders(self, message_body: typing.Any = None) -> None: # type: ignore[override] + if self._h2_stream is None: + raise ConnectionError("Must call `putrequest` first.") + + with self._h2_conn as conn: + conn.send_headers( + stream_id=self._h2_stream, + headers=self._headers, + end_stream=(message_body is None), + ) + if data_to_send := conn.data_to_send(): + self.sock.sendall(data_to_send) + self._headers = [] # Reset headers for the next request. + + def send(self, data: typing.Any) -> None: + """Send data to the server. + `data` can be: `str`, `bytes`, an iterable, or file-like objects + that support a .read() method. + """ + if self._h2_stream is None: + raise ConnectionError("Must call `putrequest` first.") + + with self._h2_conn as conn: + if data_to_send := conn.data_to_send(): + self.sock.sendall(data_to_send) + + if hasattr(data, "read"): # file-like objects + while True: + chunk = data.read(self.blocksize) + if not chunk: + break + if isinstance(chunk, str): + chunk = chunk.encode() # pragma: no cover + conn.send_data(self._h2_stream, chunk, end_stream=False) + if data_to_send := conn.data_to_send(): + self.sock.sendall(data_to_send) + conn.end_stream(self._h2_stream) + return + + if isinstance(data, str): # str -> bytes + data = data.encode() + + try: + if isinstance(data, bytes): + conn.send_data(self._h2_stream, data, end_stream=True) + if data_to_send := conn.data_to_send(): + self.sock.sendall(data_to_send) + else: + for chunk in data: + conn.send_data(self._h2_stream, chunk, end_stream=False) + if data_to_send := conn.data_to_send(): + self.sock.sendall(data_to_send) + conn.end_stream(self._h2_stream) + except TypeError: + raise TypeError( + "`data` should be str, bytes, iterable, or file. got %r" + % type(data) + ) + + def set_tunnel( + self, + host: str, + port: int | None = None, + headers: typing.Mapping[str, str] | None = None, + scheme: str = "http", + ) -> None: + raise NotImplementedError( + "HTTP/2 does not support setting up a tunnel through a proxy" + ) + + def getresponse( # type: ignore[override] + self, + ) -> HTTP2Response: + status = None + data = bytearray() + with self._h2_conn as conn: + end_stream = False + while not end_stream: + # TODO: Arbitrary read value. + if received_data := self.sock.recv(65535): + events = conn.receive_data(received_data) + for event in events: + if isinstance(event, h2.events.ResponseReceived): + headers = HTTPHeaderDict() + for header, value in event.headers: + if header == b":status": + status = int(value.decode()) + else: + headers.add( + header.decode("ascii"), value.decode("ascii") + ) + + elif isinstance(event, h2.events.DataReceived): + data += event.data + conn.acknowledge_received_data( + event.flow_controlled_length, event.stream_id + ) + + elif isinstance(event, h2.events.StreamEnded): + end_stream = True + + if data_to_send := conn.data_to_send(): + self.sock.sendall(data_to_send) + + assert status is not None + return HTTP2Response( + status=status, + headers=headers, + request_url=self._request_url, + data=bytes(data), + ) + + def request( # type: ignore[override] + self, + method: str, + url: str, + body: _TYPE_BODY | None = None, + headers: typing.Mapping[str, str] | None = None, + *, + preload_content: bool = True, + decode_content: bool = True, + enforce_content_length: bool = True, + **kwargs: typing.Any, + ) -> None: + """Send an HTTP/2 request""" + if "chunked" in kwargs: + # TODO this is often present from upstream. + # raise NotImplementedError("`chunked` isn't supported with HTTP/2") + pass + + if self.sock is not None: + self.sock.settimeout(self.timeout) + + self.putrequest(method, url) + + headers = headers or {} + for k, v in headers.items(): + if k.lower() == "transfer-encoding" and v == "chunked": + continue + else: + self.putheader(k, v) + + if b"user-agent" not in dict(self._headers): + self.putheader(b"user-agent", _get_default_user_agent()) + + if body: + self.endheaders(message_body=body) + self.send(body) + else: + self.endheaders() + + def close(self) -> None: + with self._h2_conn as conn: + try: + conn.close_connection() + if data := conn.data_to_send(): + self.sock.sendall(data) + except Exception: + pass + + # Reset all our HTTP/2 connection state. + self._h2_conn = self._new_h2_conn() + self._h2_stream = None + self._headers = [] + + super().close() + + +class HTTP2Response(BaseHTTPResponse): + # TODO: This is a woefully incomplete response object, but works for non-streaming. + def __init__( + self, + status: int, + headers: HTTPHeaderDict, + request_url: str, + data: bytes, + decode_content: bool = False, # TODO: support decoding + ) -> None: + super().__init__( + status=status, + headers=headers, + # Following CPython, we map HTTP versions to major * 10 + minor integers + version=20, + version_string="HTTP/2", + # No reason phrase in HTTP/2 + reason=None, + decode_content=decode_content, + request_url=request_url, + ) + self._data = data + self.length_remaining = 0 + + @property + def data(self) -> bytes: + return self._data + + def get_redirect_location(self) -> None: + return None + + def close(self) -> None: + pass diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/http2/probe.py b/apigw-private-cdn-acm/acm-certificate/urllib3/http2/probe.py new file mode 100644 index 000000000..9ea900764 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/http2/probe.py @@ -0,0 +1,87 @@ +from __future__ import annotations + +import threading + + +class _HTTP2ProbeCache: + __slots__ = ( + "_lock", + "_cache_locks", + "_cache_values", + ) + + def __init__(self) -> None: + self._lock = threading.Lock() + self._cache_locks: dict[tuple[str, int], threading.RLock] = {} + self._cache_values: dict[tuple[str, int], bool | None] = {} + + def acquire_and_get(self, host: str, port: int) -> bool | None: + # By the end of this block we know that + # _cache_[values,locks] is available. + value = None + with self._lock: + key = (host, port) + try: + value = self._cache_values[key] + # If it's a known value we return right away. + if value is not None: + return value + except KeyError: + self._cache_locks[key] = threading.RLock() + self._cache_values[key] = None + + # If the value is unknown, we acquire the lock to signal + # to the requesting thread that the probe is in progress + # or that the current thread needs to return their findings. + key_lock = self._cache_locks[key] + key_lock.acquire() + try: + # If the by the time we get the lock the value has been + # updated we want to return the updated value. + value = self._cache_values[key] + + # In case an exception like KeyboardInterrupt is raised here. + except BaseException as e: # Defensive: + assert not isinstance(e, KeyError) # KeyError shouldn't be possible. + key_lock.release() + raise + + return value + + def set_and_release( + self, host: str, port: int, supports_http2: bool | None + ) -> None: + key = (host, port) + key_lock = self._cache_locks[key] + with key_lock: # Uses an RLock, so can be locked again from same thread. + if supports_http2 is None and self._cache_values[key] is not None: + raise ValueError( + "Cannot reset HTTP/2 support for origin after value has been set." + ) # Defensive: not expected in normal usage + + self._cache_values[key] = supports_http2 + key_lock.release() + + def _values(self) -> dict[tuple[str, int], bool | None]: + """This function is for testing purposes only. Gets the current state of the probe cache""" + with self._lock: + return {k: v for k, v in self._cache_values.items()} + + def _reset(self) -> None: + """This function is for testing purposes only. Reset the cache values""" + with self._lock: + self._cache_locks = {} + self._cache_values = {} + + +_HTTP2_PROBE_CACHE = _HTTP2ProbeCache() + +set_and_release = _HTTP2_PROBE_CACHE.set_and_release +acquire_and_get = _HTTP2_PROBE_CACHE.acquire_and_get +_values = _HTTP2_PROBE_CACHE._values +_reset = _HTTP2_PROBE_CACHE._reset + +__all__ = [ + "set_and_release", + "acquire_and_get", +] diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/poolmanager.py b/apigw-private-cdn-acm/acm-certificate/urllib3/poolmanager.py new file mode 100644 index 000000000..085d1dbaf --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/poolmanager.py @@ -0,0 +1,637 @@ +from __future__ import annotations + +import functools +import logging +import typing +import warnings +from types import TracebackType +from urllib.parse import urljoin + +from ._collections import HTTPHeaderDict, RecentlyUsedContainer +from ._request_methods import RequestMethods +from .connection import ProxyConfig +from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, port_by_scheme +from .exceptions import ( + LocationValueError, + MaxRetryError, + ProxySchemeUnknown, + URLSchemeUnknown, +) +from .response import BaseHTTPResponse +from .util.connection import _TYPE_SOCKET_OPTIONS +from .util.proxy import connection_requires_http_tunnel +from .util.retry import Retry +from .util.timeout import Timeout +from .util.url import Url, parse_url + +if typing.TYPE_CHECKING: + import ssl + + from typing_extensions import Self + +__all__ = ["PoolManager", "ProxyManager", "proxy_from_url"] + + +log = logging.getLogger(__name__) + +SSL_KEYWORDS = ( + "key_file", + "cert_file", + "cert_reqs", + "ca_certs", + "ca_cert_data", + "ssl_version", + "ssl_minimum_version", + "ssl_maximum_version", + "ca_cert_dir", + "ssl_context", + "key_password", + "server_hostname", +) +# Default value for `blocksize` - a new parameter introduced to +# http.client.HTTPConnection & http.client.HTTPSConnection in Python 3.7 +_DEFAULT_BLOCKSIZE = 16384 + + +class PoolKey(typing.NamedTuple): + """ + All known keyword arguments that could be provided to the pool manager, its + pools, or the underlying connections. + + All custom key schemes should include the fields in this key at a minimum. + """ + + key_scheme: str + key_host: str + key_port: int | None + key_timeout: Timeout | float | int | None + key_retries: Retry | bool | int | None + key_block: bool | None + key_source_address: tuple[str, int] | None + key_key_file: str | None + key_key_password: str | None + key_cert_file: str | None + key_cert_reqs: str | None + key_ca_certs: str | None + key_ca_cert_data: str | bytes | None + key_ssl_version: int | str | None + key_ssl_minimum_version: ssl.TLSVersion | None + key_ssl_maximum_version: ssl.TLSVersion | None + key_ca_cert_dir: str | None + key_ssl_context: ssl.SSLContext | None + key_maxsize: int | None + key_headers: frozenset[tuple[str, str]] | None + key__proxy: Url | None + key__proxy_headers: frozenset[tuple[str, str]] | None + key__proxy_config: ProxyConfig | None + key_socket_options: _TYPE_SOCKET_OPTIONS | None + key__socks_options: frozenset[tuple[str, str]] | None + key_assert_hostname: bool | str | None + key_assert_fingerprint: str | None + key_server_hostname: str | None + key_blocksize: int | None + + +def _default_key_normalizer( + key_class: type[PoolKey], request_context: dict[str, typing.Any] +) -> PoolKey: + """ + Create a pool key out of a request context dictionary. + + According to RFC 3986, both the scheme and host are case-insensitive. + Therefore, this function normalizes both before constructing the pool + key for an HTTPS request. If you wish to change this behaviour, provide + alternate callables to ``key_fn_by_scheme``. + + :param key_class: + The class to use when constructing the key. This should be a namedtuple + with the ``scheme`` and ``host`` keys at a minimum. + :type key_class: namedtuple + :param request_context: + A dictionary-like object that contain the context for a request. + :type request_context: dict + + :return: A namedtuple that can be used as a connection pool key. + :rtype: PoolKey + """ + # Since we mutate the dictionary, make a copy first + context = request_context.copy() + context["scheme"] = context["scheme"].lower() + context["host"] = context["host"].lower() + + # These are both dictionaries and need to be transformed into frozensets + for key in ("headers", "_proxy_headers", "_socks_options"): + if key in context and context[key] is not None: + context[key] = frozenset(context[key].items()) + + # The socket_options key may be a list and needs to be transformed into a + # tuple. + socket_opts = context.get("socket_options") + if socket_opts is not None: + context["socket_options"] = tuple(socket_opts) + + # Map the kwargs to the names in the namedtuple - this is necessary since + # namedtuples can't have fields starting with '_'. + for key in list(context.keys()): + context["key_" + key] = context.pop(key) + + # Default to ``None`` for keys missing from the context + for field in key_class._fields: + if field not in context: + context[field] = None + + # Default key_blocksize to _DEFAULT_BLOCKSIZE if missing from the context + if context.get("key_blocksize") is None: + context["key_blocksize"] = _DEFAULT_BLOCKSIZE + + return key_class(**context) + + +#: A dictionary that maps a scheme to a callable that creates a pool key. +#: This can be used to alter the way pool keys are constructed, if desired. +#: Each PoolManager makes a copy of this dictionary so they can be configured +#: globally here, or individually on the instance. +key_fn_by_scheme = { + "http": functools.partial(_default_key_normalizer, PoolKey), + "https": functools.partial(_default_key_normalizer, PoolKey), +} + +pool_classes_by_scheme = {"http": HTTPConnectionPool, "https": HTTPSConnectionPool} + + +class PoolManager(RequestMethods): + """ + Allows for arbitrary requests while transparently keeping track of + necessary connection pools for you. + + :param num_pools: + Number of connection pools to cache before discarding the least + recently used pool. + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + + :param \\**connection_pool_kw: + Additional parameters are used to create fresh + :class:`urllib3.connectionpool.ConnectionPool` instances. + + Example: + + .. code-block:: python + + import urllib3 + + http = urllib3.PoolManager(num_pools=2) + + resp1 = http.request("GET", "https://google.com/") + resp2 = http.request("GET", "https://google.com/mail") + resp3 = http.request("GET", "https://yahoo.com/") + + print(len(http.pools)) + # 2 + + """ + + proxy: Url | None = None + proxy_config: ProxyConfig | None = None + + def __init__( + self, + num_pools: int = 10, + headers: typing.Mapping[str, str] | None = None, + **connection_pool_kw: typing.Any, + ) -> None: + super().__init__(headers) + self.connection_pool_kw = connection_pool_kw + + self.pools: RecentlyUsedContainer[PoolKey, HTTPConnectionPool] + self.pools = RecentlyUsedContainer(num_pools) + + # Locally set the pool classes and keys so other PoolManagers can + # override them. + self.pool_classes_by_scheme = pool_classes_by_scheme + self.key_fn_by_scheme = key_fn_by_scheme.copy() + + def __enter__(self) -> Self: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> typing.Literal[False]: + self.clear() + # Return False to re-raise any potential exceptions + return False + + def _new_pool( + self, + scheme: str, + host: str, + port: int, + request_context: dict[str, typing.Any] | None = None, + ) -> HTTPConnectionPool: + """ + Create a new :class:`urllib3.connectionpool.ConnectionPool` based on host, port, scheme, and + any additional pool keyword arguments. + + If ``request_context`` is provided, it is provided as keyword arguments + to the pool class used. This method is used to actually create the + connection pools handed out by :meth:`connection_from_url` and + companion methods. It is intended to be overridden for customization. + """ + pool_cls: type[HTTPConnectionPool] = self.pool_classes_by_scheme[scheme] + if request_context is None: + request_context = self.connection_pool_kw.copy() + + # Default blocksize to _DEFAULT_BLOCKSIZE if missing or explicitly + # set to 'None' in the request_context. + if request_context.get("blocksize") is None: + request_context["blocksize"] = _DEFAULT_BLOCKSIZE + + # Although the context has everything necessary to create the pool, + # this function has historically only used the scheme, host, and port + # in the positional args. When an API change is acceptable these can + # be removed. + for key in ("scheme", "host", "port"): + request_context.pop(key, None) + + if scheme == "http": + for kw in SSL_KEYWORDS: + request_context.pop(kw, None) + + return pool_cls(host, port, **request_context) + + def clear(self) -> None: + """ + Empty our store of pools and direct them all to close. + + This will not affect in-flight connections, but they will not be + re-used after completion. + """ + self.pools.clear() + + def connection_from_host( + self, + host: str | None, + port: int | None = None, + scheme: str | None = "http", + pool_kwargs: dict[str, typing.Any] | None = None, + ) -> HTTPConnectionPool: + """ + Get a :class:`urllib3.connectionpool.ConnectionPool` based on the host, port, and scheme. + + If ``port`` isn't given, it will be derived from the ``scheme`` using + ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is + provided, it is merged with the instance's ``connection_pool_kw`` + variable and used to create the new connection pool, if one is + needed. + """ + + if not host: + raise LocationValueError("No host specified.") + + request_context = self._merge_pool_kwargs(pool_kwargs) + request_context["scheme"] = scheme or "http" + if not port: + port = port_by_scheme.get(request_context["scheme"].lower(), 80) + request_context["port"] = port + request_context["host"] = host + + return self.connection_from_context(request_context) + + def connection_from_context( + self, request_context: dict[str, typing.Any] + ) -> HTTPConnectionPool: + """ + Get a :class:`urllib3.connectionpool.ConnectionPool` based on the request context. + + ``request_context`` must at least contain the ``scheme`` key and its + value must be a key in ``key_fn_by_scheme`` instance variable. + """ + if "strict" in request_context: + warnings.warn( + "The 'strict' parameter is no longer needed on Python 3+. " + "This will raise an error in urllib3 v2.1.0.", + DeprecationWarning, + ) + request_context.pop("strict") + + scheme = request_context["scheme"].lower() + pool_key_constructor = self.key_fn_by_scheme.get(scheme) + if not pool_key_constructor: + raise URLSchemeUnknown(scheme) + pool_key = pool_key_constructor(request_context) + + return self.connection_from_pool_key(pool_key, request_context=request_context) + + def connection_from_pool_key( + self, pool_key: PoolKey, request_context: dict[str, typing.Any] + ) -> HTTPConnectionPool: + """ + Get a :class:`urllib3.connectionpool.ConnectionPool` based on the provided pool key. + + ``pool_key`` should be a namedtuple that only contains immutable + objects. At a minimum it must have the ``scheme``, ``host``, and + ``port`` fields. + """ + with self.pools.lock: + # If the scheme, host, or port doesn't match existing open + # connections, open a new ConnectionPool. + pool = self.pools.get(pool_key) + if pool: + return pool + + # Make a fresh ConnectionPool of the desired type + scheme = request_context["scheme"] + host = request_context["host"] + port = request_context["port"] + pool = self._new_pool(scheme, host, port, request_context=request_context) + self.pools[pool_key] = pool + + return pool + + def connection_from_url( + self, url: str, pool_kwargs: dict[str, typing.Any] | None = None + ) -> HTTPConnectionPool: + """ + Similar to :func:`urllib3.connectionpool.connection_from_url`. + + If ``pool_kwargs`` is not provided and a new pool needs to be + constructed, ``self.connection_pool_kw`` is used to initialize + the :class:`urllib3.connectionpool.ConnectionPool`. If ``pool_kwargs`` + is provided, it is used instead. Note that if a new pool does not + need to be created for the request, the provided ``pool_kwargs`` are + not used. + """ + u = parse_url(url) + return self.connection_from_host( + u.host, port=u.port, scheme=u.scheme, pool_kwargs=pool_kwargs + ) + + def _merge_pool_kwargs( + self, override: dict[str, typing.Any] | None + ) -> dict[str, typing.Any]: + """ + Merge a dictionary of override values for self.connection_pool_kw. + + This does not modify self.connection_pool_kw and returns a new dict. + Any keys in the override dictionary with a value of ``None`` are + removed from the merged dictionary. + """ + base_pool_kwargs = self.connection_pool_kw.copy() + if override: + for key, value in override.items(): + if value is None: + try: + del base_pool_kwargs[key] + except KeyError: + pass + else: + base_pool_kwargs[key] = value + return base_pool_kwargs + + def _proxy_requires_url_absolute_form(self, parsed_url: Url) -> bool: + """ + Indicates if the proxy requires the complete destination URL in the + request. Normally this is only needed when not using an HTTP CONNECT + tunnel. + """ + if self.proxy is None: + return False + + return not connection_requires_http_tunnel( + self.proxy, self.proxy_config, parsed_url.scheme + ) + + def urlopen( # type: ignore[override] + self, method: str, url: str, redirect: bool = True, **kw: typing.Any + ) -> BaseHTTPResponse: + """ + Same as :meth:`urllib3.HTTPConnectionPool.urlopen` + with custom cross-host redirect logic and only sends the request-uri + portion of the ``url``. + + The given ``url`` parameter must be absolute, such that an appropriate + :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. + """ + u = parse_url(url) + + if u.scheme is None: + warnings.warn( + "URLs without a scheme (ie 'https://') are deprecated and will raise an error " + "in a future version of urllib3. To avoid this DeprecationWarning ensure all URLs " + "start with 'https://' or 'http://'. Read more in this issue: " + "https://github.com/urllib3/urllib3/issues/2920", + category=DeprecationWarning, + stacklevel=2, + ) + + conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) + + kw["assert_same_host"] = False + kw["redirect"] = False + + if "headers" not in kw: + kw["headers"] = self.headers + + if self._proxy_requires_url_absolute_form(u): + response = conn.urlopen(method, url, **kw) + else: + response = conn.urlopen(method, u.request_uri, **kw) + + redirect_location = redirect and response.get_redirect_location() + if not redirect_location: + return response + + # Support relative URLs for redirecting. + redirect_location = urljoin(url, redirect_location) + + if response.status == 303: + # Change the method according to RFC 9110, Section 15.4.4. + method = "GET" + # And lose the body not to transfer anything sensitive. + kw["body"] = None + kw["headers"] = HTTPHeaderDict(kw["headers"])._prepare_for_method_change() + + retries = kw.get("retries") + if not isinstance(retries, Retry): + retries = Retry.from_int(retries, redirect=redirect) + + # Strip headers marked as unsafe to forward to the redirected location. + # Check remove_headers_on_redirect to avoid a potential network call within + # conn.is_same_host() which may use socket.gethostbyname() in the future. + if retries.remove_headers_on_redirect and not conn.is_same_host( + redirect_location + ): + new_headers = kw["headers"].copy() + for header in kw["headers"]: + if header.lower() in retries.remove_headers_on_redirect: + new_headers.pop(header, None) + kw["headers"] = new_headers + + try: + retries = retries.increment(method, url, response=response, _pool=conn) + except MaxRetryError: + if retries.raise_on_redirect: + response.drain_conn() + raise + return response + + kw["retries"] = retries + kw["redirect"] = redirect + + log.info("Redirecting %s -> %s", url, redirect_location) + + response.drain_conn() + return self.urlopen(method, redirect_location, **kw) + + +class ProxyManager(PoolManager): + """ + Behaves just like :class:`PoolManager`, but sends all requests through + the defined proxy, using the CONNECT method for HTTPS URLs. + + :param proxy_url: + The URL of the proxy to be used. + + :param proxy_headers: + A dictionary containing headers that will be sent to the proxy. In case + of HTTP they are being sent with each request, while in the + HTTPS/CONNECT case they are sent only once. Could be used for proxy + authentication. + + :param proxy_ssl_context: + The proxy SSL context is used to establish the TLS connection to the + proxy when using HTTPS proxies. + + :param use_forwarding_for_https: + (Defaults to False) If set to True will forward requests to the HTTPS + proxy to be made on behalf of the client instead of creating a TLS + tunnel via the CONNECT method. **Enabling this flag means that request + and response headers and content will be visible from the HTTPS proxy** + whereas tunneling keeps request and response headers and content + private. IP address, target hostname, SNI, and port are always visible + to an HTTPS proxy even when this flag is disabled. + + :param proxy_assert_hostname: + The hostname of the certificate to verify against. + + :param proxy_assert_fingerprint: + The fingerprint of the certificate to verify against. + + Example: + + .. code-block:: python + + import urllib3 + + proxy = urllib3.ProxyManager("https://localhost:3128/") + + resp1 = proxy.request("GET", "https://google.com/") + resp2 = proxy.request("GET", "https://httpbin.org/") + + print(len(proxy.pools)) + # 1 + + resp3 = proxy.request("GET", "https://httpbin.org/") + resp4 = proxy.request("GET", "https://twitter.com/") + + print(len(proxy.pools)) + # 3 + + """ + + def __init__( + self, + proxy_url: str, + num_pools: int = 10, + headers: typing.Mapping[str, str] | None = None, + proxy_headers: typing.Mapping[str, str] | None = None, + proxy_ssl_context: ssl.SSLContext | None = None, + use_forwarding_for_https: bool = False, + proxy_assert_hostname: None | str | typing.Literal[False] = None, + proxy_assert_fingerprint: str | None = None, + **connection_pool_kw: typing.Any, + ) -> None: + if isinstance(proxy_url, HTTPConnectionPool): + str_proxy_url = f"{proxy_url.scheme}://{proxy_url.host}:{proxy_url.port}" + else: + str_proxy_url = proxy_url + proxy = parse_url(str_proxy_url) + + if proxy.scheme not in ("http", "https"): + raise ProxySchemeUnknown(proxy.scheme) + + if not proxy.port: + port = port_by_scheme.get(proxy.scheme, 80) + proxy = proxy._replace(port=port) + + self.proxy = proxy + self.proxy_headers = proxy_headers or {} + self.proxy_ssl_context = proxy_ssl_context + self.proxy_config = ProxyConfig( + proxy_ssl_context, + use_forwarding_for_https, + proxy_assert_hostname, + proxy_assert_fingerprint, + ) + + connection_pool_kw["_proxy"] = self.proxy + connection_pool_kw["_proxy_headers"] = self.proxy_headers + connection_pool_kw["_proxy_config"] = self.proxy_config + + super().__init__(num_pools, headers, **connection_pool_kw) + + def connection_from_host( + self, + host: str | None, + port: int | None = None, + scheme: str | None = "http", + pool_kwargs: dict[str, typing.Any] | None = None, + ) -> HTTPConnectionPool: + if scheme == "https": + return super().connection_from_host( + host, port, scheme, pool_kwargs=pool_kwargs + ) + + return super().connection_from_host( + self.proxy.host, self.proxy.port, self.proxy.scheme, pool_kwargs=pool_kwargs # type: ignore[union-attr] + ) + + def _set_proxy_headers( + self, url: str, headers: typing.Mapping[str, str] | None = None + ) -> typing.Mapping[str, str]: + """ + Sets headers needed by proxies: specifically, the Accept and Host + headers. Only sets headers not provided by the user. + """ + headers_ = {"Accept": "*/*"} + + netloc = parse_url(url).netloc + if netloc: + headers_["Host"] = netloc + + if headers: + headers_.update(headers) + return headers_ + + def urlopen( # type: ignore[override] + self, method: str, url: str, redirect: bool = True, **kw: typing.Any + ) -> BaseHTTPResponse: + "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute." + u = parse_url(url) + if not connection_requires_http_tunnel(self.proxy, self.proxy_config, u.scheme): + # For connections using HTTP CONNECT, httplib sets the necessary + # headers on the CONNECT to the proxy. If we're not using CONNECT, + # we'll definitely need to set 'Host' at the very least. + headers = kw.get("headers", self.headers) + kw["headers"] = self._set_proxy_headers(url, headers) + + return super().urlopen(method, url, redirect=redirect, **kw) + + +def proxy_from_url(url: str, **kw: typing.Any) -> ProxyManager: + return ProxyManager(proxy_url=url, **kw) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/py.typed b/apigw-private-cdn-acm/acm-certificate/urllib3/py.typed new file mode 100644 index 000000000..5f3ea3d91 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/py.typed @@ -0,0 +1,2 @@ +# Instruct type checkers to look for inline type annotations in this package. +# See PEP 561. diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/response.py b/apigw-private-cdn-acm/acm-certificate/urllib3/response.py new file mode 100644 index 000000000..66c6a687e --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/response.py @@ -0,0 +1,1278 @@ +from __future__ import annotations + +import collections +import io +import json as _json +import logging +import re +import socket +import sys +import typing +import warnings +import zlib +from contextlib import contextmanager +from http.client import HTTPMessage as _HttplibHTTPMessage +from http.client import HTTPResponse as _HttplibHTTPResponse +from socket import timeout as SocketTimeout + +if typing.TYPE_CHECKING: + from ._base_connection import BaseHTTPConnection + +try: + try: + import brotlicffi as brotli # type: ignore[import-not-found] + except ImportError: + import brotli # type: ignore[import-not-found] +except ImportError: + brotli = None + +try: + import zstandard as zstd +except (AttributeError, ImportError, ValueError): # Defensive: + HAS_ZSTD = False +else: + # The package 'zstandard' added the 'eof' property starting + # in v0.18.0 which we require to ensure a complete and + # valid zstd stream was fed into the ZstdDecoder. + # See: https://github.com/urllib3/urllib3/pull/2624 + _zstd_version = tuple( + map(int, re.search(r"^([0-9]+)\.([0-9]+)", zstd.__version__).groups()) # type: ignore[union-attr] + ) + if _zstd_version < (0, 18): # Defensive: + HAS_ZSTD = False + else: + HAS_ZSTD = True + +from . import util +from ._base_connection import _TYPE_BODY +from ._collections import HTTPHeaderDict +from .connection import BaseSSLError, HTTPConnection, HTTPException +from .exceptions import ( + BodyNotHttplibCompatible, + DecodeError, + HTTPError, + IncompleteRead, + InvalidChunkLength, + InvalidHeader, + ProtocolError, + ReadTimeoutError, + ResponseNotChunked, + SSLError, +) +from .util.response import is_fp_closed, is_response_to_head +from .util.retry import Retry + +if typing.TYPE_CHECKING: + from .connectionpool import HTTPConnectionPool + +log = logging.getLogger(__name__) + + +class ContentDecoder: + def decompress(self, data: bytes) -> bytes: + raise NotImplementedError() + + def flush(self) -> bytes: + raise NotImplementedError() + + +class DeflateDecoder(ContentDecoder): + def __init__(self) -> None: + self._first_try = True + self._data = b"" + self._obj = zlib.decompressobj() + + def decompress(self, data: bytes) -> bytes: + if not data: + return data + + if not self._first_try: + return self._obj.decompress(data) + + self._data += data + try: + decompressed = self._obj.decompress(data) + if decompressed: + self._first_try = False + self._data = None # type: ignore[assignment] + return decompressed + except zlib.error: + self._first_try = False + self._obj = zlib.decompressobj(-zlib.MAX_WBITS) + try: + return self.decompress(self._data) + finally: + self._data = None # type: ignore[assignment] + + def flush(self) -> bytes: + return self._obj.flush() + + +class GzipDecoderState: + FIRST_MEMBER = 0 + OTHER_MEMBERS = 1 + SWALLOW_DATA = 2 + + +class GzipDecoder(ContentDecoder): + def __init__(self) -> None: + self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS) + self._state = GzipDecoderState.FIRST_MEMBER + + def decompress(self, data: bytes) -> bytes: + ret = bytearray() + if self._state == GzipDecoderState.SWALLOW_DATA or not data: + return bytes(ret) + while True: + try: + ret += self._obj.decompress(data) + except zlib.error: + previous_state = self._state + # Ignore data after the first error + self._state = GzipDecoderState.SWALLOW_DATA + if previous_state == GzipDecoderState.OTHER_MEMBERS: + # Allow trailing garbage acceptable in other gzip clients + return bytes(ret) + raise + data = self._obj.unused_data + if not data: + return bytes(ret) + self._state = GzipDecoderState.OTHER_MEMBERS + self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS) + + def flush(self) -> bytes: + return self._obj.flush() + + +if brotli is not None: + + class BrotliDecoder(ContentDecoder): + # Supports both 'brotlipy' and 'Brotli' packages + # since they share an import name. The top branches + # are for 'brotlipy' and bottom branches for 'Brotli' + def __init__(self) -> None: + self._obj = brotli.Decompressor() + if hasattr(self._obj, "decompress"): + setattr(self, "decompress", self._obj.decompress) + else: + setattr(self, "decompress", self._obj.process) + + def flush(self) -> bytes: + if hasattr(self._obj, "flush"): + return self._obj.flush() # type: ignore[no-any-return] + return b"" + + +if HAS_ZSTD: + + class ZstdDecoder(ContentDecoder): + def __init__(self) -> None: + self._obj = zstd.ZstdDecompressor().decompressobj() + + def decompress(self, data: bytes) -> bytes: + if not data: + return b"" + data_parts = [self._obj.decompress(data)] + while self._obj.eof and self._obj.unused_data: + unused_data = self._obj.unused_data + self._obj = zstd.ZstdDecompressor().decompressobj() + data_parts.append(self._obj.decompress(unused_data)) + return b"".join(data_parts) + + def flush(self) -> bytes: + ret = self._obj.flush() # note: this is a no-op + if not self._obj.eof: + raise DecodeError("Zstandard data is incomplete") + return ret + + +class MultiDecoder(ContentDecoder): + """ + From RFC7231: + If one or more encodings have been applied to a representation, the + sender that applied the encodings MUST generate a Content-Encoding + header field that lists the content codings in the order in which + they were applied. + """ + + def __init__(self, modes: str) -> None: + self._decoders = [_get_decoder(m.strip()) for m in modes.split(",")] + + def flush(self) -> bytes: + return self._decoders[0].flush() + + def decompress(self, data: bytes) -> bytes: + for d in reversed(self._decoders): + data = d.decompress(data) + return data + + +def _get_decoder(mode: str) -> ContentDecoder: + if "," in mode: + return MultiDecoder(mode) + + # According to RFC 9110 section 8.4.1.3, recipients should + # consider x-gzip equivalent to gzip + if mode in ("gzip", "x-gzip"): + return GzipDecoder() + + if brotli is not None and mode == "br": + return BrotliDecoder() + + if HAS_ZSTD and mode == "zstd": + return ZstdDecoder() + + return DeflateDecoder() + + +class BytesQueueBuffer: + """Memory-efficient bytes buffer + + To return decoded data in read() and still follow the BufferedIOBase API, we need a + buffer to always return the correct amount of bytes. + + This buffer should be filled using calls to put() + + Our maximum memory usage is determined by the sum of the size of: + + * self.buffer, which contains the full data + * the largest chunk that we will copy in get() + + The worst case scenario is a single chunk, in which case we'll make a full copy of + the data inside get(). + """ + + def __init__(self) -> None: + self.buffer: typing.Deque[bytes] = collections.deque() + self._size: int = 0 + + def __len__(self) -> int: + return self._size + + def put(self, data: bytes) -> None: + self.buffer.append(data) + self._size += len(data) + + def get(self, n: int) -> bytes: + if n == 0: + return b"" + elif not self.buffer: + raise RuntimeError("buffer is empty") + elif n < 0: + raise ValueError("n should be > 0") + + fetched = 0 + ret = io.BytesIO() + while fetched < n: + remaining = n - fetched + chunk = self.buffer.popleft() + chunk_length = len(chunk) + if remaining < chunk_length: + left_chunk, right_chunk = chunk[:remaining], chunk[remaining:] + ret.write(left_chunk) + self.buffer.appendleft(right_chunk) + self._size -= remaining + break + else: + ret.write(chunk) + self._size -= chunk_length + fetched += chunk_length + + if not self.buffer: + break + + return ret.getvalue() + + def get_all(self) -> bytes: + buffer = self.buffer + if not buffer: + assert self._size == 0 + return b"" + if len(buffer) == 1: + result = buffer.pop() + else: + ret = io.BytesIO() + ret.writelines(buffer.popleft() for _ in range(len(buffer))) + result = ret.getvalue() + self._size = 0 + return result + + +class BaseHTTPResponse(io.IOBase): + CONTENT_DECODERS = ["gzip", "x-gzip", "deflate"] + if brotli is not None: + CONTENT_DECODERS += ["br"] + if HAS_ZSTD: + CONTENT_DECODERS += ["zstd"] + REDIRECT_STATUSES = [301, 302, 303, 307, 308] + + DECODER_ERROR_CLASSES: tuple[type[Exception], ...] = (IOError, zlib.error) + if brotli is not None: + DECODER_ERROR_CLASSES += (brotli.error,) + + if HAS_ZSTD: + DECODER_ERROR_CLASSES += (zstd.ZstdError,) + + def __init__( + self, + *, + headers: typing.Mapping[str, str] | typing.Mapping[bytes, bytes] | None = None, + status: int, + version: int, + version_string: str, + reason: str | None, + decode_content: bool, + request_url: str | None, + retries: Retry | None = None, + ) -> None: + if isinstance(headers, HTTPHeaderDict): + self.headers = headers + else: + self.headers = HTTPHeaderDict(headers) # type: ignore[arg-type] + self.status = status + self.version = version + self.version_string = version_string + self.reason = reason + self.decode_content = decode_content + self._has_decoded_content = False + self._request_url: str | None = request_url + self.retries = retries + + self.chunked = False + tr_enc = self.headers.get("transfer-encoding", "").lower() + # Don't incur the penalty of creating a list and then discarding it + encodings = (enc.strip() for enc in tr_enc.split(",")) + if "chunked" in encodings: + self.chunked = True + + self._decoder: ContentDecoder | None = None + self.length_remaining: int | None + + def get_redirect_location(self) -> str | None | typing.Literal[False]: + """ + Should we redirect and where to? + + :returns: Truthy redirect location string if we got a redirect status + code and valid location. ``None`` if redirect status and no + location. ``False`` if not a redirect status code. + """ + if self.status in self.REDIRECT_STATUSES: + return self.headers.get("location") + return False + + @property + def data(self) -> bytes: + raise NotImplementedError() + + def json(self) -> typing.Any: + """ + Deserializes the body of the HTTP response as a Python object. + + The body of the HTTP response must be encoded using UTF-8, as per + `RFC 8529 Section 8.1 `_. + + To use a custom JSON decoder pass the result of :attr:`HTTPResponse.data` to + your custom decoder instead. + + If the body of the HTTP response is not decodable to UTF-8, a + `UnicodeDecodeError` will be raised. If the body of the HTTP response is not a + valid JSON document, a `json.JSONDecodeError` will be raised. + + Read more :ref:`here `. + + :returns: The body of the HTTP response as a Python object. + """ + data = self.data.decode("utf-8") + return _json.loads(data) + + @property + def url(self) -> str | None: + raise NotImplementedError() + + @url.setter + def url(self, url: str | None) -> None: + raise NotImplementedError() + + @property + def connection(self) -> BaseHTTPConnection | None: + raise NotImplementedError() + + @property + def retries(self) -> Retry | None: + return self._retries + + @retries.setter + def retries(self, retries: Retry | None) -> None: + # Override the request_url if retries has a redirect location. + if retries is not None and retries.history: + self.url = retries.history[-1].redirect_location + self._retries = retries + + def stream( + self, amt: int | None = 2**16, decode_content: bool | None = None + ) -> typing.Iterator[bytes]: + raise NotImplementedError() + + def read( + self, + amt: int | None = None, + decode_content: bool | None = None, + cache_content: bool = False, + ) -> bytes: + raise NotImplementedError() + + def read1( + self, + amt: int | None = None, + decode_content: bool | None = None, + ) -> bytes: + raise NotImplementedError() + + def read_chunked( + self, + amt: int | None = None, + decode_content: bool | None = None, + ) -> typing.Iterator[bytes]: + raise NotImplementedError() + + def release_conn(self) -> None: + raise NotImplementedError() + + def drain_conn(self) -> None: + raise NotImplementedError() + + def shutdown(self) -> None: + raise NotImplementedError() + + def close(self) -> None: + raise NotImplementedError() + + def _init_decoder(self) -> None: + """ + Set-up the _decoder attribute if necessary. + """ + # Note: content-encoding value should be case-insensitive, per RFC 7230 + # Section 3.2 + content_encoding = self.headers.get("content-encoding", "").lower() + if self._decoder is None: + if content_encoding in self.CONTENT_DECODERS: + self._decoder = _get_decoder(content_encoding) + elif "," in content_encoding: + encodings = [ + e.strip() + for e in content_encoding.split(",") + if e.strip() in self.CONTENT_DECODERS + ] + if encodings: + self._decoder = _get_decoder(content_encoding) + + def _decode( + self, data: bytes, decode_content: bool | None, flush_decoder: bool + ) -> bytes: + """ + Decode the data passed in and potentially flush the decoder. + """ + if not decode_content: + if self._has_decoded_content: + raise RuntimeError( + "Calling read(decode_content=False) is not supported after " + "read(decode_content=True) was called." + ) + return data + + try: + if self._decoder: + data = self._decoder.decompress(data) + self._has_decoded_content = True + except self.DECODER_ERROR_CLASSES as e: + content_encoding = self.headers.get("content-encoding", "").lower() + raise DecodeError( + "Received response with content-encoding: %s, but " + "failed to decode it." % content_encoding, + e, + ) from e + if flush_decoder: + data += self._flush_decoder() + + return data + + def _flush_decoder(self) -> bytes: + """ + Flushes the decoder. Should only be called if the decoder is actually + being used. + """ + if self._decoder: + return self._decoder.decompress(b"") + self._decoder.flush() + return b"" + + # Compatibility methods for `io` module + def readinto(self, b: bytearray) -> int: + temp = self.read(len(b)) + if len(temp) == 0: + return 0 + else: + b[: len(temp)] = temp + return len(temp) + + # Compatibility methods for http.client.HTTPResponse + def getheaders(self) -> HTTPHeaderDict: + warnings.warn( + "HTTPResponse.getheaders() is deprecated and will be removed " + "in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.", + category=DeprecationWarning, + stacklevel=2, + ) + return self.headers + + def getheader(self, name: str, default: str | None = None) -> str | None: + warnings.warn( + "HTTPResponse.getheader() is deprecated and will be removed " + "in urllib3 v2.1.0. Instead use HTTPResponse.headers.get(name, default).", + category=DeprecationWarning, + stacklevel=2, + ) + return self.headers.get(name, default) + + # Compatibility method for http.cookiejar + def info(self) -> HTTPHeaderDict: + return self.headers + + def geturl(self) -> str | None: + return self.url + + +class HTTPResponse(BaseHTTPResponse): + """ + HTTP Response container. + + Backwards-compatible with :class:`http.client.HTTPResponse` but the response ``body`` is + loaded and decoded on-demand when the ``data`` property is accessed. This + class is also compatible with the Python standard library's :mod:`io` + module, and can hence be treated as a readable object in the context of that + framework. + + Extra parameters for behaviour not present in :class:`http.client.HTTPResponse`: + + :param preload_content: + If True, the response's body will be preloaded during construction. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param original_response: + When this HTTPResponse wrapper is generated from an :class:`http.client.HTTPResponse` + object, it's convenient to include the original for debug purposes. It's + otherwise unused. + + :param retries: + The retries contains the last :class:`~urllib3.util.retry.Retry` that + was used during the request. + + :param enforce_content_length: + Enforce content length checking. Body returned by server must match + value of Content-Length header, if present. Otherwise, raise error. + """ + + def __init__( + self, + body: _TYPE_BODY = "", + headers: typing.Mapping[str, str] | typing.Mapping[bytes, bytes] | None = None, + status: int = 0, + version: int = 0, + version_string: str = "HTTP/?", + reason: str | None = None, + preload_content: bool = True, + decode_content: bool = True, + original_response: _HttplibHTTPResponse | None = None, + pool: HTTPConnectionPool | None = None, + connection: HTTPConnection | None = None, + msg: _HttplibHTTPMessage | None = None, + retries: Retry | None = None, + enforce_content_length: bool = True, + request_method: str | None = None, + request_url: str | None = None, + auto_close: bool = True, + sock_shutdown: typing.Callable[[int], None] | None = None, + ) -> None: + super().__init__( + headers=headers, + status=status, + version=version, + version_string=version_string, + reason=reason, + decode_content=decode_content, + request_url=request_url, + retries=retries, + ) + + self.enforce_content_length = enforce_content_length + self.auto_close = auto_close + + self._body = None + self._fp: _HttplibHTTPResponse | None = None + self._original_response = original_response + self._fp_bytes_read = 0 + self.msg = msg + + if body and isinstance(body, (str, bytes)): + self._body = body + + self._pool = pool + self._connection = connection + + if hasattr(body, "read"): + self._fp = body # type: ignore[assignment] + self._sock_shutdown = sock_shutdown + + # Are we using the chunked-style of transfer encoding? + self.chunk_left: int | None = None + + # Determine length of response + self.length_remaining = self._init_length(request_method) + + # Used to return the correct amount of bytes for partial read()s + self._decoded_buffer = BytesQueueBuffer() + + # If requested, preload the body. + if preload_content and not self._body: + self._body = self.read(decode_content=decode_content) + + def release_conn(self) -> None: + if not self._pool or not self._connection: + return None + + self._pool._put_conn(self._connection) + self._connection = None + + def drain_conn(self) -> None: + """ + Read and discard any remaining HTTP response data in the response connection. + + Unread data in the HTTPResponse connection blocks the connection from being released back to the pool. + """ + try: + self.read() + except (HTTPError, OSError, BaseSSLError, HTTPException): + pass + + @property + def data(self) -> bytes: + # For backwards-compat with earlier urllib3 0.4 and earlier. + if self._body: + return self._body # type: ignore[return-value] + + if self._fp: + return self.read(cache_content=True) + + return None # type: ignore[return-value] + + @property + def connection(self) -> HTTPConnection | None: + return self._connection + + def isclosed(self) -> bool: + return is_fp_closed(self._fp) + + def tell(self) -> int: + """ + Obtain the number of bytes pulled over the wire so far. May differ from + the amount of content returned by :meth:``urllib3.response.HTTPResponse.read`` + if bytes are encoded on the wire (e.g, compressed). + """ + return self._fp_bytes_read + + def _init_length(self, request_method: str | None) -> int | None: + """ + Set initial length value for Response content if available. + """ + length: int | None + content_length: str | None = self.headers.get("content-length") + + if content_length is not None: + if self.chunked: + # This Response will fail with an IncompleteRead if it can't be + # received as chunked. This method falls back to attempt reading + # the response before raising an exception. + log.warning( + "Received response with both Content-Length and " + "Transfer-Encoding set. This is expressly forbidden " + "by RFC 7230 sec 3.3.2. Ignoring Content-Length and " + "attempting to process response as Transfer-Encoding: " + "chunked." + ) + return None + + try: + # RFC 7230 section 3.3.2 specifies multiple content lengths can + # be sent in a single Content-Length header + # (e.g. Content-Length: 42, 42). This line ensures the values + # are all valid ints and that as long as the `set` length is 1, + # all values are the same. Otherwise, the header is invalid. + lengths = {int(val) for val in content_length.split(",")} + if len(lengths) > 1: + raise InvalidHeader( + "Content-Length contained multiple " + "unmatching values (%s)" % content_length + ) + length = lengths.pop() + except ValueError: + length = None + else: + if length < 0: + length = None + + else: # if content_length is None + length = None + + # Convert status to int for comparison + # In some cases, httplib returns a status of "_UNKNOWN" + try: + status = int(self.status) + except ValueError: + status = 0 + + # Check for responses that shouldn't include a body + if status in (204, 304) or 100 <= status < 200 or request_method == "HEAD": + length = 0 + + return length + + @contextmanager + def _error_catcher(self) -> typing.Generator[None]: + """ + Catch low-level python exceptions, instead re-raising urllib3 + variants, so that low-level exceptions are not leaked in the + high-level api. + + On exit, release the connection back to the pool. + """ + clean_exit = False + + try: + try: + yield + + except SocketTimeout as e: + # FIXME: Ideally we'd like to include the url in the ReadTimeoutError but + # there is yet no clean way to get at it from this context. + raise ReadTimeoutError(self._pool, None, "Read timed out.") from e # type: ignore[arg-type] + + except BaseSSLError as e: + # FIXME: Is there a better way to differentiate between SSLErrors? + if "read operation timed out" not in str(e): + # SSL errors related to framing/MAC get wrapped and reraised here + raise SSLError(e) from e + + raise ReadTimeoutError(self._pool, None, "Read timed out.") from e # type: ignore[arg-type] + + except IncompleteRead as e: + if ( + e.expected is not None + and e.partial is not None + and e.expected == -e.partial + ): + arg = "Response may not contain content." + else: + arg = f"Connection broken: {e!r}" + raise ProtocolError(arg, e) from e + + except (HTTPException, OSError) as e: + raise ProtocolError(f"Connection broken: {e!r}", e) from e + + # If no exception is thrown, we should avoid cleaning up + # unnecessarily. + clean_exit = True + finally: + # If we didn't terminate cleanly, we need to throw away our + # connection. + if not clean_exit: + # The response may not be closed but we're not going to use it + # anymore so close it now to ensure that the connection is + # released back to the pool. + if self._original_response: + self._original_response.close() + + # Closing the response may not actually be sufficient to close + # everything, so if we have a hold of the connection close that + # too. + if self._connection: + self._connection.close() + + # If we hold the original response but it's closed now, we should + # return the connection back to the pool. + if self._original_response and self._original_response.isclosed(): + self.release_conn() + + def _fp_read( + self, + amt: int | None = None, + *, + read1: bool = False, + ) -> bytes: + """ + Read a response with the thought that reading the number of bytes + larger than can fit in a 32-bit int at a time via SSL in some + known cases leads to an overflow error that has to be prevented + if `amt` or `self.length_remaining` indicate that a problem may + happen. + + The known cases: + * CPython < 3.9.7 because of a bug + https://github.com/urllib3/urllib3/issues/2513#issuecomment-1152559900. + * urllib3 injected with pyOpenSSL-backed SSL-support. + * CPython < 3.10 only when `amt` does not fit 32-bit int. + """ + assert self._fp + c_int_max = 2**31 - 1 + if ( + (amt and amt > c_int_max) + or ( + amt is None + and self.length_remaining + and self.length_remaining > c_int_max + ) + ) and (util.IS_PYOPENSSL or sys.version_info < (3, 10)): + if read1: + return self._fp.read1(c_int_max) + buffer = io.BytesIO() + # Besides `max_chunk_amt` being a maximum chunk size, it + # affects memory overhead of reading a response by this + # method in CPython. + # `c_int_max` equal to 2 GiB - 1 byte is the actual maximum + # chunk size that does not lead to an overflow error, but + # 256 MiB is a compromise. + max_chunk_amt = 2**28 + while amt is None or amt != 0: + if amt is not None: + chunk_amt = min(amt, max_chunk_amt) + amt -= chunk_amt + else: + chunk_amt = max_chunk_amt + data = self._fp.read(chunk_amt) + if not data: + break + buffer.write(data) + del data # to reduce peak memory usage by `max_chunk_amt`. + return buffer.getvalue() + elif read1: + return self._fp.read1(amt) if amt is not None else self._fp.read1() + else: + # StringIO doesn't like amt=None + return self._fp.read(amt) if amt is not None else self._fp.read() + + def _raw_read( + self, + amt: int | None = None, + *, + read1: bool = False, + ) -> bytes: + """ + Reads `amt` of bytes from the socket. + """ + if self._fp is None: + return None # type: ignore[return-value] + + fp_closed = getattr(self._fp, "closed", False) + + with self._error_catcher(): + data = self._fp_read(amt, read1=read1) if not fp_closed else b"" + if amt is not None and amt != 0 and not data: + # Platform-specific: Buggy versions of Python. + # Close the connection when no data is returned + # + # This is redundant to what httplib/http.client _should_ + # already do. However, versions of python released before + # December 15, 2012 (http://bugs.python.org/issue16298) do + # not properly close the connection in all cases. There is + # no harm in redundantly calling close. + self._fp.close() + if ( + self.enforce_content_length + and self.length_remaining is not None + and self.length_remaining != 0 + ): + # This is an edge case that httplib failed to cover due + # to concerns of backward compatibility. We're + # addressing it here to make sure IncompleteRead is + # raised during streaming, so all calls with incorrect + # Content-Length are caught. + raise IncompleteRead(self._fp_bytes_read, self.length_remaining) + elif read1 and ( + (amt != 0 and not data) or self.length_remaining == len(data) + ): + # All data has been read, but `self._fp.read1` in + # CPython 3.12 and older doesn't always close + # `http.client.HTTPResponse`, so we close it here. + # See https://github.com/python/cpython/issues/113199 + self._fp.close() + + if data: + self._fp_bytes_read += len(data) + if self.length_remaining is not None: + self.length_remaining -= len(data) + return data + + def read( + self, + amt: int | None = None, + decode_content: bool | None = None, + cache_content: bool = False, + ) -> bytes: + """ + Similar to :meth:`http.client.HTTPResponse.read`, but with two additional + parameters: ``decode_content`` and ``cache_content``. + + :param amt: + How much of the content to read. If specified, caching is skipped + because it doesn't make sense to cache partial content as the full + response. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param cache_content: + If True, will save the returned data such that the same result is + returned despite of the state of the underlying file object. This + is useful if you want the ``.data`` property to continue working + after having ``.read()`` the file object. (Overridden if ``amt`` is + set.) + """ + self._init_decoder() + if decode_content is None: + decode_content = self.decode_content + + if amt and amt < 0: + # Negative numbers and `None` should be treated the same. + amt = None + elif amt is not None: + cache_content = False + + if len(self._decoded_buffer) >= amt: + return self._decoded_buffer.get(amt) + + data = self._raw_read(amt) + + flush_decoder = amt is None or (amt != 0 and not data) + + if not data and len(self._decoded_buffer) == 0: + return data + + if amt is None: + data = self._decode(data, decode_content, flush_decoder) + if cache_content: + self._body = data + else: + # do not waste memory on buffer when not decoding + if not decode_content: + if self._has_decoded_content: + raise RuntimeError( + "Calling read(decode_content=False) is not supported after " + "read(decode_content=True) was called." + ) + return data + + decoded_data = self._decode(data, decode_content, flush_decoder) + self._decoded_buffer.put(decoded_data) + + while len(self._decoded_buffer) < amt and data: + # TODO make sure to initially read enough data to get past the headers + # For example, the GZ file header takes 10 bytes, we don't want to read + # it one byte at a time + data = self._raw_read(amt) + decoded_data = self._decode(data, decode_content, flush_decoder) + self._decoded_buffer.put(decoded_data) + data = self._decoded_buffer.get(amt) + + return data + + def read1( + self, + amt: int | None = None, + decode_content: bool | None = None, + ) -> bytes: + """ + Similar to ``http.client.HTTPResponse.read1`` and documented + in :meth:`io.BufferedReader.read1`, but with an additional parameter: + ``decode_content``. + + :param amt: + How much of the content to read. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + if decode_content is None: + decode_content = self.decode_content + if amt and amt < 0: + # Negative numbers and `None` should be treated the same. + amt = None + # try and respond without going to the network + if self._has_decoded_content: + if not decode_content: + raise RuntimeError( + "Calling read1(decode_content=False) is not supported after " + "read1(decode_content=True) was called." + ) + if len(self._decoded_buffer) > 0: + if amt is None: + return self._decoded_buffer.get_all() + return self._decoded_buffer.get(amt) + if amt == 0: + return b"" + + # FIXME, this method's type doesn't say returning None is possible + data = self._raw_read(amt, read1=True) + if not decode_content or data is None: + return data + + self._init_decoder() + while True: + flush_decoder = not data + decoded_data = self._decode(data, decode_content, flush_decoder) + self._decoded_buffer.put(decoded_data) + if decoded_data or flush_decoder: + break + data = self._raw_read(8192, read1=True) + + if amt is None: + return self._decoded_buffer.get_all() + return self._decoded_buffer.get(amt) + + def stream( + self, amt: int | None = 2**16, decode_content: bool | None = None + ) -> typing.Generator[bytes]: + """ + A generator wrapper for the read() method. A call will block until + ``amt`` bytes have been read from the connection or until the + connection is closed. + + :param amt: + How much of the content to read. The generator will return up to + much data per iteration, but may return less. This is particularly + likely when using compressed data. However, the empty string will + never be returned. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + if self.chunked and self.supports_chunked_reads(): + yield from self.read_chunked(amt, decode_content=decode_content) + else: + while not is_fp_closed(self._fp) or len(self._decoded_buffer) > 0: + data = self.read(amt=amt, decode_content=decode_content) + + if data: + yield data + + # Overrides from io.IOBase + def readable(self) -> bool: + return True + + def shutdown(self) -> None: + if not self._sock_shutdown: + raise ValueError("Cannot shutdown socket as self._sock_shutdown is not set") + self._sock_shutdown(socket.SHUT_RD) + + def close(self) -> None: + self._sock_shutdown = None + + if not self.closed and self._fp: + self._fp.close() + + if self._connection: + self._connection.close() + + if not self.auto_close: + io.IOBase.close(self) + + @property + def closed(self) -> bool: + if not self.auto_close: + return io.IOBase.closed.__get__(self) # type: ignore[no-any-return] + elif self._fp is None: + return True + elif hasattr(self._fp, "isclosed"): + return self._fp.isclosed() + elif hasattr(self._fp, "closed"): + return self._fp.closed + else: + return True + + def fileno(self) -> int: + if self._fp is None: + raise OSError("HTTPResponse has no file to get a fileno from") + elif hasattr(self._fp, "fileno"): + return self._fp.fileno() + else: + raise OSError( + "The file-like object this HTTPResponse is wrapped " + "around has no file descriptor" + ) + + def flush(self) -> None: + if ( + self._fp is not None + and hasattr(self._fp, "flush") + and not getattr(self._fp, "closed", False) + ): + return self._fp.flush() + + def supports_chunked_reads(self) -> bool: + """ + Checks if the underlying file-like object looks like a + :class:`http.client.HTTPResponse` object. We do this by testing for + the fp attribute. If it is present we assume it returns raw chunks as + processed by read_chunked(). + """ + return hasattr(self._fp, "fp") + + def _update_chunk_length(self) -> None: + # First, we'll figure out length of a chunk and then + # we'll try to read it from socket. + if self.chunk_left is not None: + return None + line = self._fp.fp.readline() # type: ignore[union-attr] + line = line.split(b";", 1)[0] + try: + self.chunk_left = int(line, 16) + except ValueError: + self.close() + if line: + # Invalid chunked protocol response, abort. + raise InvalidChunkLength(self, line) from None + else: + # Truncated at start of next chunk + raise ProtocolError("Response ended prematurely") from None + + def _handle_chunk(self, amt: int | None) -> bytes: + returned_chunk = None + if amt is None: + chunk = self._fp._safe_read(self.chunk_left) # type: ignore[union-attr] + returned_chunk = chunk + self._fp._safe_read(2) # type: ignore[union-attr] # Toss the CRLF at the end of the chunk. + self.chunk_left = None + elif self.chunk_left is not None and amt < self.chunk_left: + value = self._fp._safe_read(amt) # type: ignore[union-attr] + self.chunk_left = self.chunk_left - amt + returned_chunk = value + elif amt == self.chunk_left: + value = self._fp._safe_read(amt) # type: ignore[union-attr] + self._fp._safe_read(2) # type: ignore[union-attr] # Toss the CRLF at the end of the chunk. + self.chunk_left = None + returned_chunk = value + else: # amt > self.chunk_left + returned_chunk = self._fp._safe_read(self.chunk_left) # type: ignore[union-attr] + self._fp._safe_read(2) # type: ignore[union-attr] # Toss the CRLF at the end of the chunk. + self.chunk_left = None + return returned_chunk # type: ignore[no-any-return] + + def read_chunked( + self, amt: int | None = None, decode_content: bool | None = None + ) -> typing.Generator[bytes]: + """ + Similar to :meth:`HTTPResponse.read`, but with an additional + parameter: ``decode_content``. + + :param amt: + How much of the content to read. If specified, caching is skipped + because it doesn't make sense to cache partial content as the full + response. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + self._init_decoder() + # FIXME: Rewrite this method and make it a class with a better structured logic. + if not self.chunked: + raise ResponseNotChunked( + "Response is not chunked. " + "Header 'transfer-encoding: chunked' is missing." + ) + if not self.supports_chunked_reads(): + raise BodyNotHttplibCompatible( + "Body should be http.client.HTTPResponse like. " + "It should have have an fp attribute which returns raw chunks." + ) + + with self._error_catcher(): + # Don't bother reading the body of a HEAD request. + if self._original_response and is_response_to_head(self._original_response): + self._original_response.close() + return None + + # If a response is already read and closed + # then return immediately. + if self._fp.fp is None: # type: ignore[union-attr] + return None + + if amt and amt < 0: + # Negative numbers and `None` should be treated the same, + # but httplib handles only `None` correctly. + amt = None + + while True: + self._update_chunk_length() + if self.chunk_left == 0: + break + chunk = self._handle_chunk(amt) + decoded = self._decode( + chunk, decode_content=decode_content, flush_decoder=False + ) + if decoded: + yield decoded + + if decode_content: + # On CPython and PyPy, we should never need to flush the + # decoder. However, on Jython we *might* need to, so + # lets defensively do it anyway. + decoded = self._flush_decoder() + if decoded: # Platform-specific: Jython. + yield decoded + + # Chunk content ends with \r\n: discard it. + while self._fp is not None: + line = self._fp.fp.readline() + if not line: + # Some sites may not end with '\r\n'. + break + if line == b"\r\n": + break + + # We read everything; close the "file". + if self._original_response: + self._original_response.close() + + @property + def url(self) -> str | None: + """ + Returns the URL that was the source of this response. + If the request that generated this response redirected, this method + will return the final redirect location. + """ + return self._request_url + + @url.setter + def url(self, url: str) -> None: + self._request_url = url + + def __iter__(self) -> typing.Iterator[bytes]: + buffer: list[bytes] = [] + for chunk in self.stream(decode_content=True): + if b"\n" in chunk: + chunks = chunk.split(b"\n") + yield b"".join(buffer) + chunks[0] + b"\n" + for x in chunks[1:-1]: + yield x + b"\n" + if chunks[-1]: + buffer = [chunks[-1]] + else: + buffer = [] + else: + buffer.append(chunk) + if buffer: + yield b"".join(buffer) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/__init__.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/__init__.py new file mode 100644 index 000000000..534126033 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/__init__.py @@ -0,0 +1,42 @@ +# For backwards compatibility, provide imports that used to be here. +from __future__ import annotations + +from .connection import is_connection_dropped +from .request import SKIP_HEADER, SKIPPABLE_HEADERS, make_headers +from .response import is_fp_closed +from .retry import Retry +from .ssl_ import ( + ALPN_PROTOCOLS, + IS_PYOPENSSL, + SSLContext, + assert_fingerprint, + create_urllib3_context, + resolve_cert_reqs, + resolve_ssl_version, + ssl_wrap_socket, +) +from .timeout import Timeout +from .url import Url, parse_url +from .wait import wait_for_read, wait_for_write + +__all__ = ( + "IS_PYOPENSSL", + "SSLContext", + "ALPN_PROTOCOLS", + "Retry", + "Timeout", + "Url", + "assert_fingerprint", + "create_urllib3_context", + "is_connection_dropped", + "is_fp_closed", + "parse_url", + "make_headers", + "resolve_cert_reqs", + "resolve_ssl_version", + "ssl_wrap_socket", + "wait_for_read", + "wait_for_write", + "SKIP_HEADER", + "SKIPPABLE_HEADERS", +) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/__init__.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d9c47fe164e26d82efc8783432fc84753196d5b GIT binary patch literal 1025 zcmY+Czfaph6vxkT66bfw4+0cuE2<6|s8JwohpJLaBb9Rm5vD_@lW{J=im{#NODNs? zM|AJnrF;L1s_RLJp<-Y|iYnILInby#eDvP4-@EU7@22^D28r|i$IrpFiqLQA+@ILY zP^Mpn@dcU4R1Aa_P#z;QW~xREtDr`9+=$}@BybXvSOYDJC5#kKLprjPMh0gg8`+wX z!+FT#0u*o&ig*DQa0yDd3}sw_3a&ym`Y&ZH;u_Q{OSyH0XD!e3nZ+F63$K+~Y|#mc?Ry@zWtjB94+7e&t2}EOdtLIb-Fn+T zn;yNJnir`C{?6KeG+gray(6zT`WcKuM~D?D*X8JyQsywK`&_euBg;OJoY zpd%9ZOw#>u&~5LVW`}14c72c0kBpbCFr>gp-|+?%0&qOWYc^1eQ8EVCb&j{C*6807 z(9m}$l-M!@=qTis`%oCVWFl0FhImmrXJ7>+^z9*KLYa2toKkM^dq2bZS<3&Q9I z5y_ufj!@u(sA=_h;h%d34x{x7_WGTUX$`#tULYtSU p^$WEw(8dK?zKx}o*ew#6O8luJW&IL8xHw zLpu@*Snefq5Wr4=AVzvofdF+-puO~vpuGf1fL@A9kx;YKq!HlukQ-AgMc`ce{wx$N z82ys|`u*HD-XCE5ag6O9(uQDXsd?rRj z-n`o;wuk|9)-JY+L37q|xuXY(p+S(JHqu#i#iHNPX^b%flA@@(q?c4hoB76NZMIIU zIdf}HBAT2eL?z$Q+cB3B$&4n)hSSrjOlsm%ayFeZLYdUh=aSA6P_{lVY4Ug~H8-Lv zikzdUb2e>C6wx^g!-JDBc^9S8Jl#Fe94$SCP6C^&H~4v3uM$PWDN>bjsett*8Rr@V za7n{?qE;$$9!p9dYfEaioX1&!DXW^CkMoI&M5JZ&N&+WxWl7T#i&auCm$FaC_YuV( zWqc8<*;he^I1hpaOIpT;l=HB5(}hOG!3OECkkVC2m;0|uq`#n+^D@!;U(59moPVv7 z)z1$;J@DH3q1D3RpkCCoKR%l~3$3X2r}`_UN}n!~qOA8_$y`|)96Vp_2d4TfEBcbE z^xG`P6M8(3tVm*m(;0-pm|u<5}jx*S-=EwYMtfjWlS2JKPt z9jA9~FSR$#L3BHJFb^0yqQLW+CCnj@qRimXv?UC7pQX0_R{@9>Ne0YN;3;>)*PW}#?(uAzSG&+AJYvT z!X4KmdJNAW-iLE$>4qKwK0M#$?C+21hJQmO0ZpgFnhS&P1SnVDEbt9__R7q{G3Sox zbMz}S-DrVx_I-%*4LT1vJEAA;4kOX~H0#_DS=m)U7ugf2K<^%PAmQ$hK)XU(pd4g7 z5asrSbGkn|*2m}s>->a9FWwomJVlx`ax=ir3Qn`#ZV39^N`y8uE zGxH@y(Kc^Pn0^r{mDL5PV0RzMXEA`ld{YNb*x$@w!BA73o1S*eWk zazUz=fuh9?rEVg#)CM6myMhx`If+F}eQ}6R_9gqyA`i%`G_smxdo{I6a&o3&1xgxZ zD(QH+s_8TkOW4w+TELbnv8hTPBx;rw1j?2mf=e3Qu&`nqD_}9jUzV;onr#Y*{IG(l zi7*g2bqWJkiXWfFx?C=6CW%>*>I=9wSGGWL-e4A1T?;SI817PDkqqY4>XB1ta9PUA zWlZ(FLXqjJip#1}T^! zR(4eEzKK&CUQnVoE@3Uh^hJH@FgRf z0S#v?u#EM@G(rO@P^ShpUz*{j+BAH&q72`xXc93zW?}?ZeYSQDpK~Srs4)##Qy+3@ z7;dU&!%fv|ureWr*A|Bb4>Vj-!Qki(eWfBBo(fTQ)$r#e1)Nn{mJOFC8E$%RFd2LmBx*f;V{&b@<_o-W{l@j%+C5*_manTO zL~pI$T)lI0TR5@quJPfukv$%T@phaqx;SYs-L*rXR<9`z-*4bL$*)6Vj-E~{O>jJdv?z*ehf9%WX;rA}Sb8(~fZgo34 zxIVh)MIpT5-U$xw3LQJg<6j8zTBPkg;ca2Vw-Y)2PvIC{`rr27iSI;WwP57d^v&rz ztvkV^yR9ATBeiJfn^WI*qsSyvk0UN{<9glY_IK7=+t(+6aiL?gw zVy_31;1HyoOOQNi!YV?^Hv+R&&_E}lg;Eaw8Vwk>M7Ru-chN%QV7^&U zdsjgVc3pu`Ba6eEZn{Nls{>7e3d^i&f16r@IO${|vxb$mQc-~j3~}n3O0M9Nl?cFn zb@_D~+xVtcHbZgtQe6Dgq2a z)=r*^ZAGgniqDJ@s-INMYZ;MSlC(^za&^eyY;z6~`l)L8ldtDwvsxkDum-P#dJdVc zN2pIf;&FyQcVgz`lOE^POzU`V4z=R6Nz*1SZNJU{LmR*D@j8pRMm2fC-e=j3T82~ z0IB&5_?Z4Od4j^zBAA?{=N$*m@h|XtL?IDFV;ee%*|oJ?hA=TZ~1;72yZa}*+E z`=T{~+G+42BebKnFL|DJ&p~InDcYFJT&%V^E^OIt%&ZbX7-|HA1!he!G7QVuA%o9k z3RUjCeshwhDmOnt&2()AWitktFXRH8euzx}w$eQJ z%(9xVmgS!k`dvUO&3vuAYcXmYD_Y!kKZvi^H)C;Wcp9^CVKnC|*fbUa?`J6AhDRQEs2{G=8- zT4!P04IQa_V1xwG{#4yZXB=ujYr?=6vp4!(fbNaDe9ZA0-&tqr*mKbwcRl_+53Kjv aIHq;4qm60%HjaYrx6|8!t{a>w-2VW@4uM<% literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/proxy.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/proxy.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2954e30f17d7772b761fe7886209d39bd241f06f GIT binary patch literal 1245 zcmZ8gUyIvD5MTYVEh~2KVgmK0wAuDra-zv8y~HgXB`@Zh^jy@#vP%jDq4TX}C98GWgt!&A z+N^Y8nq!rXX+Ag z0LgE&ZW52fV6;5Ah$X_0x^f<&@PZ7<2%`gKsJiOzBSQRABYlB=k6cY6HV7Fi7iF}B z))!gdqYH%080c2Tzk#CJXFP{EqXWnp4abyE7#$^X%toRb3hX!!fo0T>>BGU`fOda$ zoW1SIrOC@7+BGSXFePR3C3uOw)R$!pZjMbV!=zUn z2Q4|s{?aidQ<^48H1%UYV6dIeRvTv==n>0!7)z*^jV5f$%2WfatJGHqxrE%NTj4gN z6VB7@mSndm<0H%buF!?Cs7TkqQj2Ptq-f_E^TrAM>cdeO2SW5D$kK}XMfF9a6w4Bd z)}=j{r_01`zz!8tJB9G6&zb$y2YZ}EM+`Ficx2z(IZhAxPUr5unLV)6Ful!v2pGTp#CtO7banze3J>jc#wST^;}B50Yv(+Sa1Sx6bXMGWH)L-$ zWLbd6bDVwzSMgj|@Soks<#)26#JKvZ)}F6jTU3d0{pC-uYnwtbNWFDpv|kzRmk(YW zoBuT0^G5rm@fCij65Cim#|*^M9LKQ?Xrlbg#J548QzwZTd>{-hIqI&Q^vba&kz%MN zvZ#W*tc8Av3QQEuP^gF5N#}~e3s%c3Jq(9im)^XKOgLQ-G_VK-uKRf!hBaX z)X*=h{DS~K8v^Sh!1#8W9OV(a458sVZ*Z=?k literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/request.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/request.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7f4a37d32d58bd3f42c4302d9231d0ecf7d19a5d GIT binary patch literal 8258 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 GB>X=muc?Iq literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/ssl_.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/ssl_.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05289b60c300fbad015e8e2d867737d7ee42a76a GIT binary patch literal 16653 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 literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/ssl_match_hostname.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/ssl_match_hostname.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e70769861f63771ada06b9c00ee198f73348d35 GIT binary patch literal 5751 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 literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/ssltransport.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/ssltransport.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51eeed824d2cebbc6bb94dd35e58e5700c08e363 GIT binary patch literal 13466 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 Yda}}e>U!tDwJiHQ$Np8Jk`wEH0Gw9T5&!@I literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/url.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/url.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..27efcec5c2af8fc549de02529ecf16647b33cefc GIT binary patch literal 16310 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 F{{smjBL4sY literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/util.cpython-313.pyc b/apigw-private-cdn-acm/acm-certificate/urllib3/util/__pycache__/util.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72fb8697f267cd5ddc8a4c93fb1f9fc21b20af6c GIT binary patch literal 2148 zcmeGd&u`mg^!x1iN8&o|(w24|OWhJpO;MZCHd}{SVW6$jigKvy3l)l-#7VtoPWss? zX@t5(G?*lICEcS2;Xv-=C|YC!y@53xcrUv6l?%zu}4PQUq0}(?- z7>)Uxj8#L|n8d%Fk?tLvKu27rF$`H%j5?&yF|Cr~Kr)pES96MU%Pwy_#LPR8ZQdZH zLhPjAMoinZY)7~9hRfyl9K&{5FmuDS3^%Ej8={A}Vm52(ca3ZoHe2~h!8l@FTz5r} z0arwXIBZ%sMN!;xs!GgV-7!+TI!P5P<$^)%)J{INw6IgnISc8|gngxUkemB2j=Ms9ylLDdFjz|>H%SHw$px1^(0l0j@ zpp8d{fC)N{40{@A0O(pW4h$8XDZknl&bNf~FO@&tmZw_s)PGriG766S%1_6QH@H3m z;voz}4X*=rc4^FqSU*RH!TQT%uV<$94HyGY!O*rayi5^YXD3k+AK^@rapi2*2}USf z(qvvn#-vM%FPU2az|*9;(Y{rMA!L3GnLhyq?G;kB;<8suuO=$JKdE|Aam)RraHHqJ|;yZUMg<9EIAxW^LKNBl#Jc?22d=ui-8m#;%@YxVLmLcYXKrv*HLJNOF-k4TQ>xU1v}M>z#${why- z#sf3}JaARG5~M+x6LP@}PsP&&|8h}}_tRV~C#J{^;RZ*gZ`G1~Ejbs@$tcs%x9W#H z{f%%gkxS;nzIBB4B7QGg<98x< zR%y)@*xd!$BCdp{R^4$$T3Xd$R=nwPzGA`{s@{e%pWkBK#^6x8%{4MLs&A@}mf2Kk zreYaojoO)wQf6j)qqgEq&z_&zn7(kQGCS*3ot2B{O6QsU-D86pl7id zP{6ByA^tZ}kmF6EF9Ke}2q=K}cx|aa;{3760RoZJi!k+7n9Wnj4Rw>Y2G{{ibjG81Z+VWfGNb6gq4qP23v z#yyn=Jps&>%2p94-0!mKSNv>h&ag_VVPBf^)vkbztpNF^L0XaM_IxWEyFak~?$+C_ z#EE-%x9{%!d@nKDlt=07pp+Kq2(TB?ieaga@{y8-@Pv!a6r6g^&zYYWrc~oRYqK%)jpo%^eAIBcVcIA;RfrS+g z#2>_W<FRks=*8|5fye- z$SA1>Dr7z|N-A7h$TC-5UVuBrtMP6k{E^&(X6my#zmd4oHKvWidFg|Jv)1-}=p4zn$NbTXK?RE%g)mWLqZ5fo~2a z5*z;g!DsU&pJM~!w zC+X#d4SsRBfNsNDp_?TDMIZgH9qdqGk0?~#;Cof}I(Pj$ojS_u9s@5evZFI+a}%$` zoGY!WwhFj&t)(utaX32p!p6$K+q+(Hp!d7H&A{J6!aItt`ca0}~O4xb4TqMt} zTjjc;U80!kF-h5f2Lic-<31zfUy|70NbEB*@h literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/connection.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/connection.py new file mode 100644 index 000000000..f92519ee9 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/connection.py @@ -0,0 +1,137 @@ +from __future__ import annotations + +import socket +import typing + +from ..exceptions import LocationParseError +from .timeout import _DEFAULT_TIMEOUT, _TYPE_TIMEOUT + +_TYPE_SOCKET_OPTIONS = list[tuple[int, int, typing.Union[int, bytes]]] + +if typing.TYPE_CHECKING: + from .._base_connection import BaseHTTPConnection + + +def is_connection_dropped(conn: BaseHTTPConnection) -> bool: # Platform-specific + """ + Returns True if the connection is dropped and should be closed. + :param conn: :class:`urllib3.connection.HTTPConnection` object. + """ + return not conn.is_connected + + +# This function is copied from socket.py in the Python 2.7 standard +# library test suite. Added to its signature is only `socket_options`. +# One additional modification is that we avoid binding to IPv6 servers +# discovered in DNS if the system doesn't have IPv6 functionality. +def create_connection( + address: tuple[str, int], + timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, + source_address: tuple[str, int] | None = None, + socket_options: _TYPE_SOCKET_OPTIONS | None = None, +) -> socket.socket: + """Connect to *address* and return the socket object. + + Convenience function. Connect to *address* (a 2-tuple ``(host, + port)``) and return the socket object. Passing the optional + *timeout* parameter will set the timeout on the socket instance + before attempting to connect. If no *timeout* is supplied, the + global default timeout setting returned by :func:`socket.getdefaulttimeout` + is used. If *source_address* is set it must be a tuple of (host, port) + for the socket to bind as a source address before making the connection. + An host of '' or port 0 tells the OS to use the default. + """ + + host, port = address + if host.startswith("["): + host = host.strip("[]") + err = None + + # Using the value from allowed_gai_family() in the context of getaddrinfo lets + # us select whether to work with IPv4 DNS records, IPv6 records, or both. + # The original create_connection function always returns all records. + family = allowed_gai_family() + + try: + host.encode("idna") + except UnicodeError: + raise LocationParseError(f"'{host}', label empty or too long") from None + + for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): + af, socktype, proto, canonname, sa = res + sock = None + try: + sock = socket.socket(af, socktype, proto) + + # If provided, set socket level options before connecting. + _set_socket_options(sock, socket_options) + + if timeout is not _DEFAULT_TIMEOUT: + sock.settimeout(timeout) + if source_address: + sock.bind(source_address) + sock.connect(sa) + # Break explicitly a reference cycle + err = None + return sock + + except OSError as _: + err = _ + if sock is not None: + sock.close() + + if err is not None: + try: + raise err + finally: + # Break explicitly a reference cycle + err = None + else: + raise OSError("getaddrinfo returns an empty list") + + +def _set_socket_options( + sock: socket.socket, options: _TYPE_SOCKET_OPTIONS | None +) -> None: + if options is None: + return + + for opt in options: + sock.setsockopt(*opt) + + +def allowed_gai_family() -> socket.AddressFamily: + """This function is designed to work in the context of + getaddrinfo, where family=socket.AF_UNSPEC is the default and + will perform a DNS search for both IPv6 and IPv4 records.""" + + family = socket.AF_INET + if HAS_IPV6: + family = socket.AF_UNSPEC + return family + + +def _has_ipv6(host: str) -> bool: + """Returns True if the system can bind an IPv6 address.""" + sock = None + has_ipv6 = False + + if socket.has_ipv6: + # has_ipv6 returns true if cPython was compiled with IPv6 support. + # It does not tell us if the system has IPv6 support enabled. To + # determine that we must bind to an IPv6 address. + # https://github.com/urllib3/urllib3/pull/611 + # https://bugs.python.org/issue658327 + try: + sock = socket.socket(socket.AF_INET6) + sock.bind((host, 0)) + has_ipv6 = True + except Exception: + pass + + if sock: + sock.close() + return has_ipv6 + + +HAS_IPV6 = _has_ipv6("::1") diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/proxy.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/proxy.py new file mode 100644 index 000000000..908fc6621 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/proxy.py @@ -0,0 +1,43 @@ +from __future__ import annotations + +import typing + +from .url import Url + +if typing.TYPE_CHECKING: + from ..connection import ProxyConfig + + +def connection_requires_http_tunnel( + proxy_url: Url | None = None, + proxy_config: ProxyConfig | None = None, + destination_scheme: str | None = None, +) -> bool: + """ + Returns True if the connection requires an HTTP CONNECT through the proxy. + + :param URL proxy_url: + URL of the proxy. + :param ProxyConfig proxy_config: + Proxy configuration from poolmanager.py + :param str destination_scheme: + The scheme of the destination. (i.e https, http, etc) + """ + # If we're not using a proxy, no way to use a tunnel. + if proxy_url is None: + return False + + # HTTP destinations never require tunneling, we always forward. + if destination_scheme == "http": + return False + + # Support for forwarding with HTTPS proxies and HTTPS destinations. + if ( + proxy_url.scheme == "https" + and proxy_config + and proxy_config.use_forwarding_for_https + ): + return False + + # Otherwise always use a tunnel. + return True diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/request.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/request.py new file mode 100644 index 000000000..94392a13b --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/request.py @@ -0,0 +1,258 @@ +from __future__ import annotations + +import io +import typing +from base64 import b64encode +from enum import Enum + +from ..exceptions import UnrewindableBodyError +from .util import to_bytes + +if typing.TYPE_CHECKING: + from typing import Final + +# Pass as a value within ``headers`` to skip +# emitting some HTTP headers that are added automatically. +# The only headers that are supported are ``Accept-Encoding``, +# ``Host``, and ``User-Agent``. +SKIP_HEADER = "@@@SKIP_HEADER@@@" +SKIPPABLE_HEADERS = frozenset(["accept-encoding", "host", "user-agent"]) + +ACCEPT_ENCODING = "gzip,deflate" +try: + try: + import brotlicffi as _unused_module_brotli # type: ignore[import-not-found] # noqa: F401 + except ImportError: + import brotli as _unused_module_brotli # type: ignore[import-not-found] # noqa: F401 +except ImportError: + pass +else: + ACCEPT_ENCODING += ",br" +try: + import zstandard as _unused_module_zstd # noqa: F401 +except ImportError: + pass +else: + ACCEPT_ENCODING += ",zstd" + + +class _TYPE_FAILEDTELL(Enum): + token = 0 + + +_FAILEDTELL: Final[_TYPE_FAILEDTELL] = _TYPE_FAILEDTELL.token + +_TYPE_BODY_POSITION = typing.Union[int, _TYPE_FAILEDTELL] + +# When sending a request with these methods we aren't expecting +# a body so don't need to set an explicit 'Content-Length: 0' +# The reason we do this in the negative instead of tracking methods +# which 'should' have a body is because unknown methods should be +# treated as if they were 'POST' which *does* expect a body. +_METHODS_NOT_EXPECTING_BODY = {"GET", "HEAD", "DELETE", "TRACE", "OPTIONS", "CONNECT"} + + +def make_headers( + keep_alive: bool | None = None, + accept_encoding: bool | list[str] | str | None = None, + user_agent: str | None = None, + basic_auth: str | None = None, + proxy_basic_auth: str | None = None, + disable_cache: bool | None = None, +) -> dict[str, str]: + """ + Shortcuts for generating request headers. + + :param keep_alive: + If ``True``, adds 'connection: keep-alive' header. + + :param accept_encoding: + Can be a boolean, list, or string. + ``True`` translates to 'gzip,deflate'. If the dependencies for + Brotli (either the ``brotli`` or ``brotlicffi`` package) and/or Zstandard + (the ``zstandard`` package) algorithms are installed, then their encodings are + included in the string ('br' and 'zstd', respectively). + List will get joined by comma. + String will be used as provided. + + :param user_agent: + String representing the user-agent you want, such as + "python-urllib3/0.6" + + :param basic_auth: + Colon-separated username:password string for 'authorization: basic ...' + auth header. + + :param proxy_basic_auth: + Colon-separated username:password string for 'proxy-authorization: basic ...' + auth header. + + :param disable_cache: + If ``True``, adds 'cache-control: no-cache' header. + + Example: + + .. code-block:: python + + import urllib3 + + print(urllib3.util.make_headers(keep_alive=True, user_agent="Batman/1.0")) + # {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'} + print(urllib3.util.make_headers(accept_encoding=True)) + # {'accept-encoding': 'gzip,deflate'} + """ + headers: dict[str, str] = {} + if accept_encoding: + if isinstance(accept_encoding, str): + pass + elif isinstance(accept_encoding, list): + accept_encoding = ",".join(accept_encoding) + else: + accept_encoding = ACCEPT_ENCODING + headers["accept-encoding"] = accept_encoding + + if user_agent: + headers["user-agent"] = user_agent + + if keep_alive: + headers["connection"] = "keep-alive" + + if basic_auth: + headers["authorization"] = ( + f"Basic {b64encode(basic_auth.encode('latin-1')).decode()}" + ) + + if proxy_basic_auth: + headers["proxy-authorization"] = ( + f"Basic {b64encode(proxy_basic_auth.encode('latin-1')).decode()}" + ) + + if disable_cache: + headers["cache-control"] = "no-cache" + + return headers + + +def set_file_position( + body: typing.Any, pos: _TYPE_BODY_POSITION | None +) -> _TYPE_BODY_POSITION | None: + """ + If a position is provided, move file to that point. + Otherwise, we'll attempt to record a position for future use. + """ + if pos is not None: + rewind_body(body, pos) + elif getattr(body, "tell", None) is not None: + try: + pos = body.tell() + except OSError: + # This differentiates from None, allowing us to catch + # a failed `tell()` later when trying to rewind the body. + pos = _FAILEDTELL + + return pos + + +def rewind_body(body: typing.IO[typing.AnyStr], body_pos: _TYPE_BODY_POSITION) -> None: + """ + Attempt to rewind body to a certain position. + Primarily used for request redirects and retries. + + :param body: + File-like object that supports seek. + + :param int pos: + Position to seek to in file. + """ + body_seek = getattr(body, "seek", None) + if body_seek is not None and isinstance(body_pos, int): + try: + body_seek(body_pos) + except OSError as e: + raise UnrewindableBodyError( + "An error occurred when rewinding request body for redirect/retry." + ) from e + elif body_pos is _FAILEDTELL: + raise UnrewindableBodyError( + "Unable to record file position for rewinding " + "request body during a redirect/retry." + ) + else: + raise ValueError( + f"body_pos must be of type integer, instead it was {type(body_pos)}." + ) + + +class ChunksAndContentLength(typing.NamedTuple): + chunks: typing.Iterable[bytes] | None + content_length: int | None + + +def body_to_chunks( + body: typing.Any | None, method: str, blocksize: int +) -> ChunksAndContentLength: + """Takes the HTTP request method, body, and blocksize and + transforms them into an iterable of chunks to pass to + socket.sendall() and an optional 'Content-Length' header. + + A 'Content-Length' of 'None' indicates the length of the body + can't be determined so should use 'Transfer-Encoding: chunked' + for framing instead. + """ + + chunks: typing.Iterable[bytes] | None + content_length: int | None + + # No body, we need to make a recommendation on 'Content-Length' + # based on whether that request method is expected to have + # a body or not. + if body is None: + chunks = None + if method.upper() not in _METHODS_NOT_EXPECTING_BODY: + content_length = 0 + else: + content_length = None + + # Bytes or strings become bytes + elif isinstance(body, (str, bytes)): + chunks = (to_bytes(body),) + content_length = len(chunks[0]) + + # File-like object, TODO: use seek() and tell() for length? + elif hasattr(body, "read"): + + def chunk_readable() -> typing.Iterable[bytes]: + nonlocal body, blocksize + encode = isinstance(body, io.TextIOBase) + while True: + datablock = body.read(blocksize) + if not datablock: + break + if encode: + datablock = datablock.encode("utf-8") + yield datablock + + chunks = chunk_readable() + content_length = None + + # Otherwise we need to start checking via duck-typing. + else: + try: + # Check if the body implements the buffer API. + mv = memoryview(body) + except TypeError: + try: + # Check if the body is an iterable + chunks = iter(body) + content_length = None + except TypeError: + raise TypeError( + f"'body' must be a bytes-like object, file-like " + f"object, or iterable. Instead was {body!r}" + ) from None + else: + # Since it implements the buffer API can be passed directly to socket.sendall() + chunks = (body,) + content_length = mv.nbytes + + return ChunksAndContentLength(chunks=chunks, content_length=content_length) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/response.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/response.py new file mode 100644 index 000000000..0f4578696 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/response.py @@ -0,0 +1,101 @@ +from __future__ import annotations + +import http.client as httplib +from email.errors import MultipartInvariantViolationDefect, StartBoundaryNotFoundDefect + +from ..exceptions import HeaderParsingError + + +def is_fp_closed(obj: object) -> bool: + """ + Checks whether a given file-like object is closed. + + :param obj: + The file-like object to check. + """ + + try: + # Check `isclosed()` first, in case Python3 doesn't set `closed`. + # GH Issue #928 + return obj.isclosed() # type: ignore[no-any-return, attr-defined] + except AttributeError: + pass + + try: + # Check via the official file-like-object way. + return obj.closed # type: ignore[no-any-return, attr-defined] + except AttributeError: + pass + + try: + # Check if the object is a container for another file-like object that + # gets released on exhaustion (e.g. HTTPResponse). + return obj.fp is None # type: ignore[attr-defined] + except AttributeError: + pass + + raise ValueError("Unable to determine whether fp is closed.") + + +def assert_header_parsing(headers: httplib.HTTPMessage) -> None: + """ + Asserts whether all headers have been successfully parsed. + Extracts encountered errors from the result of parsing headers. + + Only works on Python 3. + + :param http.client.HTTPMessage headers: Headers to verify. + + :raises urllib3.exceptions.HeaderParsingError: + If parsing errors are found. + """ + + # This will fail silently if we pass in the wrong kind of parameter. + # To make debugging easier add an explicit check. + if not isinstance(headers, httplib.HTTPMessage): + raise TypeError(f"expected httplib.Message, got {type(headers)}.") + + unparsed_data = None + + # get_payload is actually email.message.Message.get_payload; + # we're only interested in the result if it's not a multipart message + if not headers.is_multipart(): + payload = headers.get_payload() + + if isinstance(payload, (bytes, str)): + unparsed_data = payload + + # httplib is assuming a response body is available + # when parsing headers even when httplib only sends + # header data to parse_headers() This results in + # defects on multipart responses in particular. + # See: https://github.com/urllib3/urllib3/issues/800 + + # So we ignore the following defects: + # - StartBoundaryNotFoundDefect: + # The claimed start boundary was never found. + # - MultipartInvariantViolationDefect: + # A message claimed to be a multipart but no subparts were found. + defects = [ + defect + for defect in headers.defects + if not isinstance( + defect, (StartBoundaryNotFoundDefect, MultipartInvariantViolationDefect) + ) + ] + + if defects or unparsed_data: + raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data) + + +def is_response_to_head(response: httplib.HTTPResponse) -> bool: + """ + Checks whether the request of a response has been a HEAD-request. + + :param http.client.HTTPResponse response: + Response to check if the originating request + used 'HEAD' as a method. + """ + # FIXME: Can we do this somehow without accessing private httplib _method? + method_str = response._method # type: str # type: ignore[attr-defined] + return method_str.upper() == "HEAD" diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/retry.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/retry.py new file mode 100644 index 000000000..0456cceba --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/retry.py @@ -0,0 +1,533 @@ +from __future__ import annotations + +import email +import logging +import random +import re +import time +import typing +from itertools import takewhile +from types import TracebackType + +from ..exceptions import ( + ConnectTimeoutError, + InvalidHeader, + MaxRetryError, + ProtocolError, + ProxyError, + ReadTimeoutError, + ResponseError, +) +from .util import reraise + +if typing.TYPE_CHECKING: + from typing_extensions import Self + + from ..connectionpool import ConnectionPool + from ..response import BaseHTTPResponse + +log = logging.getLogger(__name__) + + +# Data structure for representing the metadata of requests that result in a retry. +class RequestHistory(typing.NamedTuple): + method: str | None + url: str | None + error: Exception | None + status: int | None + redirect_location: str | None + + +class Retry: + """Retry configuration. + + Each retry attempt will create a new Retry object with updated values, so + they can be safely reused. + + Retries can be defined as a default for a pool: + + .. code-block:: python + + retries = Retry(connect=5, read=2, redirect=5) + http = PoolManager(retries=retries) + response = http.request("GET", "https://example.com/") + + Or per-request (which overrides the default for the pool): + + .. code-block:: python + + response = http.request("GET", "https://example.com/", retries=Retry(10)) + + Retries can be disabled by passing ``False``: + + .. code-block:: python + + response = http.request("GET", "https://example.com/", retries=False) + + Errors will be wrapped in :class:`~urllib3.exceptions.MaxRetryError` unless + retries are disabled, in which case the causing exception will be raised. + + :param int total: + Total number of retries to allow. Takes precedence over other counts. + + Set to ``None`` to remove this constraint and fall back on other + counts. + + Set to ``0`` to fail on the first retry. + + Set to ``False`` to disable and imply ``raise_on_redirect=False``. + + :param int connect: + How many connection-related errors to retry on. + + These are errors raised before the request is sent to the remote server, + which we assume has not triggered the server to process the request. + + Set to ``0`` to fail on the first retry of this type. + + :param int read: + How many times to retry on read errors. + + These errors are raised after the request was sent to the server, so the + request may have side-effects. + + Set to ``0`` to fail on the first retry of this type. + + :param int redirect: + How many redirects to perform. Limit this to avoid infinite redirect + loops. + + A redirect is a HTTP response with a status code 301, 302, 303, 307 or + 308. + + Set to ``0`` to fail on the first retry of this type. + + Set to ``False`` to disable and imply ``raise_on_redirect=False``. + + :param int status: + How many times to retry on bad status codes. + + These are retries made on responses, where status code matches + ``status_forcelist``. + + Set to ``0`` to fail on the first retry of this type. + + :param int other: + How many times to retry on other errors. + + Other errors are errors that are not connect, read, redirect or status errors. + These errors might be raised after the request was sent to the server, so the + request might have side-effects. + + Set to ``0`` to fail on the first retry of this type. + + If ``total`` is not set, it's a good idea to set this to 0 to account + for unexpected edge cases and avoid infinite retry loops. + + :param Collection allowed_methods: + Set of uppercased HTTP method verbs that we should retry on. + + By default, we only retry on methods which are considered to be + idempotent (multiple requests with the same parameters end with the + same state). See :attr:`Retry.DEFAULT_ALLOWED_METHODS`. + + Set to a ``None`` value to retry on any verb. + + :param Collection status_forcelist: + A set of integer HTTP status codes that we should force a retry on. + A retry is initiated if the request method is in ``allowed_methods`` + and the response status code is in ``status_forcelist``. + + By default, this is disabled with ``None``. + + :param float backoff_factor: + A backoff factor to apply between attempts after the second try + (most errors are resolved immediately by a second try without a + delay). urllib3 will sleep for:: + + {backoff factor} * (2 ** ({number of previous retries})) + + seconds. If `backoff_jitter` is non-zero, this sleep is extended by:: + + random.uniform(0, {backoff jitter}) + + seconds. For example, if the backoff_factor is 0.1, then :func:`Retry.sleep` will + sleep for [0.0s, 0.2s, 0.4s, 0.8s, ...] between retries. No backoff will ever + be longer than `backoff_max`. + + By default, backoff is disabled (factor set to 0). + + :param bool raise_on_redirect: Whether, if the number of redirects is + exhausted, to raise a MaxRetryError, or to return a response with a + response code in the 3xx range. + + :param bool raise_on_status: Similar meaning to ``raise_on_redirect``: + whether we should raise an exception, or return a response, + if status falls in ``status_forcelist`` range and retries have + been exhausted. + + :param tuple history: The history of the request encountered during + each call to :meth:`~Retry.increment`. The list is in the order + the requests occurred. Each list item is of class :class:`RequestHistory`. + + :param bool respect_retry_after_header: + Whether to respect Retry-After header on status codes defined as + :attr:`Retry.RETRY_AFTER_STATUS_CODES` or not. + + :param Collection remove_headers_on_redirect: + Sequence of headers to remove from the request when a response + indicating a redirect is returned before firing off the redirected + request. + """ + + #: Default methods to be used for ``allowed_methods`` + DEFAULT_ALLOWED_METHODS = frozenset( + ["HEAD", "GET", "PUT", "DELETE", "OPTIONS", "TRACE"] + ) + + #: Default status codes to be used for ``status_forcelist`` + RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]) + + #: Default headers to be used for ``remove_headers_on_redirect`` + DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset( + ["Cookie", "Authorization", "Proxy-Authorization"] + ) + + #: Default maximum backoff time. + DEFAULT_BACKOFF_MAX = 120 + + # Backward compatibility; assigned outside of the class. + DEFAULT: typing.ClassVar[Retry] + + def __init__( + self, + total: bool | int | None = 10, + connect: int | None = None, + read: int | None = None, + redirect: bool | int | None = None, + status: int | None = None, + other: int | None = None, + allowed_methods: typing.Collection[str] | None = DEFAULT_ALLOWED_METHODS, + status_forcelist: typing.Collection[int] | None = None, + backoff_factor: float = 0, + backoff_max: float = DEFAULT_BACKOFF_MAX, + raise_on_redirect: bool = True, + raise_on_status: bool = True, + history: tuple[RequestHistory, ...] | None = None, + respect_retry_after_header: bool = True, + remove_headers_on_redirect: typing.Collection[ + str + ] = DEFAULT_REMOVE_HEADERS_ON_REDIRECT, + backoff_jitter: float = 0.0, + ) -> None: + self.total = total + self.connect = connect + self.read = read + self.status = status + self.other = other + + if redirect is False or total is False: + redirect = 0 + raise_on_redirect = False + + self.redirect = redirect + self.status_forcelist = status_forcelist or set() + self.allowed_methods = allowed_methods + self.backoff_factor = backoff_factor + self.backoff_max = backoff_max + self.raise_on_redirect = raise_on_redirect + self.raise_on_status = raise_on_status + self.history = history or () + self.respect_retry_after_header = respect_retry_after_header + self.remove_headers_on_redirect = frozenset( + h.lower() for h in remove_headers_on_redirect + ) + self.backoff_jitter = backoff_jitter + + def new(self, **kw: typing.Any) -> Self: + params = dict( + total=self.total, + connect=self.connect, + read=self.read, + redirect=self.redirect, + status=self.status, + other=self.other, + allowed_methods=self.allowed_methods, + status_forcelist=self.status_forcelist, + backoff_factor=self.backoff_factor, + backoff_max=self.backoff_max, + raise_on_redirect=self.raise_on_redirect, + raise_on_status=self.raise_on_status, + history=self.history, + remove_headers_on_redirect=self.remove_headers_on_redirect, + respect_retry_after_header=self.respect_retry_after_header, + backoff_jitter=self.backoff_jitter, + ) + + params.update(kw) + return type(self)(**params) # type: ignore[arg-type] + + @classmethod + def from_int( + cls, + retries: Retry | bool | int | None, + redirect: bool | int | None = True, + default: Retry | bool | int | None = None, + ) -> Retry: + """Backwards-compatibility for the old retries format.""" + if retries is None: + retries = default if default is not None else cls.DEFAULT + + if isinstance(retries, Retry): + return retries + + redirect = bool(redirect) and None + new_retries = cls(retries, redirect=redirect) + log.debug("Converted retries value: %r -> %r", retries, new_retries) + return new_retries + + def get_backoff_time(self) -> float: + """Formula for computing the current backoff + + :rtype: float + """ + # We want to consider only the last consecutive errors sequence (Ignore redirects). + consecutive_errors_len = len( + list( + takewhile(lambda x: x.redirect_location is None, reversed(self.history)) + ) + ) + if consecutive_errors_len <= 1: + return 0 + + backoff_value = self.backoff_factor * (2 ** (consecutive_errors_len - 1)) + if self.backoff_jitter != 0.0: + backoff_value += random.random() * self.backoff_jitter + return float(max(0, min(self.backoff_max, backoff_value))) + + def parse_retry_after(self, retry_after: str) -> float: + seconds: float + # Whitespace: https://tools.ietf.org/html/rfc7230#section-3.2.4 + if re.match(r"^\s*[0-9]+\s*$", retry_after): + seconds = int(retry_after) + else: + retry_date_tuple = email.utils.parsedate_tz(retry_after) + if retry_date_tuple is None: + raise InvalidHeader(f"Invalid Retry-After header: {retry_after}") + + retry_date = email.utils.mktime_tz(retry_date_tuple) + seconds = retry_date - time.time() + + seconds = max(seconds, 0) + + return seconds + + def get_retry_after(self, response: BaseHTTPResponse) -> float | None: + """Get the value of Retry-After in seconds.""" + + retry_after = response.headers.get("Retry-After") + + if retry_after is None: + return None + + return self.parse_retry_after(retry_after) + + def sleep_for_retry(self, response: BaseHTTPResponse) -> bool: + retry_after = self.get_retry_after(response) + if retry_after: + time.sleep(retry_after) + return True + + return False + + def _sleep_backoff(self) -> None: + backoff = self.get_backoff_time() + if backoff <= 0: + return + time.sleep(backoff) + + def sleep(self, response: BaseHTTPResponse | None = None) -> None: + """Sleep between retry attempts. + + This method will respect a server's ``Retry-After`` response header + and sleep the duration of the time requested. If that is not present, it + will use an exponential backoff. By default, the backoff factor is 0 and + this method will return immediately. + """ + + if self.respect_retry_after_header and response: + slept = self.sleep_for_retry(response) + if slept: + return + + self._sleep_backoff() + + def _is_connection_error(self, err: Exception) -> bool: + """Errors when we're fairly sure that the server did not receive the + request, so it should be safe to retry. + """ + if isinstance(err, ProxyError): + err = err.original_error + return isinstance(err, ConnectTimeoutError) + + def _is_read_error(self, err: Exception) -> bool: + """Errors that occur after the request has been started, so we should + assume that the server began processing it. + """ + return isinstance(err, (ReadTimeoutError, ProtocolError)) + + def _is_method_retryable(self, method: str) -> bool: + """Checks if a given HTTP method should be retried upon, depending if + it is included in the allowed_methods + """ + if self.allowed_methods and method.upper() not in self.allowed_methods: + return False + return True + + def is_retry( + self, method: str, status_code: int, has_retry_after: bool = False + ) -> bool: + """Is this method/status code retryable? (Based on allowlists and control + variables such as the number of total retries to allow, whether to + respect the Retry-After header, whether this header is present, and + whether the returned status code is on the list of status codes to + be retried upon on the presence of the aforementioned header) + """ + if not self._is_method_retryable(method): + return False + + if self.status_forcelist and status_code in self.status_forcelist: + return True + + return bool( + self.total + and self.respect_retry_after_header + and has_retry_after + and (status_code in self.RETRY_AFTER_STATUS_CODES) + ) + + def is_exhausted(self) -> bool: + """Are we out of retries?""" + retry_counts = [ + x + for x in ( + self.total, + self.connect, + self.read, + self.redirect, + self.status, + self.other, + ) + if x + ] + if not retry_counts: + return False + + return min(retry_counts) < 0 + + def increment( + self, + method: str | None = None, + url: str | None = None, + response: BaseHTTPResponse | None = None, + error: Exception | None = None, + _pool: ConnectionPool | None = None, + _stacktrace: TracebackType | None = None, + ) -> Self: + """Return a new Retry object with incremented retry counters. + + :param response: A response object, or None, if the server did not + return a response. + :type response: :class:`~urllib3.response.BaseHTTPResponse` + :param Exception error: An error encountered during the request, or + None if the response was received successfully. + + :return: A new ``Retry`` object. + """ + if self.total is False and error: + # Disabled, indicate to re-raise the error. + raise reraise(type(error), error, _stacktrace) + + total = self.total + if total is not None: + total -= 1 + + connect = self.connect + read = self.read + redirect = self.redirect + status_count = self.status + other = self.other + cause = "unknown" + status = None + redirect_location = None + + if error and self._is_connection_error(error): + # Connect retry? + if connect is False: + raise reraise(type(error), error, _stacktrace) + elif connect is not None: + connect -= 1 + + elif error and self._is_read_error(error): + # Read retry? + if read is False or method is None or not self._is_method_retryable(method): + raise reraise(type(error), error, _stacktrace) + elif read is not None: + read -= 1 + + elif error: + # Other retry? + if other is not None: + other -= 1 + + elif response and response.get_redirect_location(): + # Redirect retry? + if redirect is not None: + redirect -= 1 + cause = "too many redirects" + response_redirect_location = response.get_redirect_location() + if response_redirect_location: + redirect_location = response_redirect_location + status = response.status + + else: + # Incrementing because of a server error like a 500 in + # status_forcelist and the given method is in the allowed_methods + cause = ResponseError.GENERIC_ERROR + if response and response.status: + if status_count is not None: + status_count -= 1 + cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) + status = response.status + + history = self.history + ( + RequestHistory(method, url, error, status, redirect_location), + ) + + new_retry = self.new( + total=total, + connect=connect, + read=read, + redirect=redirect, + status=status_count, + other=other, + history=history, + ) + + if new_retry.is_exhausted(): + reason = error or ResponseError(cause) + raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] + + log.debug("Incremented Retry for (url='%s'): %r", url, new_retry) + + return new_retry + + def __repr__(self) -> str: + return ( + f"{type(self).__name__}(total={self.total}, connect={self.connect}, " + f"read={self.read}, redirect={self.redirect}, status={self.status})" + ) + + +# For backwards compatibility (equivalent to pre-v1.9): +Retry.DEFAULT = Retry(3) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/ssl_.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/ssl_.py new file mode 100644 index 000000000..278128ebd --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/ssl_.py @@ -0,0 +1,504 @@ +from __future__ import annotations + +import hashlib +import hmac +import os +import socket +import sys +import typing +import warnings +from binascii import unhexlify + +from ..exceptions import ProxySchemeUnsupported, SSLError +from .url import _BRACELESS_IPV6_ADDRZ_RE, _IPV4_RE + +SSLContext = None +SSLTransport = None +HAS_NEVER_CHECK_COMMON_NAME = False +IS_PYOPENSSL = False +ALPN_PROTOCOLS = ["http/1.1"] + +_TYPE_VERSION_INFO = tuple[int, int, int, str, int] + +# Maps the length of a digest to a possible hash function producing this digest +HASHFUNC_MAP = { + length: getattr(hashlib, algorithm, None) + for length, algorithm in ((32, "md5"), (40, "sha1"), (64, "sha256")) +} + + +def _is_bpo_43522_fixed( + implementation_name: str, + version_info: _TYPE_VERSION_INFO, + pypy_version_info: _TYPE_VERSION_INFO | None, +) -> bool: + """Return True for CPython 3.9.3+ or 3.10+ and PyPy 7.3.8+ where + setting SSLContext.hostname_checks_common_name to False works. + + Outside of CPython and PyPy we don't know which implementations work + or not so we conservatively use our hostname matching as we know that works + on all implementations. + + https://github.com/urllib3/urllib3/issues/2192#issuecomment-821832963 + https://foss.heptapod.net/pypy/pypy/-/issues/3539 + """ + if implementation_name == "pypy": + # https://foss.heptapod.net/pypy/pypy/-/issues/3129 + return pypy_version_info >= (7, 3, 8) # type: ignore[operator] + elif implementation_name == "cpython": + major_minor = version_info[:2] + micro = version_info[2] + return (major_minor == (3, 9) and micro >= 3) or major_minor >= (3, 10) + else: # Defensive: + return False + + +def _is_has_never_check_common_name_reliable( + openssl_version: str, + openssl_version_number: int, + implementation_name: str, + version_info: _TYPE_VERSION_INFO, + pypy_version_info: _TYPE_VERSION_INFO | None, +) -> bool: + # As of May 2023, all released versions of LibreSSL fail to reject certificates with + # only common names, see https://github.com/urllib3/urllib3/pull/3024 + is_openssl = openssl_version.startswith("OpenSSL ") + # Before fixing OpenSSL issue #14579, the SSL_new() API was not copying hostflags + # like X509_CHECK_FLAG_NEVER_CHECK_SUBJECT, which tripped up CPython. + # https://github.com/openssl/openssl/issues/14579 + # This was released in OpenSSL 1.1.1l+ (>=0x101010cf) + is_openssl_issue_14579_fixed = openssl_version_number >= 0x101010CF + + return is_openssl and ( + is_openssl_issue_14579_fixed + or _is_bpo_43522_fixed(implementation_name, version_info, pypy_version_info) + ) + + +if typing.TYPE_CHECKING: + from ssl import VerifyMode + from typing import TypedDict + + from .ssltransport import SSLTransport as SSLTransportType + + class _TYPE_PEER_CERT_RET_DICT(TypedDict, total=False): + subjectAltName: tuple[tuple[str, str], ...] + subject: tuple[tuple[tuple[str, str], ...], ...] + serialNumber: str + + +# Mapping from 'ssl.PROTOCOL_TLSX' to 'TLSVersion.X' +_SSL_VERSION_TO_TLS_VERSION: dict[int, int] = {} + +try: # Do we have ssl at all? + import ssl + from ssl import ( # type: ignore[assignment] + CERT_REQUIRED, + HAS_NEVER_CHECK_COMMON_NAME, + OP_NO_COMPRESSION, + OP_NO_TICKET, + OPENSSL_VERSION, + OPENSSL_VERSION_NUMBER, + PROTOCOL_TLS, + PROTOCOL_TLS_CLIENT, + OP_NO_SSLv2, + OP_NO_SSLv3, + SSLContext, + TLSVersion, + ) + + PROTOCOL_SSLv23 = PROTOCOL_TLS + + # Setting SSLContext.hostname_checks_common_name = False didn't work before CPython + # 3.9.3, and 3.10 (but OK on PyPy) or OpenSSL 1.1.1l+ + if HAS_NEVER_CHECK_COMMON_NAME and not _is_has_never_check_common_name_reliable( + OPENSSL_VERSION, + OPENSSL_VERSION_NUMBER, + sys.implementation.name, + sys.version_info, + sys.pypy_version_info if sys.implementation.name == "pypy" else None, # type: ignore[attr-defined] + ): + HAS_NEVER_CHECK_COMMON_NAME = False + + # Need to be careful here in case old TLS versions get + # removed in future 'ssl' module implementations. + for attr in ("TLSv1", "TLSv1_1", "TLSv1_2"): + try: + _SSL_VERSION_TO_TLS_VERSION[getattr(ssl, f"PROTOCOL_{attr}")] = getattr( + TLSVersion, attr + ) + except AttributeError: # Defensive: + continue + + from .ssltransport import SSLTransport # type: ignore[assignment] +except ImportError: + OP_NO_COMPRESSION = 0x20000 # type: ignore[assignment] + OP_NO_TICKET = 0x4000 # type: ignore[assignment] + OP_NO_SSLv2 = 0x1000000 # type: ignore[assignment] + OP_NO_SSLv3 = 0x2000000 # type: ignore[assignment] + PROTOCOL_SSLv23 = PROTOCOL_TLS = 2 # type: ignore[assignment] + PROTOCOL_TLS_CLIENT = 16 # type: ignore[assignment] + + +_TYPE_PEER_CERT_RET = typing.Union["_TYPE_PEER_CERT_RET_DICT", bytes, None] + + +def assert_fingerprint(cert: bytes | None, fingerprint: str) -> None: + """ + Checks if given fingerprint matches the supplied certificate. + + :param cert: + Certificate as bytes object. + :param fingerprint: + Fingerprint as string of hexdigits, can be interspersed by colons. + """ + + if cert is None: + raise SSLError("No certificate for the peer.") + + fingerprint = fingerprint.replace(":", "").lower() + digest_length = len(fingerprint) + if digest_length not in HASHFUNC_MAP: + raise SSLError(f"Fingerprint of invalid length: {fingerprint}") + hashfunc = HASHFUNC_MAP.get(digest_length) + if hashfunc is None: + raise SSLError( + f"Hash function implementation unavailable for fingerprint length: {digest_length}" + ) + + # We need encode() here for py32; works on py2 and p33. + fingerprint_bytes = unhexlify(fingerprint.encode()) + + cert_digest = hashfunc(cert).digest() + + if not hmac.compare_digest(cert_digest, fingerprint_bytes): + raise SSLError( + f'Fingerprints did not match. Expected "{fingerprint}", got "{cert_digest.hex()}"' + ) + + +def resolve_cert_reqs(candidate: None | int | str) -> VerifyMode: + """ + Resolves the argument to a numeric constant, which can be passed to + the wrap_socket function/method from the ssl module. + Defaults to :data:`ssl.CERT_REQUIRED`. + If given a string it is assumed to be the name of the constant in the + :mod:`ssl` module or its abbreviation. + (So you can specify `REQUIRED` instead of `CERT_REQUIRED`. + If it's neither `None` nor a string we assume it is already the numeric + constant which can directly be passed to wrap_socket. + """ + if candidate is None: + return CERT_REQUIRED + + if isinstance(candidate, str): + res = getattr(ssl, candidate, None) + if res is None: + res = getattr(ssl, "CERT_" + candidate) + return res # type: ignore[no-any-return] + + return candidate # type: ignore[return-value] + + +def resolve_ssl_version(candidate: None | int | str) -> int: + """ + like resolve_cert_reqs + """ + if candidate is None: + return PROTOCOL_TLS + + if isinstance(candidate, str): + res = getattr(ssl, candidate, None) + if res is None: + res = getattr(ssl, "PROTOCOL_" + candidate) + return typing.cast(int, res) + + return candidate + + +def create_urllib3_context( + ssl_version: int | None = None, + cert_reqs: int | None = None, + options: int | None = None, + ciphers: str | None = None, + ssl_minimum_version: int | None = None, + ssl_maximum_version: int | None = None, +) -> ssl.SSLContext: + """Creates and configures an :class:`ssl.SSLContext` instance for use with urllib3. + + :param ssl_version: + The desired protocol version to use. This will default to + PROTOCOL_SSLv23 which will negotiate the highest protocol that both + the server and your installation of OpenSSL support. + + This parameter is deprecated instead use 'ssl_minimum_version'. + :param ssl_minimum_version: + The minimum version of TLS to be used. Use the 'ssl.TLSVersion' enum for specifying the value. + :param ssl_maximum_version: + The maximum version of TLS to be used. Use the 'ssl.TLSVersion' enum for specifying the value. + Not recommended to set to anything other than 'ssl.TLSVersion.MAXIMUM_SUPPORTED' which is the + default value. + :param cert_reqs: + Whether to require the certificate verification. This defaults to + ``ssl.CERT_REQUIRED``. + :param options: + Specific OpenSSL options. These default to ``ssl.OP_NO_SSLv2``, + ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``, and ``ssl.OP_NO_TICKET``. + :param ciphers: + Which cipher suites to allow the server to select. Defaults to either system configured + ciphers if OpenSSL 1.1.1+, otherwise uses a secure default set of ciphers. + :returns: + Constructed SSLContext object with specified options + :rtype: SSLContext + """ + if SSLContext is None: + raise TypeError("Can't create an SSLContext object without an ssl module") + + # This means 'ssl_version' was specified as an exact value. + if ssl_version not in (None, PROTOCOL_TLS, PROTOCOL_TLS_CLIENT): + # Disallow setting 'ssl_version' and 'ssl_minimum|maximum_version' + # to avoid conflicts. + if ssl_minimum_version is not None or ssl_maximum_version is not None: + raise ValueError( + "Can't specify both 'ssl_version' and either " + "'ssl_minimum_version' or 'ssl_maximum_version'" + ) + + # 'ssl_version' is deprecated and will be removed in the future. + else: + # Use 'ssl_minimum_version' and 'ssl_maximum_version' instead. + ssl_minimum_version = _SSL_VERSION_TO_TLS_VERSION.get( + ssl_version, TLSVersion.MINIMUM_SUPPORTED + ) + ssl_maximum_version = _SSL_VERSION_TO_TLS_VERSION.get( + ssl_version, TLSVersion.MAXIMUM_SUPPORTED + ) + + # This warning message is pushing users to use 'ssl_minimum_version' + # instead of both min/max. Best practice is to only set the minimum version and + # keep the maximum version to be it's default value: 'TLSVersion.MAXIMUM_SUPPORTED' + warnings.warn( + "'ssl_version' option is deprecated and will be " + "removed in urllib3 v2.1.0. Instead use 'ssl_minimum_version'", + category=DeprecationWarning, + stacklevel=2, + ) + + # PROTOCOL_TLS is deprecated in Python 3.10 so we always use PROTOCOL_TLS_CLIENT + context = SSLContext(PROTOCOL_TLS_CLIENT) + + if ssl_minimum_version is not None: + context.minimum_version = ssl_minimum_version + else: # Python <3.10 defaults to 'MINIMUM_SUPPORTED' so explicitly set TLSv1.2 here + context.minimum_version = TLSVersion.TLSv1_2 + + if ssl_maximum_version is not None: + context.maximum_version = ssl_maximum_version + + # Unless we're given ciphers defer to either system ciphers in + # the case of OpenSSL 1.1.1+ or use our own secure default ciphers. + if ciphers: + context.set_ciphers(ciphers) + + # Setting the default here, as we may have no ssl module on import + cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs + + if options is None: + options = 0 + # SSLv2 is easily broken and is considered harmful and dangerous + options |= OP_NO_SSLv2 + # SSLv3 has several problems and is now dangerous + options |= OP_NO_SSLv3 + # Disable compression to prevent CRIME attacks for OpenSSL 1.0+ + # (issue #309) + options |= OP_NO_COMPRESSION + # TLSv1.2 only. Unless set explicitly, do not request tickets. + # This may save some bandwidth on wire, and although the ticket is encrypted, + # there is a risk associated with it being on wire, + # if the server is not rotating its ticketing keys properly. + options |= OP_NO_TICKET + + context.options |= options + + # Enable post-handshake authentication for TLS 1.3, see GH #1634. PHA is + # necessary for conditional client cert authentication with TLS 1.3. + # The attribute is None for OpenSSL <= 1.1.0 or does not exist when using + # an SSLContext created by pyOpenSSL. + if getattr(context, "post_handshake_auth", None) is not None: + context.post_handshake_auth = True + + # The order of the below lines setting verify_mode and check_hostname + # matter due to safe-guards SSLContext has to prevent an SSLContext with + # check_hostname=True, verify_mode=NONE/OPTIONAL. + # We always set 'check_hostname=False' for pyOpenSSL so we rely on our own + # 'ssl.match_hostname()' implementation. + if cert_reqs == ssl.CERT_REQUIRED and not IS_PYOPENSSL: + context.verify_mode = cert_reqs + context.check_hostname = True + else: + context.check_hostname = False + context.verify_mode = cert_reqs + + try: + context.hostname_checks_common_name = False + except AttributeError: # Defensive: for CPython < 3.9.3; for PyPy < 7.3.8 + pass + + sslkeylogfile = os.environ.get("SSLKEYLOGFILE") + if sslkeylogfile: + context.keylog_filename = sslkeylogfile + + return context + + +@typing.overload +def ssl_wrap_socket( + sock: socket.socket, + keyfile: str | None = ..., + certfile: str | None = ..., + cert_reqs: int | None = ..., + ca_certs: str | None = ..., + server_hostname: str | None = ..., + ssl_version: int | None = ..., + ciphers: str | None = ..., + ssl_context: ssl.SSLContext | None = ..., + ca_cert_dir: str | None = ..., + key_password: str | None = ..., + ca_cert_data: None | str | bytes = ..., + tls_in_tls: typing.Literal[False] = ..., +) -> ssl.SSLSocket: ... + + +@typing.overload +def ssl_wrap_socket( + sock: socket.socket, + keyfile: str | None = ..., + certfile: str | None = ..., + cert_reqs: int | None = ..., + ca_certs: str | None = ..., + server_hostname: str | None = ..., + ssl_version: int | None = ..., + ciphers: str | None = ..., + ssl_context: ssl.SSLContext | None = ..., + ca_cert_dir: str | None = ..., + key_password: str | None = ..., + ca_cert_data: None | str | bytes = ..., + tls_in_tls: bool = ..., +) -> ssl.SSLSocket | SSLTransportType: ... + + +def ssl_wrap_socket( + sock: socket.socket, + keyfile: str | None = None, + certfile: str | None = None, + cert_reqs: int | None = None, + ca_certs: str | None = None, + server_hostname: str | None = None, + ssl_version: int | None = None, + ciphers: str | None = None, + ssl_context: ssl.SSLContext | None = None, + ca_cert_dir: str | None = None, + key_password: str | None = None, + ca_cert_data: None | str | bytes = None, + tls_in_tls: bool = False, +) -> ssl.SSLSocket | SSLTransportType: + """ + All arguments except for server_hostname, ssl_context, tls_in_tls, ca_cert_data and + ca_cert_dir have the same meaning as they do when using + :func:`ssl.create_default_context`, :meth:`ssl.SSLContext.load_cert_chain`, + :meth:`ssl.SSLContext.set_ciphers` and :meth:`ssl.SSLContext.wrap_socket`. + + :param server_hostname: + When SNI is supported, the expected hostname of the certificate + :param ssl_context: + A pre-made :class:`SSLContext` object. If none is provided, one will + be created using :func:`create_urllib3_context`. + :param ciphers: + A string of ciphers we wish the client to support. + :param ca_cert_dir: + A directory containing CA certificates in multiple separate files, as + supported by OpenSSL's -CApath flag or the capath argument to + SSLContext.load_verify_locations(). + :param key_password: + Optional password if the keyfile is encrypted. + :param ca_cert_data: + Optional string containing CA certificates in PEM format suitable for + passing as the cadata parameter to SSLContext.load_verify_locations() + :param tls_in_tls: + Use SSLTransport to wrap the existing socket. + """ + context = ssl_context + if context is None: + # Note: This branch of code and all the variables in it are only used in tests. + # We should consider deprecating and removing this code. + context = create_urllib3_context(ssl_version, cert_reqs, ciphers=ciphers) + + if ca_certs or ca_cert_dir or ca_cert_data: + try: + context.load_verify_locations(ca_certs, ca_cert_dir, ca_cert_data) + except OSError as e: + raise SSLError(e) from e + + elif ssl_context is None and hasattr(context, "load_default_certs"): + # try to load OS default certs; works well on Windows. + context.load_default_certs() + + # Attempt to detect if we get the goofy behavior of the + # keyfile being encrypted and OpenSSL asking for the + # passphrase via the terminal and instead error out. + if keyfile and key_password is None and _is_key_file_encrypted(keyfile): + raise SSLError("Client private key is encrypted, password is required") + + if certfile: + if key_password is None: + context.load_cert_chain(certfile, keyfile) + else: + context.load_cert_chain(certfile, keyfile, key_password) + + context.set_alpn_protocols(ALPN_PROTOCOLS) + + ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname) + return ssl_sock + + +def is_ipaddress(hostname: str | bytes) -> bool: + """Detects whether the hostname given is an IPv4 or IPv6 address. + Also detects IPv6 addresses with Zone IDs. + + :param str hostname: Hostname to examine. + :return: True if the hostname is an IP address, False otherwise. + """ + if isinstance(hostname, bytes): + # IDN A-label bytes are ASCII compatible. + hostname = hostname.decode("ascii") + return bool(_IPV4_RE.match(hostname) or _BRACELESS_IPV6_ADDRZ_RE.match(hostname)) + + +def _is_key_file_encrypted(key_file: str) -> bool: + """Detects if a key file is encrypted or not.""" + with open(key_file) as f: + for line in f: + # Look for Proc-Type: 4,ENCRYPTED + if "ENCRYPTED" in line: + return True + + return False + + +def _ssl_wrap_socket_impl( + sock: socket.socket, + ssl_context: ssl.SSLContext, + tls_in_tls: bool, + server_hostname: str | None = None, +) -> ssl.SSLSocket | SSLTransportType: + if tls_in_tls: + if not SSLTransport: + # Import error, ssl is not available. + raise ProxySchemeUnsupported( + "TLS in TLS requires support for the 'ssl' module" + ) + + SSLTransport._validate_ssl_context_for_tls_in_tls(ssl_context) + return SSLTransport(sock, ssl_context, server_hostname) + + return ssl_context.wrap_socket(sock, server_hostname=server_hostname) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/ssl_match_hostname.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/ssl_match_hostname.py new file mode 100644 index 000000000..453cfd420 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/ssl_match_hostname.py @@ -0,0 +1,159 @@ +"""The match_hostname() function from Python 3.5, essential when using SSL.""" + +# Note: This file is under the PSF license as the code comes from the python +# stdlib. http://docs.python.org/3/license.html +# It is modified to remove commonName support. + +from __future__ import annotations + +import ipaddress +import re +import typing +from ipaddress import IPv4Address, IPv6Address + +if typing.TYPE_CHECKING: + from .ssl_ import _TYPE_PEER_CERT_RET_DICT + +__version__ = "3.5.0.1" + + +class CertificateError(ValueError): + pass + + +def _dnsname_match( + dn: typing.Any, hostname: str, max_wildcards: int = 1 +) -> typing.Match[str] | None | bool: + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + # Ported from python3-syntax: + # leftmost, *remainder = dn.split(r'.') + parts = dn.split(r".") + leftmost = parts[0] + remainder = parts[1:] + + wildcards = leftmost.count("*") + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn) + ) + + # speed up common case w/o wildcards + if not wildcards: + return bool(dn.lower() == hostname.lower()) + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == "*": + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append("[^.]+") + elif leftmost.startswith("xn--") or hostname.startswith("xn--"): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r"\*", "[^.]*")) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r"\A" + r"\.".join(pats) + r"\Z", re.IGNORECASE) + return pat.match(hostname) + + +def _ipaddress_match(ipname: str, host_ip: IPv4Address | IPv6Address) -> bool: + """Exact matching of IP addresses. + + RFC 9110 section 4.3.5: "A reference identity of IP-ID contains the decoded + bytes of the IP address. An IP version 4 address is 4 octets, and an IP + version 6 address is 16 octets. [...] A reference identity of type IP-ID + matches if the address is identical to an iPAddress value of the + subjectAltName extension of the certificate." + """ + # OpenSSL may add a trailing newline to a subjectAltName's IP address + # Divergence from upstream: ipaddress can't handle byte str + ip = ipaddress.ip_address(ipname.rstrip()) + return bool(ip.packed == host_ip.packed) + + +def match_hostname( + cert: _TYPE_PEER_CERT_RET_DICT | None, + hostname: str, + hostname_checks_common_name: bool = False, +) -> None: + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError( + "empty or no certificate, match_hostname needs a " + "SSL socket or SSL context with either " + "CERT_OPTIONAL or CERT_REQUIRED" + ) + try: + # Divergence from upstream: ipaddress can't handle byte str + # + # The ipaddress module shipped with Python < 3.9 does not support + # scoped IPv6 addresses so we unconditionally strip the Zone IDs for + # now. Once we drop support for Python 3.9 we can remove this branch. + if "%" in hostname: + host_ip = ipaddress.ip_address(hostname[: hostname.rfind("%")]) + else: + host_ip = ipaddress.ip_address(hostname) + + except ValueError: + # Not an IP address (common case) + host_ip = None + dnsnames = [] + san: tuple[tuple[str, str], ...] = cert.get("subjectAltName", ()) + key: str + value: str + for key, value in san: + if key == "DNS": + if host_ip is None and _dnsname_match(value, hostname): + return + dnsnames.append(value) + elif key == "IP Address": + if host_ip is not None and _ipaddress_match(value, host_ip): + return + dnsnames.append(value) + + # We only check 'commonName' if it's enabled and we're not verifying + # an IP address. IP addresses aren't valid within 'commonName'. + if hostname_checks_common_name and host_ip is None and not dnsnames: + for sub in cert.get("subject", ()): + for key, value in sub: + if key == "commonName": + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + + if len(dnsnames) > 1: + raise CertificateError( + "hostname %r " + "doesn't match either of %s" % (hostname, ", ".join(map(repr, dnsnames))) + ) + elif len(dnsnames) == 1: + raise CertificateError(f"hostname {hostname!r} doesn't match {dnsnames[0]!r}") + else: + raise CertificateError("no appropriate subjectAltName fields were found") diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/ssltransport.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/ssltransport.py new file mode 100644 index 000000000..6d59bc3bc --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/ssltransport.py @@ -0,0 +1,271 @@ +from __future__ import annotations + +import io +import socket +import ssl +import typing + +from ..exceptions import ProxySchemeUnsupported + +if typing.TYPE_CHECKING: + from typing_extensions import Self + + from .ssl_ import _TYPE_PEER_CERT_RET, _TYPE_PEER_CERT_RET_DICT + + +_WriteBuffer = typing.Union[bytearray, memoryview] +_ReturnValue = typing.TypeVar("_ReturnValue") + +SSL_BLOCKSIZE = 16384 + + +class SSLTransport: + """ + The SSLTransport wraps an existing socket and establishes an SSL connection. + + Contrary to Python's implementation of SSLSocket, it allows you to chain + multiple TLS connections together. It's particularly useful if you need to + implement TLS within TLS. + + The class supports most of the socket API operations. + """ + + @staticmethod + def _validate_ssl_context_for_tls_in_tls(ssl_context: ssl.SSLContext) -> None: + """ + Raises a ProxySchemeUnsupported if the provided ssl_context can't be used + for TLS in TLS. + + The only requirement is that the ssl_context provides the 'wrap_bio' + methods. + """ + + if not hasattr(ssl_context, "wrap_bio"): + raise ProxySchemeUnsupported( + "TLS in TLS requires SSLContext.wrap_bio() which isn't " + "available on non-native SSLContext" + ) + + def __init__( + self, + socket: socket.socket, + ssl_context: ssl.SSLContext, + server_hostname: str | None = None, + suppress_ragged_eofs: bool = True, + ) -> None: + """ + Create an SSLTransport around socket using the provided ssl_context. + """ + self.incoming = ssl.MemoryBIO() + self.outgoing = ssl.MemoryBIO() + + self.suppress_ragged_eofs = suppress_ragged_eofs + self.socket = socket + + self.sslobj = ssl_context.wrap_bio( + self.incoming, self.outgoing, server_hostname=server_hostname + ) + + # Perform initial handshake. + self._ssl_io_loop(self.sslobj.do_handshake) + + def __enter__(self) -> Self: + return self + + def __exit__(self, *_: typing.Any) -> None: + self.close() + + def fileno(self) -> int: + return self.socket.fileno() + + def read(self, len: int = 1024, buffer: typing.Any | None = None) -> int | bytes: + return self._wrap_ssl_read(len, buffer) + + def recv(self, buflen: int = 1024, flags: int = 0) -> int | bytes: + if flags != 0: + raise ValueError("non-zero flags not allowed in calls to recv") + return self._wrap_ssl_read(buflen) + + def recv_into( + self, + buffer: _WriteBuffer, + nbytes: int | None = None, + flags: int = 0, + ) -> None | int | bytes: + if flags != 0: + raise ValueError("non-zero flags not allowed in calls to recv_into") + if nbytes is None: + nbytes = len(buffer) + return self.read(nbytes, buffer) + + def sendall(self, data: bytes, flags: int = 0) -> None: + if flags != 0: + raise ValueError("non-zero flags not allowed in calls to sendall") + count = 0 + with memoryview(data) as view, view.cast("B") as byte_view: + amount = len(byte_view) + while count < amount: + v = self.send(byte_view[count:]) + count += v + + def send(self, data: bytes, flags: int = 0) -> int: + if flags != 0: + raise ValueError("non-zero flags not allowed in calls to send") + return self._ssl_io_loop(self.sslobj.write, data) + + def makefile( + self, + mode: str, + buffering: int | None = None, + *, + encoding: str | None = None, + errors: str | None = None, + newline: str | None = None, + ) -> typing.BinaryIO | typing.TextIO | socket.SocketIO: + """ + Python's httpclient uses makefile and buffered io when reading HTTP + messages and we need to support it. + + This is unfortunately a copy and paste of socket.py makefile with small + changes to point to the socket directly. + """ + if not set(mode) <= {"r", "w", "b"}: + raise ValueError(f"invalid mode {mode!r} (only r, w, b allowed)") + + writing = "w" in mode + reading = "r" in mode or not writing + assert reading or writing + binary = "b" in mode + rawmode = "" + if reading: + rawmode += "r" + if writing: + rawmode += "w" + raw = socket.SocketIO(self, rawmode) # type: ignore[arg-type] + self.socket._io_refs += 1 # type: ignore[attr-defined] + if buffering is None: + buffering = -1 + if buffering < 0: + buffering = io.DEFAULT_BUFFER_SIZE + if buffering == 0: + if not binary: + raise ValueError("unbuffered streams must be binary") + return raw + buffer: typing.BinaryIO + if reading and writing: + buffer = io.BufferedRWPair(raw, raw, buffering) # type: ignore[assignment] + elif reading: + buffer = io.BufferedReader(raw, buffering) + else: + assert writing + buffer = io.BufferedWriter(raw, buffering) + if binary: + return buffer + text = io.TextIOWrapper(buffer, encoding, errors, newline) + text.mode = mode # type: ignore[misc] + return text + + def unwrap(self) -> None: + self._ssl_io_loop(self.sslobj.unwrap) + + def close(self) -> None: + self.socket.close() + + @typing.overload + def getpeercert( + self, binary_form: typing.Literal[False] = ... + ) -> _TYPE_PEER_CERT_RET_DICT | None: ... + + @typing.overload + def getpeercert(self, binary_form: typing.Literal[True]) -> bytes | None: ... + + def getpeercert(self, binary_form: bool = False) -> _TYPE_PEER_CERT_RET: + return self.sslobj.getpeercert(binary_form) # type: ignore[return-value] + + def version(self) -> str | None: + return self.sslobj.version() + + def cipher(self) -> tuple[str, str, int] | None: + return self.sslobj.cipher() + + def selected_alpn_protocol(self) -> str | None: + return self.sslobj.selected_alpn_protocol() + + def shared_ciphers(self) -> list[tuple[str, str, int]] | None: + return self.sslobj.shared_ciphers() + + def compression(self) -> str | None: + return self.sslobj.compression() + + def settimeout(self, value: float | None) -> None: + self.socket.settimeout(value) + + def gettimeout(self) -> float | None: + return self.socket.gettimeout() + + def _decref_socketios(self) -> None: + self.socket._decref_socketios() # type: ignore[attr-defined] + + def _wrap_ssl_read(self, len: int, buffer: bytearray | None = None) -> int | bytes: + try: + return self._ssl_io_loop(self.sslobj.read, len, buffer) + except ssl.SSLError as e: + if e.errno == ssl.SSL_ERROR_EOF and self.suppress_ragged_eofs: + return 0 # eof, return 0. + else: + raise + + # func is sslobj.do_handshake or sslobj.unwrap + @typing.overload + def _ssl_io_loop(self, func: typing.Callable[[], None]) -> None: ... + + # func is sslobj.write, arg1 is data + @typing.overload + def _ssl_io_loop(self, func: typing.Callable[[bytes], int], arg1: bytes) -> int: ... + + # func is sslobj.read, arg1 is len, arg2 is buffer + @typing.overload + def _ssl_io_loop( + self, + func: typing.Callable[[int, bytearray | None], bytes], + arg1: int, + arg2: bytearray | None, + ) -> bytes: ... + + def _ssl_io_loop( + self, + func: typing.Callable[..., _ReturnValue], + arg1: None | bytes | int = None, + arg2: bytearray | None = None, + ) -> _ReturnValue: + """Performs an I/O loop between incoming/outgoing and the socket.""" + should_loop = True + ret = None + + while should_loop: + errno = None + try: + if arg1 is None and arg2 is None: + ret = func() + elif arg2 is None: + ret = func(arg1) + else: + ret = func(arg1, arg2) + except ssl.SSLError as e: + if e.errno not in (ssl.SSL_ERROR_WANT_READ, ssl.SSL_ERROR_WANT_WRITE): + # WANT_READ, and WANT_WRITE are expected, others are not. + raise e + errno = e.errno + + buf = self.outgoing.read() + self.socket.sendall(buf) + + if errno is None: + should_loop = False + elif errno == ssl.SSL_ERROR_WANT_READ: + buf = self.socket.recv(SSL_BLOCKSIZE) + if buf: + self.incoming.write(buf) + else: + self.incoming.write_eof() + return typing.cast(_ReturnValue, ret) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/timeout.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/timeout.py new file mode 100644 index 000000000..4bb1be11d --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/timeout.py @@ -0,0 +1,275 @@ +from __future__ import annotations + +import time +import typing +from enum import Enum +from socket import getdefaulttimeout + +from ..exceptions import TimeoutStateError + +if typing.TYPE_CHECKING: + from typing import Final + + +class _TYPE_DEFAULT(Enum): + # This value should never be passed to socket.settimeout() so for safety we use a -1. + # socket.settimout() raises a ValueError for negative values. + token = -1 + + +_DEFAULT_TIMEOUT: Final[_TYPE_DEFAULT] = _TYPE_DEFAULT.token + +_TYPE_TIMEOUT = typing.Optional[typing.Union[float, _TYPE_DEFAULT]] + + +class Timeout: + """Timeout configuration. + + Timeouts can be defined as a default for a pool: + + .. code-block:: python + + import urllib3 + + timeout = urllib3.util.Timeout(connect=2.0, read=7.0) + + http = urllib3.PoolManager(timeout=timeout) + + resp = http.request("GET", "https://example.com/") + + print(resp.status) + + Or per-request (which overrides the default for the pool): + + .. code-block:: python + + response = http.request("GET", "https://example.com/", timeout=Timeout(10)) + + Timeouts can be disabled by setting all the parameters to ``None``: + + .. code-block:: python + + no_timeout = Timeout(connect=None, read=None) + response = http.request("GET", "https://example.com/", timeout=no_timeout) + + + :param total: + This combines the connect and read timeouts into one; the read timeout + will be set to the time leftover from the connect attempt. In the + event that both a connect timeout and a total are specified, or a read + timeout and a total are specified, the shorter timeout will be applied. + + Defaults to None. + + :type total: int, float, or None + + :param connect: + The maximum amount of time (in seconds) to wait for a connection + attempt to a server to succeed. Omitting the parameter will default the + connect timeout to the system default, probably `the global default + timeout in socket.py + `_. + None will set an infinite timeout for connection attempts. + + :type connect: int, float, or None + + :param read: + The maximum amount of time (in seconds) to wait between consecutive + read operations for a response from the server. Omitting the parameter + will default the read timeout to the system default, probably `the + global default timeout in socket.py + `_. + None will set an infinite timeout. + + :type read: int, float, or None + + .. note:: + + Many factors can affect the total amount of time for urllib3 to return + an HTTP response. + + For example, Python's DNS resolver does not obey the timeout specified + on the socket. Other factors that can affect total request time include + high CPU load, high swap, the program running at a low priority level, + or other behaviors. + + In addition, the read and total timeouts only measure the time between + read operations on the socket connecting the client and the server, + not the total amount of time for the request to return a complete + response. For most requests, the timeout is raised because the server + has not sent the first byte in the specified time. This is not always + the case; if a server streams one byte every fifteen seconds, a timeout + of 20 seconds will not trigger, even though the request will take + several minutes to complete. + """ + + #: A sentinel object representing the default timeout value + DEFAULT_TIMEOUT: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT + + def __init__( + self, + total: _TYPE_TIMEOUT = None, + connect: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, + read: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, + ) -> None: + self._connect = self._validate_timeout(connect, "connect") + self._read = self._validate_timeout(read, "read") + self.total = self._validate_timeout(total, "total") + self._start_connect: float | None = None + + def __repr__(self) -> str: + return f"{type(self).__name__}(connect={self._connect!r}, read={self._read!r}, total={self.total!r})" + + # __str__ provided for backwards compatibility + __str__ = __repr__ + + @staticmethod + def resolve_default_timeout(timeout: _TYPE_TIMEOUT) -> float | None: + return getdefaulttimeout() if timeout is _DEFAULT_TIMEOUT else timeout + + @classmethod + def _validate_timeout(cls, value: _TYPE_TIMEOUT, name: str) -> _TYPE_TIMEOUT: + """Check that a timeout attribute is valid. + + :param value: The timeout value to validate + :param name: The name of the timeout attribute to validate. This is + used to specify in error messages. + :return: The validated and casted version of the given value. + :raises ValueError: If it is a numeric value less than or equal to + zero, or the type is not an integer, float, or None. + """ + if value is None or value is _DEFAULT_TIMEOUT: + return value + + if isinstance(value, bool): + raise ValueError( + "Timeout cannot be a boolean value. It must " + "be an int, float or None." + ) + try: + float(value) + except (TypeError, ValueError): + raise ValueError( + "Timeout value %s was %s, but it must be an " + "int, float or None." % (name, value) + ) from None + + try: + if value <= 0: + raise ValueError( + "Attempted to set %s timeout to %s, but the " + "timeout cannot be set to a value less " + "than or equal to 0." % (name, value) + ) + except TypeError: + raise ValueError( + "Timeout value %s was %s, but it must be an " + "int, float or None." % (name, value) + ) from None + + return value + + @classmethod + def from_float(cls, timeout: _TYPE_TIMEOUT) -> Timeout: + """Create a new Timeout from a legacy timeout value. + + The timeout value used by httplib.py sets the same timeout on the + connect(), and recv() socket requests. This creates a :class:`Timeout` + object that sets the individual timeouts to the ``timeout`` value + passed to this function. + + :param timeout: The legacy timeout value. + :type timeout: integer, float, :attr:`urllib3.util.Timeout.DEFAULT_TIMEOUT`, or None + :return: Timeout object + :rtype: :class:`Timeout` + """ + return Timeout(read=timeout, connect=timeout) + + def clone(self) -> Timeout: + """Create a copy of the timeout object + + Timeout properties are stored per-pool but each request needs a fresh + Timeout object to ensure each one has its own start/stop configured. + + :return: a copy of the timeout object + :rtype: :class:`Timeout` + """ + # We can't use copy.deepcopy because that will also create a new object + # for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to + # detect the user default. + return Timeout(connect=self._connect, read=self._read, total=self.total) + + def start_connect(self) -> float: + """Start the timeout clock, used during a connect() attempt + + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to start a timer that has been started already. + """ + if self._start_connect is not None: + raise TimeoutStateError("Timeout timer has already been started.") + self._start_connect = time.monotonic() + return self._start_connect + + def get_connect_duration(self) -> float: + """Gets the time elapsed since the call to :meth:`start_connect`. + + :return: Elapsed time in seconds. + :rtype: float + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to get duration for a timer that hasn't been started. + """ + if self._start_connect is None: + raise TimeoutStateError( + "Can't get connect duration for timer that has not started." + ) + return time.monotonic() - self._start_connect + + @property + def connect_timeout(self) -> _TYPE_TIMEOUT: + """Get the value to use when setting a connection timeout. + + This will be a positive float or integer, the value None + (never timeout), or the default system timeout. + + :return: Connect timeout. + :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None + """ + if self.total is None: + return self._connect + + if self._connect is None or self._connect is _DEFAULT_TIMEOUT: + return self.total + + return min(self._connect, self.total) # type: ignore[type-var] + + @property + def read_timeout(self) -> float | None: + """Get the value for the read timeout. + + This assumes some time has elapsed in the connection timeout and + computes the read timeout appropriately. + + If self.total is set, the read timeout is dependent on the amount of + time taken by the connect timeout. If the connection time has not been + established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be + raised. + + :return: Value to use for the read timeout. + :rtype: int, float or None + :raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect` + has not yet been called on this object. + """ + if ( + self.total is not None + and self.total is not _DEFAULT_TIMEOUT + and self._read is not None + and self._read is not _DEFAULT_TIMEOUT + ): + # In case the connect timeout has not yet been established. + if self._start_connect is None: + return self._read + return max(0, min(self.total - self.get_connect_duration(), self._read)) + elif self.total is not None and self.total is not _DEFAULT_TIMEOUT: + return max(0, self.total - self.get_connect_duration()) + else: + return self.resolve_default_timeout(self._read) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/url.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/url.py new file mode 100644 index 000000000..db057f17b --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/url.py @@ -0,0 +1,469 @@ +from __future__ import annotations + +import re +import typing + +from ..exceptions import LocationParseError +from .util import to_str + +# We only want to normalize urls with an HTTP(S) scheme. +# urllib3 infers URLs without a scheme (None) to be http. +_NORMALIZABLE_SCHEMES = ("http", "https", None) + +# Almost all of these patterns were derived from the +# 'rfc3986' module: https://github.com/python-hyper/rfc3986 +_PERCENT_RE = re.compile(r"%[a-fA-F0-9]{2}") +_SCHEME_RE = re.compile(r"^(?:[a-zA-Z][a-zA-Z0-9+-]*:|/)") +_URI_RE = re.compile( + r"^(?:([a-zA-Z][a-zA-Z0-9+.-]*):)?" + r"(?://([^\\/?#]*))?" + r"([^?#]*)" + r"(?:\?([^#]*))?" + r"(?:#(.*))?$", + re.UNICODE | re.DOTALL, +) + +_IPV4_PAT = r"(?:[0-9]{1,3}\.){3}[0-9]{1,3}" +_HEX_PAT = "[0-9A-Fa-f]{1,4}" +_LS32_PAT = "(?:{hex}:{hex}|{ipv4})".format(hex=_HEX_PAT, ipv4=_IPV4_PAT) +_subs = {"hex": _HEX_PAT, "ls32": _LS32_PAT} +_variations = [ + # 6( h16 ":" ) ls32 + "(?:%(hex)s:){6}%(ls32)s", + # "::" 5( h16 ":" ) ls32 + "::(?:%(hex)s:){5}%(ls32)s", + # [ h16 ] "::" 4( h16 ":" ) ls32 + "(?:%(hex)s)?::(?:%(hex)s:){4}%(ls32)s", + # [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 + "(?:(?:%(hex)s:)?%(hex)s)?::(?:%(hex)s:){3}%(ls32)s", + # [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 + "(?:(?:%(hex)s:){0,2}%(hex)s)?::(?:%(hex)s:){2}%(ls32)s", + # [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 + "(?:(?:%(hex)s:){0,3}%(hex)s)?::%(hex)s:%(ls32)s", + # [ *4( h16 ":" ) h16 ] "::" ls32 + "(?:(?:%(hex)s:){0,4}%(hex)s)?::%(ls32)s", + # [ *5( h16 ":" ) h16 ] "::" h16 + "(?:(?:%(hex)s:){0,5}%(hex)s)?::%(hex)s", + # [ *6( h16 ":" ) h16 ] "::" + "(?:(?:%(hex)s:){0,6}%(hex)s)?::", +] + +_UNRESERVED_PAT = r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._\-~" +_IPV6_PAT = "(?:" + "|".join([x % _subs for x in _variations]) + ")" +_ZONE_ID_PAT = "(?:%25|%)(?:[" + _UNRESERVED_PAT + "]|%[a-fA-F0-9]{2})+" +_IPV6_ADDRZ_PAT = r"\[" + _IPV6_PAT + r"(?:" + _ZONE_ID_PAT + r")?\]" +_REG_NAME_PAT = r"(?:[^\[\]%:/?#]|%[a-fA-F0-9]{2})*" +_TARGET_RE = re.compile(r"^(/[^?#]*)(?:\?([^#]*))?(?:#.*)?$") + +_IPV4_RE = re.compile("^" + _IPV4_PAT + "$") +_IPV6_RE = re.compile("^" + _IPV6_PAT + "$") +_IPV6_ADDRZ_RE = re.compile("^" + _IPV6_ADDRZ_PAT + "$") +_BRACELESS_IPV6_ADDRZ_RE = re.compile("^" + _IPV6_ADDRZ_PAT[2:-2] + "$") +_ZONE_ID_RE = re.compile("(" + _ZONE_ID_PAT + r")\]$") + +_HOST_PORT_PAT = ("^(%s|%s|%s)(?::0*?(|0|[1-9][0-9]{0,4}))?$") % ( + _REG_NAME_PAT, + _IPV4_PAT, + _IPV6_ADDRZ_PAT, +) +_HOST_PORT_RE = re.compile(_HOST_PORT_PAT, re.UNICODE | re.DOTALL) + +_UNRESERVED_CHARS = set( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-~" +) +_SUB_DELIM_CHARS = set("!$&'()*+,;=") +_USERINFO_CHARS = _UNRESERVED_CHARS | _SUB_DELIM_CHARS | {":"} +_PATH_CHARS = _USERINFO_CHARS | {"@", "/"} +_QUERY_CHARS = _FRAGMENT_CHARS = _PATH_CHARS | {"?"} + + +class Url( + typing.NamedTuple( + "Url", + [ + ("scheme", typing.Optional[str]), + ("auth", typing.Optional[str]), + ("host", typing.Optional[str]), + ("port", typing.Optional[int]), + ("path", typing.Optional[str]), + ("query", typing.Optional[str]), + ("fragment", typing.Optional[str]), + ], + ) +): + """ + Data structure for representing an HTTP URL. Used as a return value for + :func:`parse_url`. Both the scheme and host are normalized as they are + both case-insensitive according to RFC 3986. + """ + + def __new__( # type: ignore[no-untyped-def] + cls, + scheme: str | None = None, + auth: str | None = None, + host: str | None = None, + port: int | None = None, + path: str | None = None, + query: str | None = None, + fragment: str | None = None, + ): + if path and not path.startswith("/"): + path = "/" + path + if scheme is not None: + scheme = scheme.lower() + return super().__new__(cls, scheme, auth, host, port, path, query, fragment) + + @property + def hostname(self) -> str | None: + """For backwards-compatibility with urlparse. We're nice like that.""" + return self.host + + @property + def request_uri(self) -> str: + """Absolute path including the query string.""" + uri = self.path or "/" + + if self.query is not None: + uri += "?" + self.query + + return uri + + @property + def authority(self) -> str | None: + """ + Authority component as defined in RFC 3986 3.2. + This includes userinfo (auth), host and port. + + i.e. + userinfo@host:port + """ + userinfo = self.auth + netloc = self.netloc + if netloc is None or userinfo is None: + return netloc + else: + return f"{userinfo}@{netloc}" + + @property + def netloc(self) -> str | None: + """ + Network location including host and port. + + If you need the equivalent of urllib.parse's ``netloc``, + use the ``authority`` property instead. + """ + if self.host is None: + return None + if self.port: + return f"{self.host}:{self.port}" + return self.host + + @property + def url(self) -> str: + """ + Convert self into a url + + This function should more or less round-trip with :func:`.parse_url`. The + returned url may not be exactly the same as the url inputted to + :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls + with a blank port will have : removed). + + Example: + + .. code-block:: python + + import urllib3 + + U = urllib3.util.parse_url("https://google.com/mail/") + + print(U.url) + # "https://google.com/mail/" + + print( urllib3.util.Url("https", "username:password", + "host.com", 80, "/path", "query", "fragment" + ).url + ) + # "https://username:password@host.com:80/path?query#fragment" + """ + scheme, auth, host, port, path, query, fragment = self + url = "" + + # We use "is not None" we want things to happen with empty strings (or 0 port) + if scheme is not None: + url += scheme + "://" + if auth is not None: + url += auth + "@" + if host is not None: + url += host + if port is not None: + url += ":" + str(port) + if path is not None: + url += path + if query is not None: + url += "?" + query + if fragment is not None: + url += "#" + fragment + + return url + + def __str__(self) -> str: + return self.url + + +@typing.overload +def _encode_invalid_chars( + component: str, allowed_chars: typing.Container[str] +) -> str: # Abstract + ... + + +@typing.overload +def _encode_invalid_chars( + component: None, allowed_chars: typing.Container[str] +) -> None: # Abstract + ... + + +def _encode_invalid_chars( + component: str | None, allowed_chars: typing.Container[str] +) -> str | None: + """Percent-encodes a URI component without reapplying + onto an already percent-encoded component. + """ + if component is None: + return component + + component = to_str(component) + + # Normalize existing percent-encoded bytes. + # Try to see if the component we're encoding is already percent-encoded + # so we can skip all '%' characters but still encode all others. + component, percent_encodings = _PERCENT_RE.subn( + lambda match: match.group(0).upper(), component + ) + + uri_bytes = component.encode("utf-8", "surrogatepass") + is_percent_encoded = percent_encodings == uri_bytes.count(b"%") + encoded_component = bytearray() + + for i in range(0, len(uri_bytes)): + # Will return a single character bytestring + byte = uri_bytes[i : i + 1] + byte_ord = ord(byte) + if (is_percent_encoded and byte == b"%") or ( + byte_ord < 128 and byte.decode() in allowed_chars + ): + encoded_component += byte + continue + encoded_component.extend(b"%" + (hex(byte_ord)[2:].encode().zfill(2).upper())) + + return encoded_component.decode() + + +def _remove_path_dot_segments(path: str) -> str: + # See http://tools.ietf.org/html/rfc3986#section-5.2.4 for pseudo-code + segments = path.split("/") # Turn the path into a list of segments + output = [] # Initialize the variable to use to store output + + for segment in segments: + # '.' is the current directory, so ignore it, it is superfluous + if segment == ".": + continue + # Anything other than '..', should be appended to the output + if segment != "..": + output.append(segment) + # In this case segment == '..', if we can, we should pop the last + # element + elif output: + output.pop() + + # If the path starts with '/' and the output is empty or the first string + # is non-empty + if path.startswith("/") and (not output or output[0]): + output.insert(0, "") + + # If the path starts with '/.' or '/..' ensure we add one more empty + # string to add a trailing '/' + if path.endswith(("/.", "/..")): + output.append("") + + return "/".join(output) + + +@typing.overload +def _normalize_host(host: None, scheme: str | None) -> None: ... + + +@typing.overload +def _normalize_host(host: str, scheme: str | None) -> str: ... + + +def _normalize_host(host: str | None, scheme: str | None) -> str | None: + if host: + if scheme in _NORMALIZABLE_SCHEMES: + is_ipv6 = _IPV6_ADDRZ_RE.match(host) + if is_ipv6: + # IPv6 hosts of the form 'a::b%zone' are encoded in a URL as + # such per RFC 6874: 'a::b%25zone'. Unquote the ZoneID + # separator as necessary to return a valid RFC 4007 scoped IP. + match = _ZONE_ID_RE.search(host) + if match: + start, end = match.span(1) + zone_id = host[start:end] + + if zone_id.startswith("%25") and zone_id != "%25": + zone_id = zone_id[3:] + else: + zone_id = zone_id[1:] + zone_id = _encode_invalid_chars(zone_id, _UNRESERVED_CHARS) + return f"{host[:start].lower()}%{zone_id}{host[end:]}" + else: + return host.lower() + elif not _IPV4_RE.match(host): + return to_str( + b".".join([_idna_encode(label) for label in host.split(".")]), + "ascii", + ) + return host + + +def _idna_encode(name: str) -> bytes: + if not name.isascii(): + try: + import idna + except ImportError: + raise LocationParseError( + "Unable to parse URL without the 'idna' module" + ) from None + + try: + return idna.encode(name.lower(), strict=True, std3_rules=True) + except idna.IDNAError: + raise LocationParseError( + f"Name '{name}' is not a valid IDNA label" + ) from None + + return name.lower().encode("ascii") + + +def _encode_target(target: str) -> str: + """Percent-encodes a request target so that there are no invalid characters + + Pre-condition for this function is that 'target' must start with '/'. + If that is the case then _TARGET_RE will always produce a match. + """ + match = _TARGET_RE.match(target) + if not match: # Defensive: + raise LocationParseError(f"{target!r} is not a valid request URI") + + path, query = match.groups() + encoded_target = _encode_invalid_chars(path, _PATH_CHARS) + if query is not None: + query = _encode_invalid_chars(query, _QUERY_CHARS) + encoded_target += "?" + query + return encoded_target + + +def parse_url(url: str) -> Url: + """ + Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is + performed to parse incomplete urls. Fields not provided will be None. + This parser is RFC 3986 and RFC 6874 compliant. + + The parser logic and helper functions are based heavily on + work done in the ``rfc3986`` module. + + :param str url: URL to parse into a :class:`.Url` namedtuple. + + Partly backwards-compatible with :mod:`urllib.parse`. + + Example: + + .. code-block:: python + + import urllib3 + + print( urllib3.util.parse_url('http://google.com/mail/')) + # Url(scheme='http', host='google.com', port=None, path='/mail/', ...) + + print( urllib3.util.parse_url('google.com:80')) + # Url(scheme=None, host='google.com', port=80, path=None, ...) + + print( urllib3.util.parse_url('/foo?bar')) + # Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...) + """ + if not url: + # Empty + return Url() + + source_url = url + if not _SCHEME_RE.search(url): + url = "//" + url + + scheme: str | None + authority: str | None + auth: str | None + host: str | None + port: str | None + port_int: int | None + path: str | None + query: str | None + fragment: str | None + + try: + scheme, authority, path, query, fragment = _URI_RE.match(url).groups() # type: ignore[union-attr] + normalize_uri = scheme is None or scheme.lower() in _NORMALIZABLE_SCHEMES + + if scheme: + scheme = scheme.lower() + + if authority: + auth, _, host_port = authority.rpartition("@") + auth = auth or None + host, port = _HOST_PORT_RE.match(host_port).groups() # type: ignore[union-attr] + if auth and normalize_uri: + auth = _encode_invalid_chars(auth, _USERINFO_CHARS) + if port == "": + port = None + else: + auth, host, port = None, None, None + + if port is not None: + port_int = int(port) + if not (0 <= port_int <= 65535): + raise LocationParseError(url) + else: + port_int = None + + host = _normalize_host(host, scheme) + + if normalize_uri and path: + path = _remove_path_dot_segments(path) + path = _encode_invalid_chars(path, _PATH_CHARS) + if normalize_uri and query: + query = _encode_invalid_chars(query, _QUERY_CHARS) + if normalize_uri and fragment: + fragment = _encode_invalid_chars(fragment, _FRAGMENT_CHARS) + + except (ValueError, AttributeError) as e: + raise LocationParseError(source_url) from e + + # For the sake of backwards compatibility we put empty + # string values for path if there are any defined values + # beyond the path in the URL. + # TODO: Remove this when we break backwards compatibility. + if not path: + if query is not None or fragment is not None: + path = "" + else: + path = None + + return Url( + scheme=scheme, + auth=auth, + host=host, + port=port_int, + path=path, + query=query, + fragment=fragment, + ) diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/util.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/util.py new file mode 100644 index 000000000..35c77e402 --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/util.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +import typing +from types import TracebackType + + +def to_bytes( + x: str | bytes, encoding: str | None = None, errors: str | None = None +) -> bytes: + if isinstance(x, bytes): + return x + elif not isinstance(x, str): + raise TypeError(f"not expecting type {type(x).__name__}") + if encoding or errors: + return x.encode(encoding or "utf-8", errors=errors or "strict") + return x.encode() + + +def to_str( + x: str | bytes, encoding: str | None = None, errors: str | None = None +) -> str: + if isinstance(x, str): + return x + elif not isinstance(x, bytes): + raise TypeError(f"not expecting type {type(x).__name__}") + if encoding or errors: + return x.decode(encoding or "utf-8", errors=errors or "strict") + return x.decode() + + +def reraise( + tp: type[BaseException] | None, + value: BaseException, + tb: TracebackType | None = None, +) -> typing.NoReturn: + try: + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None # type: ignore[assignment] + tb = None diff --git a/apigw-private-cdn-acm/acm-certificate/urllib3/util/wait.py b/apigw-private-cdn-acm/acm-certificate/urllib3/util/wait.py new file mode 100644 index 000000000..aeca0c7ad --- /dev/null +++ b/apigw-private-cdn-acm/acm-certificate/urllib3/util/wait.py @@ -0,0 +1,124 @@ +from __future__ import annotations + +import select +import socket +from functools import partial + +__all__ = ["wait_for_read", "wait_for_write"] + + +# How should we wait on sockets? +# +# There are two types of APIs you can use for waiting on sockets: the fancy +# modern stateful APIs like epoll/kqueue, and the older stateless APIs like +# select/poll. The stateful APIs are more efficient when you have a lots of +# sockets to keep track of, because you can set them up once and then use them +# lots of times. But we only ever want to wait on a single socket at a time +# and don't want to keep track of state, so the stateless APIs are actually +# more efficient. So we want to use select() or poll(). +# +# Now, how do we choose between select() and poll()? On traditional Unixes, +# select() has a strange calling convention that makes it slow, or fail +# altogether, for high-numbered file descriptors. The point of poll() is to fix +# that, so on Unixes, we prefer poll(). +# +# On Windows, there is no poll() (or at least Python doesn't provide a wrapper +# for it), but that's OK, because on Windows, select() doesn't have this +# strange calling convention; plain select() works fine. +# +# So: on Windows we use select(), and everywhere else we use poll(). We also +# fall back to select() in case poll() is somehow broken or missing. + + +def select_wait_for_socket( + sock: socket.socket, + read: bool = False, + write: bool = False, + timeout: float | None = None, +) -> bool: + if not read and not write: + raise RuntimeError("must specify at least one of read=True, write=True") + rcheck = [] + wcheck = [] + if read: + rcheck.append(sock) + if write: + wcheck.append(sock) + # When doing a non-blocking connect, most systems signal success by + # marking the socket writable. Windows, though, signals success by marked + # it as "exceptional". We paper over the difference by checking the write + # sockets for both conditions. (The stdlib selectors module does the same + # thing.) + fn = partial(select.select, rcheck, wcheck, wcheck) + rready, wready, xready = fn(timeout) + return bool(rready or wready or xready) + + +def poll_wait_for_socket( + sock: socket.socket, + read: bool = False, + write: bool = False, + timeout: float | None = None, +) -> bool: + if not read and not write: + raise RuntimeError("must specify at least one of read=True, write=True") + mask = 0 + if read: + mask |= select.POLLIN + if write: + mask |= select.POLLOUT + poll_obj = select.poll() + poll_obj.register(sock, mask) + + # For some reason, poll() takes timeout in milliseconds + def do_poll(t: float | None) -> list[tuple[int, int]]: + if t is not None: + t *= 1000 + return poll_obj.poll(t) + + return bool(do_poll(timeout)) + + +def _have_working_poll() -> bool: + # Apparently some systems have a select.poll that fails as soon as you try + # to use it, either due to strange configuration or broken monkeypatching + # from libraries like eventlet/greenlet. + try: + poll_obj = select.poll() + poll_obj.poll(0) + except (AttributeError, OSError): + return False + else: + return True + + +def wait_for_socket( + sock: socket.socket, + read: bool = False, + write: bool = False, + timeout: float | None = None, +) -> bool: + # We delay choosing which implementation to use until the first time we're + # called. We could do it at import time, but then we might make the wrong + # decision if someone goes wild with monkeypatching select.poll after + # we're imported. + global wait_for_socket + if _have_working_poll(): + wait_for_socket = poll_wait_for_socket + elif hasattr(select, "select"): + wait_for_socket = select_wait_for_socket + return wait_for_socket(sock, read, write, timeout) + + +def wait_for_read(sock: socket.socket, timeout: float | None = None) -> bool: + """Waits for reading to be available on a given socket. + Returns True if the socket is readable, or False if the timeout expired. + """ + return wait_for_socket(sock, read=True, timeout=timeout) + + +def wait_for_write(sock: socket.socket, timeout: float | None = None) -> bool: + """Waits for writing to be available on a given socket. + Returns True if the socket is readable, or False if the timeout expired. + """ + return wait_for_socket(sock, write=True, timeout=timeout) diff --git a/apigw-private-cdn-acm/api-testing/index.py b/apigw-private-cdn-acm/api-testing/index.py new file mode 100644 index 000000000..05ae6bed9 --- /dev/null +++ b/apigw-private-cdn-acm/api-testing/index.py @@ -0,0 +1,40 @@ +import boto3 +import os +import botocore.credentials +from botocore.awsrequest import AWSRequest +from botocore.httpsession import URLLib3Session +from botocore.auth import SigV4Auth + +def lambda_handler(event, context): + """ + Lambda function handler to make a GET request to a custom domain name with a specific path. + + Args: + event (dict): The event payload from AWS Lambda. + context (object): The context object from AWS Lambda. + + Returns: + str: The response text from the GET request. + """ + + # Getting custom domain name from the environment variable + custom_domain_name = os.environ['CUSTOM_DOMAIN_NAME'] + + # Constructing the URL for the GET request + request = AWSRequest(method="GET", url="https://" + custom_domain_name + "/prod/mypath") + + # Creating a URLLib3Session object with SSL/TLS verification using the provided root CA certificate + session = URLLib3Session( + verify='./rootCA.pem' + ) + + # Sending the GET request and getting the response + r = session.send(request.prepare()) + + # Printing the response text, headers, and status code for debugging purposes + print(r.text) + print(r.headers) + print(r.status_code) + + # Returning the response text + return r.text \ No newline at end of file diff --git a/apigw-private-cdn-acm/api-testing/rootCA.pem b/apigw-private-cdn-acm/api-testing/rootCA.pem new file mode 100644 index 000000000..984746bc3 --- /dev/null +++ b/apigw-private-cdn-acm/api-testing/rootCA.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFqTCCA5GgAwIBAgIUcUEHsdwNth1HsR/07VkeR+p15V4wDQYJKoZIhvcNAQEN +BQAwZDELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxHTAbBgNVBAoM +FEV4YW1wbGUgT3JnYW5pemF0aW9uMQswCQYDVQQLDAJJVDEUMBIGA1UEAwwLZXhh +bXBsZS5jb20wHhcNMjUwMzI0MDE1NzA3WhcNMzUwMzIyMDE1NzA3WjBkMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTEdMBsGA1UECgwURXhhbXBsZSBP +cmdhbml6YXRpb24xCzAJBgNVBAsMAklUMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMbxvxlv3P8tQS8Q00kLHnBE +GenvDAnu4PL5scKCb5vYXTtp+JNTu6co4d7JiSnpyvJ5lPwZybTsXpEj3VVs46rO +CzumlPT1UjJ9XAFDdI437cZCslr3lhGz84y3HLWOq1F91/lnPj1gh4Zi3lR/opu5 +nbdIuu1Knj0EaKMO5xvkfpzcndU26CIcrX/Sm9k2g1/GG9EEgCLcAXOpxxJI10OI +ccd1REQg5VmJcLdSGI7j9b/9/OEsv1CmBNY2JDAK1PJFKY7qXDwN1+bUdCe29omR +h/dshAa4jnqLX7ydraQgLeYUQP9bsOkFativAHDL/VywDhjZP3dARdZB8VnrMjae +/fbe8WLohmnYToyEb4WCX7Jhd7wqqhff+WCneGSMlHmZJ8AFIn8DeHBlyL6jxa02 +kYxlCH4pmIRQZJzY6OvtopNZ4R4T0GiYC5OVvNJjKjAwwTjENQTF5u58xV8mVmnI +kPmYk2J3ViD6ACUb+ICcjg0ZQvsfqzBN7bS3iKrbzOM83UNsRCl5r7ZK7lozpXBp +ymEOqBdbdPApKbMmlaXA0cE1Z6Ly9hiqc3yaate2bER/j8Rdnps4FGYqC05bbnUf +a9a8EfxM1AyoZDIvOduyiH7X0EsbC0mdLwZu0/CD8VEjNkDJUQMaOCn6TlqXaVr3 +yFEM4G7M5w9Iv8JOfnXRAgMBAAGjUzBRMB0GA1UdDgQWBBT1MipFOQO1sYOZhkoD +Tck58lmZ/TAfBgNVHSMEGDAWgBT1MipFOQO1sYOZhkoDTck58lmZ/TAPBgNVHRMB +Af8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4ICAQBmUHfr4Q4FA91n7GHne9fr3tj2 +9SQykgvK0FrlaFXbbY6xgWhqtY1mpUCXZfSboQ5cguDps2JFZQsXfznspl0jIfbw +OjqIPBI38y82yAkj54EB1gOtoSyB+V6pZIOaSNQw3fMiDXqNjMm/ffwzQBOrpccS +v8+DjojNis5GIeFZPtBTml3jQaKZP32oQg/t8RGF+xODYbEBiK5gfQKF1sc7jp1J +Udc0jlGpYQPBrfIN05elIl0+D2tKPiHupgNod9a8nCf0CjXywh63FYdEBRN6V+ay +/bKU8InWMUkEBBLN3d/jskHH9aNnHM2A3bfUsnEmaq0YVFj2a70qWKiofpCepkFc +I12qYrba/crw31P1DyUQ4dBhKNIvrSwnhu8qdIqi1KpKBAUjxzHydo0PJKt04KRo +0QhdQerx46ydbNlhzqtrDoLeEM5fw/6IbB+RhHRWC0IZdJTKs/W4FUzxklFTfh+F +UFl6G0l8j3lUDcYLCrQYBFKz538YqLHIRweUyyy3zw0QK7X3TcdeT+FXmBbrO53z +zuqnFKxcC8PJSKyrJH9KWjXQuP2wTgMJFj5eVCCrSJ3T9ZRH+P97Pn1P/tghyDfC +/lToFeDPJrPP2wTzNGyoRToQCXOAVMGPILbqxRcVWmlkcQrZnq3x9NTLWSezPUGu +2eebSqIFJ6T2aiPXQQ== +-----END CERTIFICATE----- diff --git a/apigw-private-cdn-acm/example-pattern.json b/apigw-private-cdn-acm/example-pattern.json new file mode 100644 index 000000000..868056f8a --- /dev/null +++ b/apigw-private-cdn-acm/example-pattern.json @@ -0,0 +1,65 @@ +{ + "title": "Amazon API Gateway Private Custom Domain Name", + "description": "Create Amazon API Gateway private REST API with private custom domain name configured with private SSL certificate managed my ACM signed by Amazon Private Certificate Authority.", + "language": "Python", + "level": "200", + "framework": "AWS CloudFormation", + "introBox": { + "headline": "How it works", + "text": [ + "1. Private Certificate Authority and API Gateway Setup\n 1. Creates an PCA\n 2. Issue a root certificate through the PCA\n 3. Create a certificate in ACM using PCA's root certificate\n 4. Create a private REST API in API gateway\n 5. Associate the ACM certificate with API Gateway's private custom domain\n 6. Configure a Lambda function as the API Gateway backend processor\n 7. Deploys a private REST API through API Gateway\n 8. Associate the custom domain with the API Gateway stage", + "2. VPC Endpoints configurations for private communication:\n 1. 'acm-pca' VPC Endpoint - Facilitates communication with PCA\n 2. 'execute-api' VPC Endpoint - Provides private access to the REST API", + "3. DNS Configuration\n 1. Establish a private hosted zone for the domain name\n 2. Creates a CNAME record within the hosted zone for custom domain name\n 3. Points API Gateway's private custom domain name to the 'execute-api' VPC Endpoint DNS name" + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-private-cdn-acm", + "templateURL": "serverless-patterns/apigw-private-cdn-acm", + "projectFolder": "apigw-private-cdn-acm", + "templateFile": "template.yaml" + } + }, + "resources": { + "bullets": [ + { + "text": "Custom domain names for private APIs in API Gateway", + "link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-custom-domains.html" + }, + { + "text": "Tutorial: Create and invoke a custom domain name for private APIs", + "link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-custom-domains-tutorial.html" + } + ] + }, + "deploy": { + "text": [ + "aws cloudformation package --template-file template.yaml --s3-bucket --output-template-file output.yaml", + "aws cloudformation deploy --template-file output.yaml --stack-name apigw-private-cdn-acm --parameter-overrides VpcIdParameter= VpcEndpointSubnetIdsParameter= ApiVPCESecurityGroup= --capabilities CAPABILITY_IAM" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "Delete the stack: aws cloudformation delete-stack --stack-name apigw-private-cdn-acm." + ] + }, + "authors": [ + { + "name": "Vijay Shekhar Rao", + "image": "./images/vijay.jpg", + "bio": "Vijay Shekhar Rao is a Partner Solutions Architect working with global system integrators. Before joining AWS, Vijay spent several years architecting, building, managing, and troubleshooting complex infrastructure for critical systems. When not working, he enjoys time with his family and tries to stay healthy.", + "linkedin": "vsr4321" + }, + { + "name": "Tushar Thapar", + "image": "./images/tusharthapar.jpg", + "bio": "Tushar Thapar is a Cloud Engineer at Amazon Web Services based in Australia.", + "linkedin": "tushar-thapar-b76247120" + } + ] +} diff --git a/apigw-private-cdn-acm/images/architecture.png b/apigw-private-cdn-acm/images/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..2d8b052abdfdc0f97bac78415afc36f4fc39ff8a GIT binary patch literal 77964 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 AUH||9 literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/images/tusharthapar.jpg b/apigw-private-cdn-acm/images/tusharthapar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..954eda7ffc411b7df9c17a29b34241821fe791af GIT binary patch literal 308262 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%0A$`pv83e!6_5>FY-J-f0 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

IO#oB%#=qzdSVSQXQ_MR^NW()2`NW}^e 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 z%0Dr=kMNT?*CNXQ(yK&uZt;?B-FaJ8;I?L%#uvqv=gzB>nNRBWkkou#!L@Ju2%X29 z+Q_CF@2Bdd>ZKUW2z#Vf^^Uscz7Fq5ffetLRvYa&uU55D!6y7q>Dc6O-->1 zxJ|FUTi{jem!JUvY;H>Xm?{~Z_=q}kqqs9VCgh~E(E`)@Ldo4l5fZWaXuqzf%5gCw zRplR4st^1vn6BzSbXY=vd?ljq;$wULq2)n86rlpi3?~)WJK#Kxe;;C(xghyY9qj)B z)Qu9S|A@S!{g?gM+C8(12jms|W&@vw=g5TqPLC_bjk^z%2(m#SOTA4fV1gqOiCe{j zyb7;aPXOItULHHkLPb8bt2ba&uOO00S;epsG{3>55TgKxZCHecavL&(!{FWn+R*+H ziVS1Pv~1{Q0LN2O%gL$!@DA`+gpZ4K{FMs9PM$L}^ST99KLfNp6b)rj1x2&n`UNSH#Z!Z zjoD8}uKZUZ-1YihmgSRBR?3rzjALO7(j$t0odJ5O@bg;#qNwNROUg;v{4`btB-CulVeXTkv`2Y1VBME$~<1cI?l1 zJN>z{Av1<|{wn865mcP5Q&V3tkM|#g+4QakpgIRqO8hT{mL9RU&uno9 z%ue&XhQBco+4XbQcdl}@+0}SF>Ws*(+se&yhjjGo8nS5CLD=VnwgCWL6KazeA% zP5cC~c)^CfYCFXdY7to;elkB5lA_E$T1GK=PTJOPJzc)XphI>Onb24a z>m}w18tM<}0tko_df?AOA6#Wn%vE0}Il9*=aDt0N#t-}33fTuLPSuu);-7Mo-n#b; zNt~83UPAbkgHJ{8{s|V~-f`4Vh4jAIk+5(4mRsN_>8b&SBL5pXb>hLLswzUMuX+<}X3jK+velib?AJBiM6As1uss>8IoD8E^2PeNxr zEvt#3EmQm~LH8a&x}74)_SR+iS8hk&px33Dgna*A;&4v2a_|C~kEA1dz$me|9N2Qw z?q}=i9^okRCEpcAgx*SUo?Pell+{thgx^Kdt99r;Mh`xAhLMFxIF}c9(<9U2ovB zJMbMwb0Flg_>*GQcc~eJZQi3-a{P=1GoWT&Ho^wY5s^SmzH?Z4heZuwD$Gk{6*N9y zsfvFAE&6wWLrQO79qqe;6!z_D<36@6#MjrZXGpgvN){ebei(%hQW`>#X5}-Na)pZl z4nfuWb2F(~&hECd9ar#aMse3rP1HQn9rMR85yyy7klOnyRw9j`^eT@qCI=x#5~sRStwu8l2VD!Hh&~b z^0^ODSOLI(WtUE;gUnKi9d=Wq>PP1J`QlUU2 zsqR@stkK<8%`A-zH=_vQ1q}!o3T7h{%EK%gDkiv^rHg|55#rm$m`pV4f%b=EthF}JwG;poT$5|11QWt8VR*iu|83`rG0Q z!(aE0(#z#Xoe74?xg~=9{3%x|dKAfa2#?yXg1Fi)1<(6&&?y@!G^3TqCK#XivJje+03 zb}n{bAf;#)KrpR9UGjIvD(7o_^!;U#%at!&me%Vn@WaJ`yfKHE5J}j$hreB@`s29C zFFQujxfJMM;o0O8vaX(jB>Yn8l#<&D>PDQa7{Q+KpW(G!kEL#mnc#fBgDm}em8|I} zquH+Bv$jqm0nu-!!?5&KM|QB$dj1FE>-vYRUh~KCjY3?H&KK?)FD(+NmOHpyZHle6 z)#M?7^S)iwj^YcW+W1H$Oc_0`vUki=M(tO2BF&QV1;2?5`c7_&(KJ+r3oPUGM~a57 zQ}ar*u{B69twQIxL-Oti)Ul=W{fnb&&A5(a3EdAnwd!?=vNIYLqn@3?T(cpczK8VZ zzWH8wb;{M-Cr|sNK^x;vn%_Tdv8_H8xlM4tZ}&2WQEHW<;WWOaJ#bBW`G(P(8eQNw zf&;|iv7@0|Ejlu*uMefz=!zFDy37W28jO%5QYEFDjB5`i1zgUY}jqgWA!q?X7t8@JkJMYk4uRzfd1;P< z0YPAEZw{-A7dlwl1R*tg6{>TCuq7}7#Yux9Y-lnmz?l4B=JiL~PJ*WONwUy)C*j5A zcz2x`7z1oj2ahs45IWg&gUPag+f6^GFvARWjltRUC@JSu;$IrxyZw}HdKQIq`&iFsat(cVI@xeq zFWC%v)#=>3A}!lf9^Sym*cAu1De#LBHbb+JnG>hvnM{6V*QG2P%u|qE%ceTG!NK-HqyP0Km;b&j*!>PdHPZD1|N&BN@$i zYlu3;v!$!f+N?J{bf-yYz9}t>oy6th^193PTynRBY4!kEZVNF_WOX!o4CoE%dA+5d zzeFC@p2##9`ZK7JbTT6fu&fhx4y^6v++mqoq<>8MP%LwKhx&tR`v@%W6>8QuNsYmX zy>PpUhGh>=C}t08_G`i}yE_m5bfnLK1_GRf>KNN9C_!N@Y2AdpU{IYSKbuc|Cy39^P+9d(|Iq{k2W1b(vI(8>`uHaRZ`In@HhXZ_J6%7DjL&-7 zyx@hEE4fywHY}WZwFt<(g>UxUF{-7hIl!uDm}3#iW=D8P6QtF1Y`V*NSHg3JK((Og zv;t$Yj5tdYVtrl0;Z1I?EoF+OMDQ^Qjug^Vt+i;pl8!wi9uA)m2FAx%NWT}101U^L zFl>O2b)?&!GHHO^~(B?%GTjcOU$&PU@A`ZR-KU-O0d`qfEfdPu8Cbm?=q()7PGdgwy@ zcK!*ez)%jY8^ZGPH(M#8M=Fo59~Nn(rwS2$f)~V1RrN9c0j^#j2rECn=dN)q5*?mQ zj$HkZ)RUjTR1IhVhLS}H?sp-Ihap{y&~m+JNKmHryl+ygUou_nkgcno)V5mim5M*n z?e^y{+5h6QAO(y>!w6|zg9cJ!1$lDF!jpRCb0hAaX7}PJ=c>4hdP~m?F znd9`2>0Pw7-{28uR0Z0cZ%UkUvik1%nw*K0?7<0r5CAU<`6{f0b@^2S_X&p+z4hWEd71 z3d|PfpCzA<*Dy zETme+exfMPmZbY2z-i?I9Y3&jsA`_)ZDH?FuJ$FMC1Pun4iDryL?#f= zfL}dW_g^?k?ugAQ{V=+thSzPvSQf6VJj-PK(Ct}i3Co@hskmu1_K~)utIQ2;)3N@o zF_jGHWqbGjRZIVKPn511>c}j8FUG#;YUKgz^e`iACZUuC66k{Bb-fA{L3z!;p|cf< z0Efa0y547Ml`>?+A4Z*evqF@v(Tpe%fHx`$T;D?Mg;h)o)LN>WWlAa2030F-3)NSz zcx4RxaEly1DCwK&Ni4;&PEr*0{^j8j(*wNArS4Izx)4249zp)^tCKVTU}p9XLm)cn zmzwaw$~apgT}w3xzBMT9xZ=_2pG`R3~`=RYAq>h14(QPBhU$Rkfe}xHlig6yA56=z#l4}R4 zT#{b3c6D%jS>GFye)0(e;!mGfv}+A;uZ+$uD6sd@_wU{_*}%W1>cj|#YMm1HywLY2 zM$4a}TR01+(rQukMpNxOBmJTR=WB3>-*qMUP2XwfR^cH&Z(gb}`JT6ql#TCc9LS5L7d zS^(Qh9HhnBq^&%~GZ~S_az@V(CRS6e)S^SA{ZcqZh*6ipi#}Gw2AuHX6e>>YxRC|5*wcNDy<=L*mrO$og{+ggbqY`7N4KGVD*kB>uI5 z!Gm4l_s8o*xsSIAB60xhlc0a-VHLe$jaIU*gUwPRIjJ*;ht&(Tqt$P+vnyCGCt?&l zDx@BvpW_tRj~;!3`Yx|ZKYFt;uiijdyevCtz5_TarL`u1WS~0Ck7O1~LbVwnE}BaD zu44T24l!g1FfGhh10n#KeMl#g1>24;wcTL!`xGBOD#pcs~iFqH> z0)F%ZzS!iZN52Oh;C1F2b4?4pwz{3h3+nHNi759_QT_<9Zr`{Ck1u~xrMWPStEKO=Y~ywF@N zBjG0a@<@#vC@+KP--_=#`67*{o~_M|%>6Ptx=B3(JYk=p*Qz}Fj3bsS2%<(@L5lVX zw6$}gRWxCdJi?ExSgHzic>E7qPuaO(7q6^g*YDgstM54yfieptnm922YIr-qJ$=h^ zmAO3krxJjDWsme^w^`TYN$oYCA`vT7bvsG164jB(b5mL^LPw6N>x<$GmmWFFT=eB> zzV}Sj7Q?gL{);j6p&j!%5{Jlo6rYnEG8+Y`4DNlnZisM`p1whXI_nz(tE%Vm=K;Sc zwSRpdd$W)C8u0j^{VHi3;v@3Ry%6DJA+@#LAd$j273Xoso9F#S}z%M+PFd z-5_LF2?1t_wQDke!HQN40zPie0?JExpj#MhNY>KXnLkFVU!;L|;pNylr7EA2Wfeq0j_J{Um+o0K$ z{_SD$OusHeaQ5RwNu?sWV|tOEx#>-4tv5+aznwLrb)q#;%3sB#)sF~ ztS~CbSU}T1?Q0y{<6^pSDs}5}I>X)$Rl+>?d-%^eYEI?Ql*os(r*Qv7x6PG1D{*?G zORvLFoTL#nyF*1yHyYYt+O98IT_V+EsyCw4NS*eNjx&L4gg=oQlA*c~|K7Le-pk_Q zr@quiKLH#+y(nBeu+{%7Lb$9vB?X3UQTEnG*R z3XS^qPWJ=1CdO)soTeTtnpsNgmTD^nJk7@1MK-s;YndJrA?*a&C}ry%kS9wT2P)Tf zPI2l35-gk)$VYn9(cu&uDs`%F$BbS%+Q#QJwkdhhnR$~lxOBrZ?}$(Wke)zOi+N1R z9qQ)P=oOn`{_A&bi30N%m~#{W9tox0iW)H41};yK&s2i z5l@i*8(Gitg7D5)MwJGvUrT!;N>58~%Xf`XNc{g z%ph%^SYBj{LXyr~3`r)9qDb1OR(B%i#_4H`vQtLi+d7Q(E(U@20W&iMHOieOzzVS_ z{bsb&>_@hEV-;htgE)GoSoFpJ0BU2yq$-I-f3{wQwaW0mG*1t%-9K7jG>AcVs@hoy zkBf)wY2={0Z*t&*puKO`Y^?|9#`4Z=O9?!Z>)*`(; zggN&1Y$8e0tu2t99@p|!;H=c9u4#rO@AT|bri18=$#tt6*xZT94V5ShiV3VenXoR% z`HX-C+7mUpo_#fvvoARRlxJ9YYVGYANj#&pIuZOPsK8E?c*sNxmsD%u->s=te8OEi zXRX-D939aSYS)3D5jon#2?=~C(LT4qt+`0I@A_<_Vwqjx+dpVv6d}vGzK*wXsS>7hw69!4422^cdEsKm-P`tF z7`&~XiExX3uJ1#l*R%MC)XoSObj!z2ag$xnZ4Pp5)AF18nnM{}_M4sB31vBsPwwlF znZ=|bZaqgdMXI!D(Ct%P)?33PU?KT*7xNSR%OrOYD!%g)dhk>c`dW~f@y*g;P;<`U zXMh*r+%16ZdY0ocJ(bUh_L2&5!Q*>^r4+uRZubYR^+dMYQ-vEn)U@kcPQtZo>eGrh zqvYbmZspv(fWbpsSC4ijv6S$-Tb4Loojr5^_|HI~N5u0reGfj=m2_ZQOsLMTN|WY7 zRCS~px9)&)pp^DM!1>;89Z#*YwY4z%VP{G0x_}o^;Ta`uRvZ2%{rOgiI#6OgLc<DlOoNF{fmG3{)JKk&$kM#ok zG4)O91^2|93g;QPXX?%FZBf+^rby>8@i#}`Ob+&3)C59XpJ1+k6F>zSlZE3#M+Nqjz);6<=^NtR#XjPrO&h2 zF2iRsk(AfS<);h;XUg{in-S;6&FK}*wjtzr{Yq2$n1k(n!)>%?xxoANx6v2z-^ef! zT5UAR38{taXNw-$yWXhYD7Nok5H&z?>#$H=?{Jsbm;QSO6PVcX@us!T?VZq5mVv0O zY~FKN!$&=j)B>V@I0ss{&-`=z`u6%OF7FYVRBNg@MjeccRFapO^QVq|?EmMb5YDe! zFQDpW)DeJfoy)<#F?`sNN_<{w)?UVMUODIj=5_cW@>e_uMbDw?Cvu{C74el%`% zE6>Q$8xv~N;0ch>5#1KenoN4dr~z?thFvlz*@IQkJ&~1guAtz0rs(pW(b_Q{xZUj? zTOnH~bKrH2OcB06_s5lg(E+)u! zNEf@loz%E<+Eu_ z39xv|oniAA$jZ@(--NA)2f&S-wDzrflCMn+1X0DbNyHK%`m^<&{WfJsc*lX(v$1+!fl>Krj))CNBcdtjUUJSww@?) zv8lf0)Cr0b=cxN;jkel@5XS(XyCUbSRU708yh&fTA>)rvLLrbU`|V0vmqk5Yasg;F z7@^(3$4+YRdMj1r{qbhE?qd5N$4dx+jAlav}ztwp;))9Zz1+?6U5&~oP7;3d{kEPynENE~GuF-Rm zRAk^8>VK@Z;tA1@b6nOrS)+IHUjL3Ta!|R!S)~kDx|3ua6jM^fmu}_$Vb&=;|bfE((M7!5bB@r1`MGJR7&PEVXylmX8g?X3!>ZcYR_2i z)y<>s>Yq7=zkIpxMYk?M#Ej`;53%jJJH{FUVCiSE^h8++xaHrC3;Guvcpdb|wm&+5 zWv?KgJ4vrjWyHN@l{h!>-5+;|PY<``NgiVeTW8D~1UHyUPwrzE6}P_fWs}wuAb|fY zOYFtMcVz9fnYeGk@hpk$s`P7jKcDLm*i?K6`xuxkD$9kg(9Z{@ls=S#`kU4te&5lN0&(gj+x4DyXz()P^djH?0P)lJhuYY$QZmYME5(6FbeD&w!P>0p zt5crnpgMwyoss1FO!`%J7W$R>EjZI5;>-B(RMACgNqc);#I2ngB=6n-08|9Wb1kGr z^ea&MZnvVSq9sQ&S`(d;cobM0(%0|orKS@qs78|X*?2swTFEG=esG)b;-MbZ2eP6o zn-;Gz1i3%vqqYOvdR71MOp;l!dqCBWgr|(IIjPy@DBE7ZoHO+3s!e4^ou9^^9^aXsit@A!!{{4|aVN!K5+!zhUD+L#$?_sCBW~GBZWH{{qRF4- z=_mf%<~xsINK)%W3*y9(VVEk>-cg5n>sdac%|e_+ZY^hx_Qlx-G!hp*pA43(1G8Kr{xYrrMWODT?<8v%u@lzgl$ZI2Br3W{^qN9=tnT=rfJbqr zT=zm;)OC3I2Gkz1K&(GQD})Et&a2zk3_e%$hE8lZxcvmXSJ;WgXgq+`f1pZW#pT!z zVtW`u;Hz;N73Uh^es;8kQQMwRC)_015W#rJSrcK`2C^j8Dp+1;FWnD<#T1`Eh7uA3 zi%pE#0eSz93LYu;d&u8^=bqn@%jvB4zc@;oi*xwp;&2aslZ|V35)1LgO?1H9xjXe) z*J);!2PO^QhwB`Y=fQVw;)Rquz2pKV&TlJXp?YrE zXZOgm-TE}EN`FtkG_f@umoDS1K&K-4MCvK%#AqYm=gSJh*8G{aV?fn>YKgiIFPI^=I6L+Aq)?y#1#c~lRMaTt^JyV0|EwX! zQ%mzLEVR7C$$no3=544nLj5Zff0JgOZc80HJVM9F%F6ZIJv2-xu=ljjj!`U6dS=*&LjT^VBQwiX_`#3ObYzFb;j%d7Ntz` zD7|5MjW9ia%~@jj8j7$Jq}8GUNjv`|9kCGBTV(ciL&wl+RH6QljoRX=aX?tFt#5Yi z*=L9kCjh&UEo-_7VyV7x8eeowPn}~86W0kQD&}?x>b*Q&{oDH5VC8d7H>wo83T&@Z z&wZK|cyt*X{e6UdEECFP_+=LOGD&407}i~YBSxK<$(5y{k1>NRFX9lRHf>p z-XAyXQ=V)08|+C60kS$K*PZfVATYP@gV7N6NuYh!HmG>LAU%xcm!;As>nB-lySg2$ zYi<{1ikQOvUZI(K*D(KU+j>hIW=0qMg z&8Ik`90TeT(b_2qn~yD;pwBV}7++LN=@wv_X99AO*ew;oCm089@#QzYkaG1Y?z20z z>vez#mA(VQtpVUSPcCOrLP?t);Vu+i;h*{#X2ZWhemRTcBZvu(6GPM@*kKLkF50%( zq?~MA`^Ncil?a-4X?m9de45{zKvox@>b1C%RTmSYq}=K!_L`wvy~V=X_3n6vd%Hwv zWEW2466VQ`ktZmHnL|@-i<_rV7`#;kY|-N#PcB0|g3oYDw=Y{yiv^;jC9tAE^h5&= z$V4$buaY_jznvbm{cm8RSUcH5mr-i$T2^?rDAfKq^P&7zJ8T;*E;qit(`cI8M;l>B zzFSB9t>QnuoBV|3z`(>b{7Dei_E7do6l-nRxu3jN3kH&~umh-L-py{5m1TqOLYFIkM{7HtWBVFx{XFSh)2hrV)BMs7HaY+yT=G}u5}tX zy&MFgdyQ z?{dzI&Kh6xddG#s*PiGA|4t8a_45j!gMPAGThH1nT*}L3yN8QB(p3Mj%m2(y1*>EF zTTRI0o3n7GPAmU_dY;V*x8lHfm$VkijoVK<8hyG~9qfQ^>Dbwm#e1?NG4hkbHBD=h zzJd01wfT1?i!gtg*5fZrOKfngNRXh555^%e8}m2=yKX zU+QOm^=Wr`prNTV3S;0Kf#iuqypa(S{Al=D&ZSWH*yX3o`aIrZOH~WLg*_BvxvhaZ z@dBg0@k$_q3i2(D=BpeG`m}w5*hrjWwg3A`;YT{kEc~n1h|n>k+1&TW{K)`qkdd8d znW;cIbVpjbn(Qk|**kucl)I?X|N5PXz3D1?#pdrOYAcseeGi^uZI)-6$e$Z0;CD?Q zq!75CPsyM{n^j}r)=M({k?qmP>JA{1f?Ig6PMuu(l!Ck2AC}l7EVO#-raG!@Afc3= zD800ejWLw9W;Z6#Wuki2?jfDsTG2fBxBP{RFVlR|9H}h=Ny^h#oNyAVODVJj>M|(^ z@5>Qe;0lV7J8Y#kQ{k9XBToux*^xY`nH@;PQz|H;O7J^r<${rplT)oidxNoFo`3Ea z^Rm}wLjg`g0(+B5S01vjNguxgM#?i8e2Uu9TwCAkp-t#mWjkPNzeB=wM97Ytdz&=J zWLu#l0#XL1>)>7!J9-qeoa^F-C#8xpXJhO6C^QCZ0W^SwwLVYv07`( z5S3d+)vwd_LXdhY!G?-VVc*ld1>3I1zw6c6_UIaAJNsvc$^^V)WOcT#fMWq@qVBh%>G^#5-|SyVB5jzb163BF^OAI976I^C1JBQ548(_W5Hy zC2)A7lBtnSH*x+itGV$tGBYbW4qFBcX zS0-@>qzKu$bs#Mn&`fsJ`R$Oohr3|3mbm?sYQbHM$SIE32=Seb0~2^Xh0y4&VhCj$ z_^vPpaKE43zb<4DY?P*%iUpl{r2VgyfjiH53iM8GsTljL>g*;DGa9|cSOZD7!BMhoxraq3pL5*uhs@E z(u{LmzG5K%b^#`p%JlQFB9uo*wEG z-#=p`DwNW$FN1f4b7tCCpw<8~g?3O02!G>&; zRcG2SoEn@5tl`v=k};;Z?k=Ab=djg;vk@4Hw>w@O$q3WCbtO5(v>06<3v#Ajwyh7Y zzkjNa_L=H}ju4XSsvwoFIZdw#_7A6O$gEHUBmU-Hnrvc!^YqUmF39Tx`RmaC00~NXBd-XE$R_4-R-3Xy z7HD5k_fC0?xF*#W7YiPcBe-tIi&RIwr~DS|?7RMGp-c7&5LuU@y56vSU}_e0wk%xn zY-wg42GDuVF#AfbQsy!3Fjx3ghM&ko<1M3#A*oVHVdLN#(jmgYQ8on$A8cr>-r{(- zV9?j5;u3Ooz`sS6#T>bB@!fI=`b~F?xIwYm!9zRy;Hx&5LiCg!pwe@X85UYU9$Mgn z0>_>9uN5CzPZxOGQu&49)N7c~;13OkFhcX-!zCxvFnyNfo~*xB-i>IVL;R-`&sb}c zM4q#^H@|f@_?eVyptGXqqaCbl^<4{mSZT+R4*v_MUx|Ryi>|?J!pGp7TxD0Q={-fY z0+tYCmKhnzYHf@HCo_l5%V4;=kpraw@I@b(zYvt&mHlUmS(ei@kMn}?L_2An3V|&l z9vW?+73#gxC*TeNA5Jtj->$O0o8$?7MMpSbC&u(mmQ){qg(Rm_?zfLsV?Qh1*WuPm z-(-^SRyi78fc3L)hcW%KW8>Mh9~3y60?@k5^lQ8(mD>}vTuj^CKHnuF;N^Ai7p49W zfqoV5*%+N#BqMYZuJ5T@{lsuk2n@&Z0=ac9@^Wjm3g_+1JMepi9%l-TthP?<}pWx*`?qu7B>R64Wc!XwW-G}zw*0GWvdTA zwg{Pev}>H9B?!;a#zxt?at|BU+Mxk$P<2X-59z3Sn?r=RD87pO3Uu?0dD`L=aAV6NX96i4Zn)@e-RjkUig#{xnc>QlAi^mF82*50?}jt2Bprj_9WL<=4m zwJNub?u6a3{VZ(Q=W70B&uwP7J^_~#zQeP6C}k+CneafP22U5zo{O0HJ{<9M7*k%h zvvU$~4)OD*O?6rBA~k!1APZMEzZtm zY2acTxCik``ZFUE&e2&?@MbyL`8B$csAAkE!G*XiAHLu-VF|*fY}SQ>yTy7_DT6imhLh=xCzCF8){KX z8Mnr&ZDg|c1GYn-Ms?yt@(^C|tJU5|y3g#r?ef^{|2-w#=U8WjyC4VbBSV+<=&#zC z1@^8q>tJgRL+1SvwWpZo?gO{)rGIJ3p?h#z(Y6=rE1Mwy{36-xv>p7ScZ*t5L?I3M z@?nC8NdSY4jkXTSDorrfw#Ny!*WdG5&)03bgv==WA3)ecz|M(znpXR}W&6kUkr?S@xted( zj2h7!aWjbajzQb7KOmbY_!IQ8;es9c3xfbJ_rlmmmh_*6yt#V#OD>Zx7Czq@uiL$96x`BYf~sv1wGyO zcv289o1@}I-RfF$UwKB!@m0#pcH}VqdSFI#m8d*^E#`~%y7KqiQqAph;)w-?H=HjX zNox6-Nq_Eg7<)LmV5mDL2Wz@IzCQ493n1%F$L9~xXui1R*PQRj5anzR-|s;&>yN`L zF3wXc3F;ZfDPilmhyzudT17VA@E9j4*Q*r_*})kQpkWB8$E4yoh-Uei{P& z%D+kyC&SYfMW=T7qk7Ul8OvE7fIK;upKF|JYEW-XFG#r>ipVe)m|MZ6{ZSYtW6m-v5H_-0=q^O&At0ozKe&r77V=?a>CXKv@MP!gkrD+l}Cv>z4u;R-ZQJ@Ig4Rt`l z(hh(+K}k{N%{AtrM8C2TttTDVzoDBUTWU1)6=uYLF(R$>Y~PT|8e56fG?0#?;hBtW zO`sm?{1zFsVyPMOE=0n!Te#_Z9UwA^ZT@swR!%6+OT?{SZ-u|hHFP%MBYm3MKRf|? z#AQ5rbHlJk)gO;ie1*N1P;3lUd5+DiVka`G$bjLO>2hdYy(1uWTs*LvJam9={& zen}Vqn@r)$l@SRvM(SkNyY!%?E*7pQ8~h`schc^J?B6Y&_RD+6MhkKZ0;B@1P~7eR zq9QbPtA4Y-TQ}c!;+*oyP&5`0bluZP>&c9GAO0g3@bS+L<1BtPj&r~{s)&* zBdRDBw&FbaIxn=tiBGvMFWVN=`a(u?@r}d$j)~)wQe2oL(Gi~CS`QUiwkWy2DE3c$ z#|DwoVo|d8vmk3UV5M}rr&OTht)0#+rgMEKh|G<2Yr8h0Q_z_%p%6IYg^D(iG+g1s znB^E>e_xzil%NyRV39Ua0+{=Khd%#hY-xjs!FO;{y{=A5ZxP$e{t)k{Pa`Y!PRci6 zE;*@feAPQM$crG=Wy|!W@tx4>eZiVVjn(DVV;X*vJ&$sSVk%n~5;}<=i`ryE@`Bc- znpeT)*J*4p=jIN00nfcueBm3g*w(HE!ZAH z0V%PiS2B8<$Db9Q7>Xb5=8FwaCu}`!fGMH!Vv)K{Uiem{R4USlL2A*oviXsJ4il)j zXLy~FHVb`MQfH0dG@`iGdeueY-YbM%wX5nJlcx8?{wxDuO~Zjsusn8i!ik3O_jH}; z%om1ocU0z7iozoBcXb5}vdQS1b9tTuFGEvSy+qML$4B#Pk2lk-x z$K%V;t;H|XTNVp^LepL=tf41OR6i`n%yAp01Gha%LNoP z{-gAp-biFr-?jd>GpfT6S=A|tB%aj$h1Q`#Evko7c{}8GTTA=}V#@aU%?F`^_jJEm;UG0Zu28n<6NA3RQy;g zr&q$?SpULT8T23zkD8QEXed&!WIK%*CVVwNF#qx_n|Ghu9iG70rp~Rpq}rLtXh{EC zy_>V%TCRN6kzXo-Ia=#{)Eq`!K}hVK@QF^z#W$g$pRqxPSex|o5}luwGxco29@76- zScjRQO^8muAxi<)os4FgqAmPC!m9++I+)>GFqvp(0Wl7iIreq`yMHX3f8BeZJ=&gK z+=C#iCC5~OT@;ya@>ct*Vv#aOs;SzYEt?Y!s9Mj&`0|tWckHf7r6Jbd-Ln2CC)R+b zm!-u6mYic7`J;SNZWEbDZqiljAb0S&&KpF z1SZ4-6N{E>Q%j|+ggf(Nzmr-olFRvPeq60uj)5@Iy!f-KQcRDfe zm(;XAC4qS^E!+tWcW^bO&(xT}!>In@Gx4@P+EX>{;Sm8bd~4BlpJgE}%d-lhOK-oL z0dfVOlDAhayjiX3k84_KBZ={Y?I#i$_7AIs0~`47p(!WcU)5v5Dn5y457bWHZ+2Ax&<>P`bWlv*B$A z>w-~*HA|W=&Le8o=`cem99*!IKc4+W?%v+<3*b9DzChAVt7L6sxnv62t6T>y?;4YC zEWi_A4m&VPwrTqu&;vy@^9=U1=EVqtWK)tAMO#kDhuNWCt``IHAL2`u&IUI!Zh|!g zi3Nw~=@W-O4c~y_TqB!g0IyhSFM5?YdV?02q+Yodj&y3+_)i8TF(Dk@bs%m0kR#Y5n zM0YP&3t1~;py68@XXX=L?tv8RuO0P{Cz-nP`Z6|8?^v=)U_6M|m$qXRq#tFs`UduF8Y3M}8l>jzLC0Q?`e&*+l)mN7t&nXiGGsafzB(nqA&1$wjBmT*p zoT8V1+>cwG&HUtVo4RES+^m-n)ZepZ@5=(nCmwHep(K^!=v6Tx&Kmv9O|;)x7RV zN6RAc@ic_Lb8chsOn);aTZ;B{38LS^MG{Rgpbcc-=9y_ zZxw9Uew75Ifsqik1?0+Qi0v+@SniCox<0_$4op9KGJizEOM*)a|{u zgAjUZd@RP>Sjg)UDIZVbuC z-<#7@S?BwmmT>fFwx4ldY))h*p#m7=DODG8Z3KzdHAPgz5|Es&Q2CYkS9pGQZZSfj zPE%6r;xCf&YX~A`Y(lEm4I@Z)%9J?3S4#}jvUqM@Ke;L8bV|m~wN*PlDGKhOjr8LU zJKa<&KP!Bvhtu3!rnjzPJ}O_iKjb|+Qk#NO`~Bm_fj(c0lrK@Lzq9cj`xao$5S3j6 zZMk6AfR|H`0h)tn{!K-Y{V^7bZhrN(`s>AhPe65`cZ^u#_afb6O68I73Zy`$tRb)y zqGvPK&2tr7B;{ZALU(UNzoF3$W`EPISv|4kLU{S%x4d}4seF!VNQj%ZkG6C9=cuwr zXD6saHtYAoxA$v{x2(MGS8pIKye&zkuBEC6^{ngO37_q%0%9`sJW{(|mm_6k-hTD(;7dwzU0LS}B<_ zM1=y0R79oTc3~GgYv1|XrqMoHM6&AP{2;#J&kBlN2g#paO?R~g! zKOI?io#@+wV}=TfNsJS4+09XYUk&YFKuH+Z*)caH+xXFwwXzVmVyt9w@nqu?eOIS# z^zZcSj zlBk%*sWYCMHGYQ=7gnR^JQ`nmq0p$M%$tXyE!oqr?rHx9mzWVu%HP6NHuD{ z2L72hX9#nF0K6)&r1y+-W8lLrUykG;BomAAk3*?VPIpw(RpEKI&Y^9nC;?=#iJS^_ z!AC3ZKWml&^zSIH3*&BaBp*I}jf|E9Ti>DCd9K?nSTgfrm-s1HHmFx-Wd!Rid9=Ij z(I$WH#H){2sXI}f>TEY_f3$bARtj&-M4SIn;}(I#w%8eD7J!KpsLS$V%x ztJEqz8Vtz!j~{zyY1a^ZCa4V9)roZt5vlhQ3mm$lYuKfb(7gFwv{qEXa zkVyR>0J=GONMo!acTG%t^9%w15t2)KM=Y}|KbK!+l?pp*_Z0HJ+%J?8e)?#tV7=aC zdSyy_3@u*56-^V4*F#*d)xPcCKE@b!V{k<}T$`JkiiyhhT~BWkxPxdzkcN>%OK{z4 zMgNVShB7hzF8^%I7tRPXhcMn&yg+kld>9F4~_ zwsK^h3JGXO6F}hRZN~E25&pM%mVvAHUS0*Fa-hE%`F5nhb^a?W)4=Et{%LwvMp^Tw z+GhJiaPu}mXu~;6Mh0AkUfB#1Dx&nGA&bfYj-E`;vlFl9jrHWN5Kse>$Tw)-|!0EGdenuPA3x-3xN#c>wzN3uU2G z-=Yfz%owv{MxkQ^d2{#|cRxwp@7ocQUmHmbqi#G$K+MWFjL_ zxu^YOsYcaRb*nTOx4iI?3tBYvOem0bMEY)Q2aous65Ng|_8aGn?-jDj6|0|e2>!Di zTkro!B2l;M*eUQGh`ftYR{@jhJ;3s)L>eA6OsGFY$TO-1PmM2MH=CYKtjsgsihO2>q32H~y~%NZGZ9(lkcMly z7U)R@^AjvIVi@cH)Ju}Y-l|8RnghMy!NbajihlUbo<*aa`r;lFRY{w$(}%k^v~&K` z%`ICQmS*+0g<*8PBZHUVxqa&HPFp9W)_V^i2Ry@Efw>1+QEE7<89!V=RB#6>xR8`Q zj_)VgDep>!IGkiw%IpeD6JpES*fN34ahp14RN3+OUGGD~Ec6mq5Nq{U>>LGJqvb%Y zJT_32tC0cXoAic!H5cU!aQu@29%b$()*igsKnIf2WJIzoHz!P;3HHq(Y|ct|BMm)C2g)`?oR0 z1J4WfZnwSD^I=zM+aei75(6@cjDdn9)#+j_#c20iB&`9OlL#)s*2;Zdu_e@1~V93je6vK{T>=o9hgn6nqO4dyuV1A1_@H>_L# z!Q)s#n?-A3(9ozdJf0!=)0OZr0f;Oxen?raf9VpATLE+jejwR(KGC2&8wL0_%XPF& zj|L=>-4vLq)iL%y3b(z>p?Sj_IE`>n*oM|eb;zfT>;j{0iFm!4VmpSGaY%hYu*$CP z_0mS8Qc<>E+0HS6cQh?f6GI`|a(K)~K#$tO7E++n+L12Y$;yJJQKrxmTnlo z;otnVJj6C4ub*AT(I_k7T@>u<&;WJssXb30oN=ZGU*!eO2LV};sB(g?a$*148KR1F z^KsL5_u}F4KaC-lUK+wOw4#!;rUZ%(I;irHz)2eO!F(f|nce!}u%?`;K*AZLYZ`UW zy%zHH_C1TgN(bZ%1HSflQ2h<9l=AI|$LtgyS(5RRT_~MC-?SZs`|_vh>GCwaDb|Cl z{)fLRVVc{=9G4Zs?IbL!)`cIPQ>OenT5YpmCsA^n)hvGx^`POpdWeL4uM>COga1d3 za0Zr&4{KMozn*?%%K&TMlD*}BNkScFe5k0p29BWkcc?`_(15sq2&|MG9h;P_b64R$OU*qek3kFvbCem&qnqm@a0#x`jUq0G4go)B8H{bqC9KW^mZ+TM z$EmR1BuP1${+7PNsOamBikA8DBF`9tg?70-|KSd;GJ%o_;C*;;n97LK(IhS3iIFZp zssNz`{z@~(G{N;LrCeoS*;ZgDH6NIj^NmxtPbdk9l87xhGJhmLP9N;=cpS?}O{up< z5T1LNzKv9MBuU3mqI&8kSHX&5g0}*5?@ME@JzjPS!0U|(`56zTr%A?|eWOGOG;FE8 zxXE-E+SNJLS)R}Yf&D610Pi3kHy?40ePBtBt#?|nyEtatEp~WXD^V(dnD$lY_`ndC z(0=J>K`blDe(I=uqUR#6!TJ|j<20jH68ix~ujeh)K>H#mjp=y7EFJZK8lqSjba}#F z?q38wQO~5L`x`u~z};sUrm)8iICH3n$rX53M$Rp*x97o&?oQ(bd*pB~JM49Zdu#Shsrg#kZ ztl9bbbrL|?avztXFg>i|x|I{;Htm#VNylZSuxnXw#aqHnub4wyd1(Sfc43I&fq=Mi z`LmOo(e6D0^=C^-Cb-woAN8O#uZn^zJp6~tEEtmE0)lw^BsM+73TZ4FFjfNF*st!M zxLy+7K9&84*6;$Yl739m&-8O*3Pov+Q+11Za?Al|U7*Z>if6#Y?!K7P`>mvNt+DJDAsz166D$NuF^C2|!@ zU@&jI z;JB6%9R(H!sdR6?&kto#4umDikIfMfUq)pF4?LD+tCZ5rQW6HHC479MFBD5QzsR-w zj4+ziFr*|3tKGH6E5}Q5CNkRhNf}p~wTsW4N{A2U$$3B)1J8x~|WsTtTrZ1LFKlu+zorqB8D& zm%0cVF@I^@NDst0Csdf_iFv1ums+mEXvN+zE%ERRJGHrZbl!JW}Rs0F7EqXBV6Wv zjKNYM*nh$`r^)#4+f~KP;x2D>HJ6{=7KXidE&YJ4zbedHu~GbK$azujJC%|RzFAht zlDH;nJqhesA|EDg{HmP9uT+m(=5*t4R9|Ct$=uqskS>Av(dBQ;c} zr5x##hBlq3C!H7t4;y%m1Qb<7SN^rtDQ1)v{dl5j^zL+AIkOx_>+$S^HfcpwtAPXs zmL7z=c8cklnT-}7^py>UR71C^hf&?L3 zin!)#d%<2EfmZp+b@+7#G|IP!PA&<36JBGeLAu}wj5r_Hto30<{>uPN7gGKeB%XiK z@d(7X^gMpp)grrN_Oc;$Hpbu5_V1`rz&mb~&$RE_N>1R_7i!DbE~DXc4R~L?mSC{I zhwF0-lm7vhvyP(_P9qUEXD5gJXNwwF`*$&*!6SH~T#o9NiBMT_V0!6e%CX2;HsQUV z3uXm0*5J={xB(_f){b=8j$lqD^wvl(TYq~suh?k)iOsGus@)b4i=F>(OXJOjaCJwf zu-l`*Z)iP;x|+QryHL*uTHxeaf1_M*xMa{*2x$2Ytqp{vblS+Qp58QRyk_aDQSv+A zZ;ejFhVRpoUmbnsRk+}vU`39-QTt9BD|Bt&s{p6Lqym!L_yIT+U1Ic%aX6`Gwa)V> zN-an-M!0notuJPoBPV{+>pReZs2v*xz|G1kRoVB$pK=d@hfpXnS09#$)nm*(o z%(PHb%JO3TsQLP3NQ>kU#{Q4-MRy0cg92uT_eax0AcD!o6I|hZh0nM56z4wSRcn28 z*FE-0jvnmbskiV7Kw&GZpBt?`YFTpp$)btxlKf_232&n?`)AIPF3h)1a4P&~?u1AE zo7k-DqB>C}X)@A_yTslrLB0AA8GL%G&f! zNJRi67;_iVJy@6#yXuSPmVwac%2Rs|;F15D@Y%z>SSJIIV&h7+*m$o%S^9LF3w^GABn1$SKj|TKhKoG|E!E+LXn^ ztMv)-nB_;7bH7e*HaZtzn z>Nc?KK~BI@jBMfxFZD6y>fNg}p<$;<@!Zx5B_2bB%wn1Kz$~oIxn1CNQ*4I-RYok_ z>*lmzAj;?-JljpK=u2^tmP>W1*j8wG{}}=ukLe@WrjYcnN+9}ogWZ;>5wCxdM@k9H zq8FW&nfiViMcE#$nx=2e{s%A>I7}zl*W3QR6OjR}5M{_M&Md~M?K%{MW`s>}h*5WD zGhG|9>F1_l4t;23q~w#MUe%+gZ&72hf(!4@u@KQs#V(SaPu`sbi;l1>O?2Y{G5r`7 z8He`OBB6ef4xP|HDa1=OU$T#ch-*&GVAN_&P_;L7I8=9(Nf^z@y*bhqCQU=EFc2Lt zMAkg5N197s8`=Zzv+XRIv3;lmZbqumCA-kI9;M0&^Ojz7oeUQc5g>KBrRdeYgdoq< zKiwP1_3UB2O|!4ha%r#Bb>Y_+yEbGECD@iGYwLO})pf zBAa0)qVGTNBy@%$_}eIN8FiktHn)ZMwKpp$*<7dkUMP6lBom(XHmi<_YLs3z_MNmW zACyv{gdU=kmJMGP`|=>+=bFRRxUpz~<6DZ!?l6B!{^GAfH>6MWb+^U$bK zHlXs+{E<8j?D-T4K(%WM!nvdeswsp<^|J1qX|=rQCZt(-i*g0cU03|M?VT+K=iqM> zvb*FOr)Q2(7r1*MAIwh)62SQ22UnTKMse!-T`R6 zuULD*qeSonmsctisE>m?d7r@#u98%-ZJNitk&7>8w~zhu`d}o&_uD1C5&c{f_6}Wg z32mcT{I+0?iB*}%`Elh?J(mer&b!c3rBq7|AoA|tgprb{QRQlQ?2fl?mHApY*;zqy ztofCopP$CWK?d?Bw%0>S8`Cce{m^Pi*dLc86GBnKk&^YfLJnm}CXoT`lbuzr0(a}G z$0Mqr2fOp?V>MOJL2SR)~t~|6g%ID7F(|$o!2FaRr5{tl~G*bz+(*4Pu=zY z-AMR>MqF_~fNOss`G?U=MiP@dW=oO%b-G2|nSZY;TP#+EeHx%@*BVgHA!3%(>#B?D z^up$a^~wM3k&82sz|)0p(Efh#m1LeYB#sp6w+c5_mXgxAP$6G1d`)a6C8zozndOo)EQmHfV9t`4dR6?M&laYQ(;vvJRHYw5 zhFL$+P}yVl!z7;=OL{_oRlu^yCWIv1X0)2g&|U>1mZXmBPl%pzH=5ZDYYmSpXlO`- zKEZ`zd_yeC)Fc!04oP(&+sTcwJ6S)bZHuXG)Q(d-f&z6_`Iw35&^}HB#Vy`(DYKjY z$D+7SE4P9#!fUA52Qb73)`V=}Rl2_@=$WmrRzE_$_;w6?zljP`QDOtLS~ALvUEk(N z2=%GCS7tQ&k-Ts5X}6;RpTQ;2I~uKc0cy5VP$r}{Ey>m zcZ$v~k@U_lBQQ6s@WQ$j#|(jJ~>SJ9G^%xiD7! zQB>HW;GS?pmd|qi05nJ*;}D%z#ps|OytL})snv!bTFCQ5FJS1G|Ki^LF>0yV=Gj z+z&Qhzsl7;_Z6WKVZm&uP9lAJybBb$cWLAI{t89*id&E1z4GflCf=7YC=AIXT^~+ZGTr_ zK$b@*)!zKfn*Mw>`bBueKu2>U3&6i1R$dx~6O}d75d-y0M@MutuAHwJ_onAjqe?+t(U7z-|-Ec5Dl@LD;|_#xwsk^h-8CTh)OwE zMskE|c;fr5V~r14!r+rB^NMcGdd6bRufr*uioBk$FaXj!FxcKz=64xgQ;cKMK!=L^ zRW{$iLDueTbA4a%t#aG&jW601&13JVEI+02CWUu%OU#mb?5{n&C-$KOEqM89^X;<&K7NOLQG4Sr4Uv3!}vg3IEg z|Iiz;&K>!75q0+T!5V9)xb=loXx>nHsQ6caSW=2ngdllCzV^*+iwe_WHC!4C9x^VF zIWojNtDEUWRmdFm`H!%KY0{tQ?Itm?SuAu{w^#UsUryCsjvQbEt~?kR=OBoK?+TU! zsoLJQrJHd#134VmmBK`e${fx_5iOoKETJBdTq`SlBxE8o+uZAlt=#g?Y(_)?aD1-O zjE`0PvR6WwBHTkC?`)(-U}x}EVzo*cw3Rce(<0Mv%dR;zMk*@5;>Z83gIF^D2QV6! zqH3Cb=K#sS3Jq6z2AU{b*79}gyfxeO$~{a&KbLD`ACP@8N$vKl3g57Q;eAbvcNzCP z{VJYx1pG(qP&S~oGR^&p7ywnFkwlb@LuI?p8FpzK~LV^#=_{;ZO8H{9-11zd>2c=a)O^h_}$tS2&w zmrlPvF2jmAa`O1VjtG5Q$HNcbi|T>p9LyZG)lc0F^mV39s+HPo;OZJ)mUORGnQj@X z_=#s(oI$MvXqJwrPe_d?kJz1lzLf8*GgE8Ns{Q_pEUNWmgfUa`eoMGH1kXY#&jMd_ zoS+F7G1T9zzwl}qWzG(E2fAN;Q>^$?V-6L%G0Ig!ZY+TV#Hn7DDo+XF!_3OC?(j4T zI8R;0aPtW5BmC+^VWl#m@gADFq^g^R;lq`}pe85<9}3UfPaReWc*i98Jn@sLWV%JH z@&Z4<EaMO$(JxD+#98Kz-3PPB&3Ad-;eda+GqZLH>C#bh)KSBYLf5 zW(##9aHX|SEO0}@Q)OCw18e2&h7|)K1k&h+Zp+d21%;pWdrtT){bJ4D=#zE5ZKGP( zzVD*{%NFzdHh|T?Tt0nta+|c?Q0yC~;$A%#<&t?#uz2apd0qFm-w(njOB8doPIWgp zGxyykXo&AscOS`HUOc1i%#l@5L8CI!G_UX9lcCiO9OWGufm7oz$^^g4l#ezQUTMaWJpy%~~E%JBHn^N@u;6Eim0@$3X9j-ghKARTXT7 z#rz_j?R?2BQP7uYu-iP^?)2PS^;3W{;Fe$$$8bRA!}^qnA)&&@7tj|UeVc-he4-^b z+%$FyGGJ;zlk+h6EptNgDR^hU-)74NcUUBZ)%Hw0qdLi|^bb*5Q%NUBRODwxoVRC0 zt}!S=KH5|!u-Y?xfu|UJ?m@FIYS9<(pF6VqMkhkn%{)!tC+VE;P%g}9m=oj_&sFI% zMnx@NKXXL9ahYNNazjdGWIkBsj3~fogb#{&y9*R*B8oeith4SAbihH4U zDlb-%12*L%f{2I%xR-A!alR%TH#{T6!>lxHgi86DrKI{!^qaL?tcI3G!Tf3W`_6Y` zX!Q>QX(3Kbdt144t}mpAZi|bB-#0W#dkuYhfGt>L zGOqV9RizIk?=_XN#2A;_qFSyTh9P`3XT!WRNjiFxKEVlwPEsF2*k_8fLZ*F(m5Z%7 z$wCCLjwl6aZtsM6h7g9xYVv1@{D3lxSH~q^HH(*r3w;qa7SKKF4!v`b1iqfO#G6sZ z9K@0oH5rEmCyzfrc@HZ{LzCJ7sV_OJdUulKHvvxqi*nm*IekG~s`N&v1_#ScbH@p; z#e?pIH(qMARVG7*c)W`*?4BwghyaH#M@Nflg*FshF~B1zl%QXdM2|8Ve)S50rDwp5 zWC`Z^F6$Qy0LQ=QJr8TUZk9V|r&87D8r!Z6kJ8QmvWY#{NE?Iezp9@spqwGu29p%k zW1}^r&TyX<|{23(^%(_DlKtbt~icoy3g@yIa&~%iA)@ zz&DCpkSn=f*~#R4q+VUd2U`TZfc~ccNDn5Ok)^|pe#zKh_u(-=Z$yL@|#awzAl3h%b`_EcF$ZT5*w ztDT^87UaGr$WnriMR1RUM=1ihtnM#iT9p@u;!_2mJZ(wPxt#ocDc~om^?2fGuj$rf z(7V7=bzYrP7GN($PNvJUz_y7dB6uY-Ho81dCyb=vHjjZ_9GMg8mDP|inpEg350O{* z@T;HoCOtu_t{74OHNUUi(9WvpF5d8}4}GQ1rpsQDh_LUTkiesZFg#5R{06h)Zpiai6dSBqb2Yf*R--MZHv%>HQvlh}gd7(Q? z;y`=3-xq@0USG1k&uD;awQZa<;Wc){h>Q9| z#e@GMVi+Ct*b|WI%S4A@w_X_SE9Jp|Q_!`Fa~_IOvk}H_#q{vy{1%6!HbdD!+%P`) z^^hwG(VJAABl6F|EBo>JXzWEhGEk@ac@}O-|(Wii%c`q+L)%Qar?vN0kY8+ck~J9*I+K zV6ClDYW_vd*IaawJ#_4=P6VP8*Hsn7IL3ww)cnJZ3~R?6>NlB>=Q%k2rgY58*7j&` zBLsS?>Kk_CkvdNyj|*L~tkHIk3?;Je(mG>+A+qlYR(l-E?P9;}+P z?=iYfMCzYnG@D&-H2*%Dk`x{V1zHrmDRh_rU?8j$Y;3ml=y?&N1Q(-~G3lx<21>EblGE+Ohf;42E~1Xa zn@%FNkf!bv9&RTMS{x_p7&#(x{bww4PPp9&(CuFXa}&C}&0fqA$3m4U+#^@~ zP1RPYx(vwh{{SbVp!9t1h`vVNyC7>Hj#OHwrVLYjj$J(Lw&6HQE7SUIz~7}*r(~$QX{3nes;46hbrBv1Xm4Q}XCwyaS%WkeM_T5Uy6 z9dM9LXV^yx#58M5{dj+ycfN&_x@{M&lB6Xd^%i7$3$MI|Y$XRyHg9C+M@OxuV$p>j zc;P$67o2Q28y{>Qm7UF5R`hn$z%Qkogi_*ESYM>@>n3iE-!ukaKcH^$Pw;JQz1sAKUZuhKc-Pa z_BwgsQk5w^+m__6e3|+cP#@f$nyv5#7=7z>G*wpOB=g*=>g0#I>6a{zY0~;BFe-?k zt|v|C-GxC1c*hDI!&w)L-1j01S0rM!%SjE+@~7uM&B2ru8gi^W`MH|zYc}!9YR+;No|#ko;-lUnAt*JBLb}3b*lWeZJOx=R@!xB@CB4W~`;3j`lQ1qOIIvUO|5%Hy zxU5@cBmdQfB7dx{5CNvO5^OJ|(1HyM00*kw^Ol&ER6hb&8%f$uF9rDac7XyVI`iHI zmSCTuoA)wC_xw{>WH&t0vWje06u<~s3e13R5@)yEhm=1(Gc zSi6k|d=7&eZ|N9D7)w%L!z%&un`YQkUxh~>9Dk9dZZc8xyEsQNSfRx>EV+{NxC1Yx z;~DPypNiudQ{o%%!vWDggTZikZr*C{Wp7?rw9M0%=4fe-*-ZhC9(+?!(Xeoc3m3Zs zPS1Pa7(&-Lt#=oKY4J-dj25ytYA&$<=47w4Fg$J;Kz*~}k28<1f|e^e`IBA^=$=IJ zn|KLll#6Rn`nN1AC8*QQs{H?=SUsL-Nr~DqtpidKG>j;E3jI4@Gl&;#?Sf6R(G-0& zP7-Jq$QJOn<;w-YU__v{mbwkf>x)cQP)mmOU=!qzNaeriiS>83||aD-(JT@LKiftPyZhN*ODWzP%?e*HefQM-}^#g z)vqs^@Y=mMBMHSx`FmAX=*i%5cUBCgu`BYOPmg2&yt+Hbhd!2`87*B?m^e|epn_Fl zYI}7Eq)1clAbwITE9`0~0xsGsBy?K0<4LP?z-x#k;LJddw{YY77x`^qR^oN%7rpNH zlBW$w+mP&C{j`?24h_tX$fOLN(y$%F0GryTV)|MRF!l7<%Ij=f2N`$O?d)E(vB-Yp+`QxaapW$UV|7y0T=#{=*9wBFr#h2c&oD{FOm{{{EctIh;wD> z%2DJClv)6Vcq9ExFvlD=pfY9SVwf4i7VD`JB^*Srd7sCpu;z}_8oM~!SDDp*C%I!E z-GwApuhRDDQ64jn!M&^15f!*3%NcyY1vQ@Rrii@c=-)AM!O`M$7BEIu6jR;jyo4o4 z48Vn&81bn097a6Gm+qZn5_&pksw{}!5`@%dDG&Xs?97Eh_OG<`Liz4yU<%5VutLbE z-lJ?04JFed*b(61PrB6I($@v}`=Q+K2M$f4<=gcKqWRUd& zCPLRsENgyODYuq;zQHe^ls7Pya}GUHi$_^c)(2tOaE7;k3r^FB`5Zl6Oml@<;(8Wa z2-PPtE?iBFIh*9gBb@U3QjctY7elNeh8fWG-IO$Aryup9Kv+`6(sb}Ni@+hAi1XB1 z+p_s1U8Tsn*DJ_ow6x1)y~9d+y(nhiSG#PupF=cD1ws}ieENVFX9|*1xv9hw;u>%F zDo58*Dv+#bERY@-9r-(pSOMI4<2>W2-BKJ>8675KE+)LZiF;d^6BuG`C)p+C0prIm zA5g?6o0+2JMCek1FqfaV|Hk&@oGGNHta1p&7pI8aOg`kE@Ix72bMXQVeMafy+ih7x z3ba5}9!i9+RWG=>E$PNdeoFBU6;r;#Sm2un6jr^&n|mkx6W!C8fitFq#_lGq@<()NKzIfo2s9@T^`mjFt?!{%tOBXhQ zatARZkGJ)$bkDkl3i0X@VmAu>DYL3OMt-_Yl=`N7giq@;&X<{*jfU}yNSFa?oz<8} z^}J**NuNa=h&u$7h**k`ypO5X1y*{dNS!VV=p-hG!{$1g> zKei*Af(xVPc7InyWrsb83Q5xm*NriH@>nd?JJ}3z-N3h=2Pt1R8mVyGIBc)>Daokb z+NEh%FX^(ki0UMf$E+sLnaWMwA6@P3!g_GWQ!Pt#gZ+7!doG`ap9l}qa&ieOjtNNy z;58Oc_D4A?;IULRblu^%+pK#z3jf9qUA7olnkvx!)o^ZCL3asuOKZa*`MqLg)L^+L zif;7HpZC}WaQnA-Vyi+83xBGYAH~>7 z7RdC^tGJ zHs7-P)M@M@3$@Zkc2!=SZvT%fI6ba4M%AppM|+QaiWzvybuBa1W3Yc0JWAY^LX7LO z_fyHY-#R!36_>;dzb|dL+meToBGqUO^L3aJSi5KIBuk?mGf>8sM)OmG*fR-Kbt$kz z!>c`UW^4@lkYU@f(BLo6vmRSWC0z0hu&+E9^)2qBfmyWr?bS~Gr);!$YK872ru`C? z>wD_Xg{58KN3RM*xXu96+bO(Ct)JU`SDDjhm$Vv`DZ`d2vtuhMCRTWA3oK}I&kVaR z*r-RV?jKm@j}|d|>gW7Wr|;I8Qo@DXGqv)a_w3~wWl;fz!Yb#oGeUb<;Wv!tj1x>P zDs6@<&0&O>E2O2=`ySsA(fiD_6zB*Ow?e>8{ctA_k804Rh<88)m%_*}}9u@$fbWH!>=)>u2?;uO{6}Xa!k4n~0Y(uW4_q(~f<=ejY!m zEx!?jncP_SA*xP16n>~OV<`5kcEa6|qv|2Mz$w}*w~2$!;Dsc+!YZ!N>YP*bDd8gF zzPbwFOBzQiLYpjZ@qblXdukiKX2v>Q-w4noP+t;F1o{~1{sQVDt&k6i`{uGu`Rj?f zHJNTYvAxhb8Dvp$QnJ&1qJG(QvohZ=vAQbhTy-4gx7Low7c27Ohy|A2`rQ>eCu?s~Jz3|q7Ynvl40wW5smf3Q zcod7$LKjtBF$wLE`wzJ((Mw?;HWi&%4P!5pWcGz2jL6U1%LuOCT^YgU@0ym1{{x^a zI?^kflGZDL@Up4XiBYtlGOiDY2!_L38U{`>)P2CsMAT;FbEA(coIA>#^X=%Q1do4o$E0`nW^ z(d{t-Vx@}PGk7I*lOd)dXLbHC9r|BYTr*bOCwPd6s(OPq+q1DzN6FrXt-dZ0QLh{K zVE3fLE|dxj+tkx(Tc+uyf0V!A4;n8+xD2JL{tK?f&kmAWiOv_B(W2c#llXfS&lkId zu19e|$#S+BX!5om*zTrGzb_0u`J3|DDa1MWKkwh}`pi?O!%L&qD<#%jFq4h#slecq zvGPRZlM}`=f1QUqewB`QYqpCDk7Au|)^iKy9t|Jl)jJ>f=rz)Ny%d@wsWJ+b7^!|9 ztzLAKv_#EdX4mdQUq8yzgC;2Na!(`wZfXH7;&iUH?C6XLHxi7NduKvef?g~4*&zST z0DFn~d!({C*k@6~RsCq7)5~|f*|yXde8@^j{i>)Q)+g8rmH(F)6CpX)bV!Oo}NgJ7po1b5=L>q~aMx&PQZ3Sy;UynY<^%v(vpv0r_ zic;(EWFDy7Xx;Rps&K>xOC{!m)^<$Zd8@<`-*}axRSHnb_39u%8u5N=&CK8Q;L9|X z@w7~53sb{5Qzk3K8T}_v6*fDv9AypZi;Z+2H^{*Ek3=p91o$kQr%C=JtQ@ zP^-^%@6)d}m)AgT%$ehI9a6Ft7;({jCBB?((=&v=FO;0!cW(bba)Sm-p3sNfO-L9m zZGOc1{O0#Fw|Z zfMy5AXz0cTpY)bni`^aPbuvBA{=9t;y1j-W{4RufG0Cad6t7>rQ3X0YwQbs+LfbK~ z7*bCP2dC-Xl?9wC6rsN1Id!~ow5*s_Y@60YD$F-Y&~uo`qBfs~Kxj?3?$)^`l5 zRAx*u#$WZv6f5K3(XygzPCR*X_u@&fBlMy$ikK`aN_;TjTsk_!eDzB@4lf(qRn@a~ zVf=PR(TX6+U57BmH}^fDdCBt2g=`%$vXdrO4RJg#OmA_Oqq3z#Xw}Oqh&quF)I(d) zg3$oJ1&8Vdc)mhA`tXcwFGLV7?unlspl$NJu$zcTJn0Q-?UvTrn_S##L7Jh1-&W9O z*flBT3Nhty0P@k7jI28V#795&t?3 zz}$JwxiczFqzg<)&g8oD;Vqv00|ZL>bSDy!_9L8+|6nQO@LwPtAOo= zKy;$-xqtp31x3`W4a;UYsVfm|fiS#Aa?So}H3t~+Wgu;d%)PM_JVi&Tg%Ik43WvE- zoWnDico*RjDqr(G++9JbmTPc*K~@t2R9UudLpdp?Wav49#8YN<33r>FE^1w@ok|j` zq9~c718W?@l)Lp731$!GBIu1ldFnWIFFD)`ekLm$gAih(`6i31mWkM6B(|6a{Rpov z2c@>#j@N)v(P3>wp)ej|p+nZER{DqN}e0Rm-*pEtGdGDT8hyU|cL1Xu(u9FF7qR!~k2^M>tkTD8ee} zAJoD277pVH#8(Hn0&|$oEVQ+v2x~5mBT}Jvj%5*o(5qynQ{a6{XK~3MAhoDriQy~M61?es>He@%x69y;uX|< z2GF#sVCjXmoXefmAzj|43WBB*5CiUkdmnG+doqaCuMA#Wj-~^+u$;qrm&c1ABs>_K zi#}oF243?Rvy>sz8A1wFuppR^=`K?$50SqHDRE1UOjK7>;$9}@W*2hAdAKDxgk z5mV@tjapy@$1JZh{a_A-W>`1qg6Xg21mN1tQr8FEMm2p$Z9sX4QJ~zbaWZNcA+{U$ z4Ehn;t~!dn`Hx-04<68=-hoV{ztNDg5 zn}yRsnJ&*`686A;BT}INYBL=8X<#9eVR z@ja&^7gDL)sM}vbalsnP>M}&#leH3gSZy7|VIa{CU@I)4A-`reRYHVj14N4Xf>=fc zGQ!XsY1DkKCnyc#HCG)+IU~U|mgtFDn>|K|5mjK0nn#Eiq;N{20l+;>KrfGSo{SK) zA~DyKaFd8G3u;oOGc>V-#QUPmwmzlB3W87KUy7jhHw+LfxE25wsYsx3mZ^mG2u>T- zT==n4E3b&gd10Uki)M3pm09sopt0>L3P!4L<$!y zS8iC&vk)al`JUka05e&ZT}q0^q;eUh?iDAHN z5nd5AARsIo^)myM370S;`QU+(NQq@!4o(>L1bw2cA$!%!>b?@~m%#=AT@W)TOQ;+T z^2VuwGigC+V;02GPnLG8U#Yo5jZ4B#kk5XV1e?!SEN4f#Q-g4j0T6EoT86L&qtJao z;BON5WjKR^!b%Dto~U;ybUKwD&LIffF$}2fEly4#pm@zq;jZF)idVQTvKN@=<`y$; zvlQOpbLI*R0n`vG^(jw?a@&bRZZ*vGnsBb5vIL>s#b`%;FxNp)oab@n;3&r7^n@FZ zXg1qZNGMA{9RxrFQ7H8~j7zw<3Gt~>B}a?YyD;8tZ( zT&u-#HywF4z=PhQfl|wvN`BIMXit_9pmiOX!kkU(f(4es^B4m z<-{dLm3JG#`-6sAbE30yz<2Q#t7l9O6)co8en`+bjEdAObS_A(nkK3aflpn>2uEuR zl~L|wC=RV-USrKc-fsrt5E;)L#W#Z zLD)+eBP$)EYtAdVfyWUTtpfmSFSsdkAF>lr+QL*dR`oA;IkrR`=5k!BB4#+;EU4k9 zQ3S*ZmRPir)7gk1j_Re!veKAYNSVhn*s7wUwuSVHHQ{mKf{C5LbKp}O*D!cs<|%PY zmpJhGE&^wWd_cmitYdR3C`VIDbp>!YfQagq%o~u|r^cnGgpNCku~^m1TthUx6XctH zO|dcH_&jk5c#K%Nn}j9HtCT-+Ou6?A7gs17Qk$}6mOG1&BbY+w5Y%E}nnjIVIg4+T z30Q@30}~^4J}M!3HE|L( z8^p)l4-G>$wicMg8`>aFAH=xGax^1lbI8zV91uVt8_aDfm;r9oM5dHN0KzdF)NTNC z6>Y?2QY}K%*wkPwBY2*`fxT*?1AQE%%_5y{Th}MNz{&1hcF12$0}EelY|tkc#Ip>1 z5{Bd2w;Nb(%()vUbus`w$|G$501zwzX!BR~7W#TO9NM&N+!pH`l@2itV7b|cabjAl zBGZ1+f-+e&@Z3<#c_PimVDOn{D^OYS95zI^d5fCj03(RX%)z}yIG0S}Jteq;(Khrz zY1FEVpyh+AHvlbb#}grGLo#VFIF-JL;b7)p>Yz#6OaaU8R@iS4R*J1L-Rvzy&;I~a z4r!UBX7v@<9vwt$a|BVr1i5vVrZWt(!T7BFMnV%nc1$}#bBIlz@r*=tts@w|Mq#Ka zbq!_(czQJeK720L<;TYSGmOAxOpK5{;um<-vf?0%Gt>ic9s*}AoZMTTi~#^fm<5|W zS`21?_hsUtzU~7eu!jinFiqkNwc-AJ9|SevoJ*RIaAo2W{4x+qDHh7tQO30absTTQ zH3H!m5}d*sgMuWZ5Dm^_nP#J%OQ>dRiF@_qgQ%Jql=IX8HQO>z#6%bd=SB@zGZofr zFc-F~`G#!lXeJKK%#{NY+)ZVhW-YjwsA~}2LlA<+Oz(maPSLB|9djtqS$Spk25LaU zD)h{# zRn=l!tEYF|St#~uqX>=kYG4Yz#yKe&tq}lVuX4e$#xolvhf0jM?M|X#So0bH*@#x4 z9oLnJ&@_IDgv)Zm?$<=boT7>Qmlcv`=3)FGsAFnv3Y*;1;WXJZi80w z1Yg-O+(}^A%wDBgbuel?a~35`R2$qt%3t_}SIiZn@ja0$rXf*ikpf*29u#HEm31S_>{_uqiZiReJ(zs*!x3>! z?gCuf9e8cv@pEsLzXaEvCc2r|w^H_eL|P^0rPi3;&U|mdh_f2APYdpC6EUEdlA^bW z9m|`jV2(%{hY(OjQJH&=TaQt4AEyu~=I)s63V0?s%ETVl6C1UK6wHszSgD!ByyJ+u zxx@@&cQ-Jr+%3V!FsqOC48zbEg(Wt=JWf=cVq!rTWa79ciX5U8r4k28obppwCe3n-UXOODJ;r;E-bdbw=C#$iybr#>5V zikzxsD)9=df>{DIA~hI6Z>-EVBM1^9F~bw{{Sjqt-d7`vC!O004=ORU_-EV zKlqUl8aHgPgK4)R9)U4!Ce2JGu;Ojt@*XeOleu$-4AgjcGWe!9gKX28K(Y5L!9-r6 zpAF*zX&9Fn?mM~6cEGbR;%*pb7%FQLDEo~U7#hq1!);J|nVi4ih!o!{SyO^s<7>0j zxFGESa;?B2b9_O0m$IcOh9T|_W$p#;7=Z>hotdRYy~Y}4C5fZ8dcRQ3BL4tkz5PVd z+C@OQsOB}OyJK12*<=zZmX*{MihM`Vg1~-b48ivbXnhd`6@L({syM!2wFUWcDQgPK zgO{k51A-ugTFJVI2nM#Yn=!mFiWI?@GddtZas7vfuF@YS(y(VWPN&Ev3{V zgMF~~bLuf?23b_$PPYp~Z@H++azpPg(4}E7n6V<&lO%<7mH-UpZWf{9I;8}A1yCaGw17?ewQ#YC}#c5qAq(;wmtV+C%n z)B%DGD1f1Aq8@B5FVxMjCwF{@J1*u1osDZ zD%)0*cFf=oO%c|o1;?rSl@tZjh-;X%q|_Y7-g7m~8-p~1K27+!ehJLtTzBUo^9?0& zIYU;)Ckn*H&Sx=>p)bg>IF*PacN00(^dqXDGUZ|nF5o3hC}X1rW4%GsFwj=s2~KX< zs5M}scQGhwToA5xY^EICGSd2rIQKMEcc_b~ZW)2h#CVxGW!|NWyv+wJL!9*m098M1 z!&C;oS(+yp1vcH&MVf&(6s=p3$YLaE2OVc8X<7$waV63PI+ zNEHKM?^n;a$gw zv&^wY0l9)S{$e?|EY)Jzjs`AX+0+n=iZM23JXBWaFd$~G8XU#VW*NTa)?0uI%D==a zp_}3w6ne7|OiAh|LLUREdRz`orlE-457K6!)*l(PGoiB4M71749;#1)iKY8Yes zM1cC3Xo;zG;uUcVBFSj|h!m|vmh%iDy399l*;pgIeEu6wG2yw!48sm1l9jmlV+cWJ zVMZ9%rAw8a%FgGhS<4F^qDrj1Pe85A0##-K4)pO8cWZCBmrgB#l1~;}S#K)F=TKikqsAJXtTn;k?pZS&PXpIe@9^ zFODJM!t9Fia)72Ta|?<3iK8*h_*5w~(l{(Pl@f~FQVcf0P}^~BZ*aoy6dvVsQKN{t zmu?}fGkTSZWhz)?fm?SA0L!Jkga%$0iFiOWz?t-kwwq3uEP`a^m=uc+hqP28d_*}5 zW%F5mzy}OaZK;Z_O?;~`8Xk{RP(DJ&pUXIO~n%t|vccbkMYDjf1hI0LC_O0cP!Kbe3#;u<`}Z0F)q zuqdZ9Mj;ufLBuk6wZH|;6?ceXZlD`Mn434Cf*FepHN$9d=8S&e8|Cg?A_dWM);iM- z0W+$XPzq&MbLs`IS38I)YAPtOC4*9{e> z=YP3pb$iUj3on?Tywt5t=~&FYWjBr^AhqX&QwD360$?uK?w1BuIK~nhc3{g2{laK( z<`t3-rGreRrkcqT&h;*T%*fyM1KLyel%b*LGUknd6BUMx!mOt&T7p?F6vTkjF^Fg; z3SG@Dm7BORnNT$dvDDV(suJj^G>H{*!-exGXl?;6qsUyEsY)vX{$+>T@QkO2FY&6W2c%RBNv|c5obX!`6g~-t;Fj8RkDnyRz NfAHu3{s032|Jl!iaIXLW literal 0 HcmV?d00001 diff --git a/apigw-private-cdn-acm/images/vijay.jpg b/apigw-private-cdn-acm/images/vijay.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fc526b0be853aabc2fbd3876a9ef9a5359076115 GIT binary patch literal 8859 zcmb7ocTf{f@NYtb6zNTrE}={BT|ipsp;x6tDAJK8pdiv~Xwpdtp$deK2w3PSRR|pk zy(vwpKfk{>^Jd50Mx{Q62J=(kQzWh4FpjGZ$ATA0RX@q(0}3nUjp7CA|@dK5rRqo z$yKQUz<*8&{tK1_Nb*k!NB{zW3GYx7(QpuplF+IcJ+$|YrV~@8Pj46}W#ELs97=nS z?s17rsQJArTmAJ9gXv!;2>%}!|3LmhfQbGHWvBr_5C{Y$BnA+I2>%NL2p|A~sW}K~ zL{;w48rl2OJrs*hFKy_h=M+~RhdKBeH?AK2y2Sy=K>swULDT?cK-qzB(lO1we}*!f zU3}6icrvo}6nh%>$BLgB8mXg*2*4b7!?M`*@96TiOQ{M^UX@bvY7#aCa8L}8sCSgJ zr-+U)>V#!^RXa4LYMD^UT4a=ki2UF#AJd@3QTYZujAEigE>fFOh~B)9r}`RJEyBS} zGOBuaQIag_r$~vdU;ACb#0HM^z>UR7(3KbWepgzBzqlelqEqAU|Y1i6@EJ zE$u~lNARm(-9ywzGUL$bs~#W6l2ChipM&LKIDHc8DMGCwrPgoVN_7h6pJx9VkPgsR zW;|H~sHeU0UAX4(B&Fg9wZBOWgz9}K;*^PbeD8^mc0ZOE{}8gN@GnU+nt%08DxV-N zy>jg5`qPDll7}t(G`on10hvx4^K#<6Z{}@|H@t)F8b4JQha29-`NZY+-?eixEYug6a{$hvN=+04n zr7Oz6DfT1NoPe-ipW??DkI`9UwUBK@ughT$23pS)?ODskNtEID;ui37+>6l0_%62Q z+LSJhhFDv9NK2`Jv1o#{UQkdC5JdHHA)SgnGaAUjiznYce^Zk9$h5DKjO6hX-y#lg zqx3$&%DO6h0Y|}cF4fddz;WsE1==DjCub?ng`0*+Df&L%#($eyfX7)vC@hsUs8C(d z%h=)BhiUZ5@wk45JGLuhxuRKGqGfzTS)_28LAFP9LoyU)YCO6ayN?S>R(agp5LHY= z_hZ5fIGLBvL|c*HXZ3tlO|XSV{E*fSGyf>85b?DU^=lBzqY;P9HWg9{U~n6070$4k zomnz?8L>8)_H|~Ke-nD%8TcbA;JRW;+m#!Wz1PI$&TlE0RB*BRaY?qLND8|uV=}bq zRAFo?!QWHWaWdrf_epof6ru(~MJdCXik{#_x;xfQ!v{%ROssZtK3xoT226N+BiJ8Q zkr=|(jFM_7Hkthy=mN#mc-gB)p|6S>3wy8xRZPYw-Sy9Gj;G`b8oUP0r(z*we#$Y= zxABxoGJ$sL=Abgfh$5*LT{RaZ=#bV^n)iuCjp;n#y5!*iV3Cp0fNht!Fno@T?B+R^ z#Ej_v%Hv#;4knX3KWERP!8T=HtRB(GC{jd}!N?lei$C;)%VUzOs&-8KeO8raOk=DU z4-Y#HQG37t&3Mv2i*eCnbf~oB_JcY3WqQXTdX}MTL9Q9P0zp1zKlz|b4c5~Jp$%lOPl)-9*}7ejLmf2%P8RbUNI~D&=hf{%|>mm{Pa9gAib~N zo}qb$o;3Uy5+TpqbhHn41_I*6&ObC6RgB49X6QiL+Z~^spWFh9 z(zQAD*J?S#q@n{B;Q~-NE^um?{4aZpCci!+|RRd_#16-k1Chw9( z#FMP>U(35pg<`OsXZLb<({Q!3h8ykdRnF?L*k@@#nUilwyVtR~FNS_O!jGdVA#?#M z)=}%{Z;G->x6Y^t;g>sm|#bs%yXMUh?z5{LHZ`<5y#jv`R+X zZ{wO-*Q-SN_ymOR)^{kePngs=UO{0gBC-mah47k;GVJHx>CmNUE=7ub?vNJRMEzeW z|Lp}`VQ69>^r4qkGRl9Z-4Bs=QD1`2`ah4?2u@M9l#DbknUJttCq*kOc{N8i}9z=mLGQZhC5# znNr)roK0hP50hVcs!6v9#a4Ny$qpfX)w|yqsHNKFdlcRAe8c7s92d;=ehq1|H6xmE zW++bbkoDTTbGKd``X1$Mh!)A_ny{PIR>r8c;)FiD$@E$>v&Er8ay&gdo^HpzwX3$7 zBuAT_1eH|jP7ZR{8axk0o;#AlfPd1zady0nC@U+=F;E`QR3bfyGn}de|6+O(gFF3( z%%GX3UkpHkho;~CUUDZMIHpAqQl_gS`iHpPGM&DL`jnn!AnF`lp4-q{TMcSSgbl(j zMecGYw=vUjIt|NKf8%oZsL60`8~8cH;_z;qW{T7|DNGeY#M>QKqTOq8@TX-B+ybcy zu9l7FR+Tbg3KTHfE76YO9$dp492E0mp<{0+xICubz-io66W--&7=0jAhon9o{Tyd4<3BV&`5`w?C}Y_X z)D$SEdf-?@rhsBT(=CAi>?_ee&;B*1g9OJZB% zM3ngxRA1?fiTKmP*OJFCQ$Lo~A;aHMrLFP7fXmolNx@9yAwzr?x z{+A(v(U<8hbXb-n79+#2YGO#?o6?t!s(I;X1%0s$c$AiSbAdXv4pR6cud*RP3%fC% zu&1P|Xx9RVhW^{xmfYXCw33}9&n#iEFM>c)`csbeso7}p4h6hHr3F*;G}B{zHxotM zJpH@m4ON<|w9`JnLb3gbyK>6Jq+$b=-d{z6A?ZfMX@gwQtiwv66iYar*g7*Ggv~*g zy8J_%#d0k5{6cTIB}k!+53&y`&JsRD_4ZBtyQ88O*=1Dei8ur#_zzq56m3dv%>!%s ztSW}SQGPW>8`90cHROf7?&Vu-b4_|1TdDpC``m*(x!o*O{fR_J5^U)E#_P23qgqNN zITtpNz`5ft$Ssslb2!bO?&F1Pry`aYFk_h*|*x~R7)OOcUoE?)%ChVYSd zt^Nv~ua`BzIzK?YFDt|3Fbd_U9Cm_TQ&x@~6WNqskQiSM`Q9g()0ZkfDb#P-hN^$t zG>If#T9$IKBzqs7^N?^vi0g4i={apX6B$3 z-$NEm=TL|?bLB+Z5wZ4Whj{t4x8z5wR<}Cm-j;|g45C){00snKlUZ5}$I*ZKD2i{@ z#}hr?OME!TPe_53(3pshSqas=_j$J0D0q;wkxp~>%@0JS@upxfn?N>(T`Y&#pogwR zK4^t8RbPj@O+PHS$7+3MIUo`Kv6TL9{)YRE>;C=ry!aWHD9u$11SuEqCW*#p$m_3u zGH<_Bgr@8lQ!6(I3`V>W7q|f|Pn5O)%`(vcpoAl(71=3-Qf`wP8M1k{Fyk_TO{ZEUQm* zWBV=r<-*Y$7_sBzdRgdI4>9bey1e5Mf3)Z0zlej;Cj9)`_m@Ncp8Hy9wJ=l~`V0kt z0D$~w7m=rg3YYDA;VLNq(3mME9fN@J3p_lafxj_b>JM{F<{0Hs$|Tln2paMAsX9~W z(_gQ*GnTsGXVikBcPEB(Ljtu>5jr{@m#s+;+u*!;^0_1E*P)#QaJ-lYV|2&fSI3=3f4w_Mfa; z1%K~;xgpiDyu-PulxG||GZP}4V1sRTQ5RJDNn#=7Sdf|%i4<_bdBV;iGUp{WLwi|5<^*m9SO}nUl{q9Hvk#&htA~1_=TEZ4~`1ubcR?>f2w+#+R+!iw|^H zM6RLbf^G7eXzK0iuRey%1&{N+#vK}VbE%fhPykAn67>XLswE>jl%qq#K=0c9FeY^M z!|ik9-OMwkf*t0opNT;(lklQeU0hD45CL%WcL9Z_H|MuzVk=yHISctsyIm7{I*)hT zMMgfTINg|1PY#=o)DoG7)@1h>aQ!S6iQZFuS@cVFz{xZBuGZhxgM+npTi7WceM+uS z*g$&=@X#}XytQdqMR0P+2MZh*`N4`koitvh>Qv>A1p!Rxt?=YrpU8(^!E}v;Fs`G} zZfAU6zOfizp0$>mH>sCac6JEej>XlT>s3cD(UT-fQL>TMe|i;bB-R;ZlPnjfaja zB;#FKs4qEoa@*B!(O#VMSP+{*+q%mB(}(F*)ElLI#HM@m^%toZ^G87$GoQ00$(b~Z8(2|lT~6|< zVnLf@tZ+eCMh3EN&6Y$ND9lAd zqEJ}%^KI96cSxWIN|2*=r3gLfdZ}Z}6tL0v=9N+>uz9#Z@--yI-T3dgU7ZamM6b94zw}f+8<@rT!3S!{Pabyz%V5h z&M{B3v)9^@O(a63FPeo>R*5Z_#y?Vx%)(+?GV(k^RlND?Cr zo3MlTtO*c!MS*P)7u0^&0q<9m=bl`r^MRYXjrp9fmuJc`ok3z!{$*dogIED?yHA0l z9sE;pb#XLKuv*#j%I308=I4PfZF;+>;irc-d zVuvN7;^5-n^yJdF&cxo_O_S+EH zH#TD`t&E8W)UrB43=()EiQ>Db%ADzD0sOTR_KCRBZwq%0KCSi{vdO~RZ%a?CY533) z`JQlc9x~&TGoM(5*1d;rannerRd`iT-S4Ui3F)xz{NBX5!kz?}$+Ar~3Gn6@V%T-1%<`U+w=el#J<6>^{&S7#)1--e-#T(QVU zIWL|SuB1R$EF=p3s~R}PWj)8L^eSlRWko&;w!WHfAd&ADf(2c1{;PHP_o^|AM%gG0 zR|Xo7%@%2npb0WdF3xQmO{R9U-Yn+iczJ(omcUl~Cz5y-eg+d(t~kB^z<+<8P_20J z{N=9dCUc-r=5mO#n7Og)3IB1|PO7QE$=_3$GY{pydQ;Bb1TU^H*gK28D(qJf=D#8L ziKu3ub$%MM-0*)W`szamazUf3e5k zOpJp=TPN&RbqREL@p+MOw86b6v9LEBB=8lls6@sj4S(yN#(FepM9@*rh z{>)aZ4)=<{Bd?Np(O6>kjKuc!p6nGtpKKDQK1QOp*vA3@jlEotc71Cu{BlvgHwYRl^@6d6TKz^i_^vbHF*=0; zFsC_Rrw$~#0T@PyJU1K|pt`t^o7v}5ox<35DVE*vYb;!xI_S=s$R&z3PW;C3*$cM} zS%vFX*7^%S+FR&~LXi1n6d%c%K z=-$gT$PGS5yvi@Vo1sw9Cc^ME(Pd&D4VlLZq^On$eCrk&78}S@Acz8id4?Giv45%NLlw{KQm2S{`g-`OI~Gg7?`wf6r!m!+n9Y3vb!q zt1pqe!*)GrmH@;mJ2=XK9Uz)A%NRdemEP7-8wjBsgr68b>i3CP5k8V?YPc^0{;7DA zm+~BgSo<=J44B&cVd8?^0^;oC% zOJJkOIBt|vWl#splP~&cMTrZ>9A|4f>uhb`XO##(dk)R#RFbh{=3d|V@9R2e&G!UC z-VwT)6>D{Peb3Q76H40lEMw_9y=zn%@E~B4_|vp|3z`cJ_fI(0?W9Q(1kEa>h4Awr ztYbb$iOgh##{oh!P&2`ywvYf(=P~xSKUGaL?~E^+r{AEBvzO0XnkhooD^tvHn>M~Y z2MFZ#TCt_ONI&~Z%d$vbX{1nvo9%#~-^Mbd0FmEOztGtuEFJ*h_s9h&6M=K85@&eOVN*dkE*i`@*IgS-;OJ$!ycQ!&#*3UbW1+^3MU`^(Ww1Bj z4wAzj+^3ivkK6HNh_vv?AF_~}KkoAsx+y-ni@B+LUMuw@S+sQFx4)e4<3fZ>lP>(( z@GT&$vJ~nC*FQ4}=E>sYX;n}!ceumR*?&?uBBE#WXWi@T%#D^&c{SVC=dIYoN2mQ0 zFOm9|rjpDR@iqcQ6~b2-NX{Ia;xOn+babl6xr$sPT8FO-g1ts42i~8U`52HFF|xgE z7;0QDB(7D03Y91Jb@4M4DHak`*ks8l2XOb z;j3!(aiQD*<%(UBLb30QVioh)c>fQ&P>JBK&FYl4GPB*dX&uPbHD{B>1GB0kUiZ94 z?pf~hDs2_zs(kq;xlpo_k42ST<9p3R#@ve@skU`=)jME6U-qm_>8^0WTR`AVR9fd2 zLN0Ml*v5C;uOm`FlwMFkpEbVi0LF0K6PZj?4O2OgB93*~Qn>|G-U6B;e>aT3t_*tn z0`$k!bj{g$&^;$!5w5P6jjE=@L5|=3xu1^~367AiU^6w?&lkttvC`|-dABpKgA0~f zk(s^v0iP|^n@C{FbJtc`dA$`;KH?9641&Tx;a;vR!e50O)Om^->Kv<@xyBZIiP{ z-{X-;mUP6tfLgju*DI>Dm^6TLR`@F8-2t`2#T1xvpH!@J{SB9?Q0d0J(0D-IY%yk7 zp)~7;!_6cs?f$h+ZiGH%rsYYhQEAByTbUSb+>rXU>?I*y5}`lSsVar9m11i|ALZx` z{}9Tx(8YVXcPHCQk6cLmESwr`Y|}u^8-BxfGJl&r(e+vGN~!bE9A4tr^Y~)!#yGs% zatjcMEi-7h`o%UwSej9>H6vLKWi(SYi=-CsZ{6HysAU^ub*iqkvBiuSXkcGLvzD8t zHu+Ch@JeYwX9Xsqi0ujn`dfgSX?-O_px6g}e|e;b$wo!4?CI=T}%n(@91w>U(nr7^Azu*2RaE~MR)r}s2&yMj+J|Tg@>kAkm~lT?b*=ZGfeKn zur+bhH2l6A*x=L^Dp-*gIR)PWaORE`?ewF&<`&XqnH&Zqfj~WE4zy7R7GM%nK2HKm zA?i|lwf^sP++(ZG=22;CwzLVQJgPRoP&KnYc}^8Afdw}kPck{!N6E~B%ktSH58O2m z87_>UgW@g|Mt3QKTV)r$Be@=h1~ys$(9hY*ujhCa_pfF*#MSpL7a{jW)t1;i7pBBM zKUzz{@g(?|c2HBv182*EbGG|)3#d43II?>;r{~py5)R~sJo}crcGJ!0tToQpiUKE& zdV{IkQvY856mH9@^@t+ZuIhffI2GRyM!pT~TBq@S>tCQ=lP&T?0;QPfVB*Y&$Hkp_ zJRXE0W_%wHT)9pO&_+&#*jH=UdAG#~?nk3}+AE)9PM2C8hyo*I}XjPp$^ zeY|LDhb*a%Kd!K3a7u_8vUJZ=y-Wtp%TH*7W*#=AP^);O4wOws*)KI3w+-Tzoieth zQt+RqieVS8B}!K8Dxu@31)@|TjUt=~DGXNpX#cNF2lI9J>FOMnA3aMvW2u-Z=7oq6&`b-NSAkXI>FSb zdGS0m47OcicF?&?d#;Y_i&_+xSNI#ySSFu6j&D8HP7F@-@}|othP*182!E1sXq + Description: List of subnet ids where the VPC Endpoints (execute-api and acm-pca) and Lambda will be created. + + ApiVPCESecurityGroup: + Type: List + Description: Security group id for the VPC Endpoints (execute-api and acm-pca) and Lambda VPC configuration. + +Resources: + + LambdaExecutionRoleACM: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: [lambda.amazonaws.com] + Action: ['sts:AssumeRole'] + Policies: + - PolicyName: execution-role-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - acm:ImportCertificate + - acm:DeleteCertificate + Resource: "*" + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + + AcmCertificateImportLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Runtime: python3.13 + Handler: index.lambda_handler + Role: !GetAtt LambdaExecutionRoleACM.Arn + Code: ./acm-certificate/ + + AcmCertificateImport: + Type: Custom::AcmCertificateImport + Properties: + ServiceToken: !GetAtt AcmCertificateImportLambdaFunction.Arn + + LambdaExecutionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: [lambda.amazonaws.com] + Action: ['sts:AssumeRole'] + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + + PythonLambda: + Type: AWS::Lambda::Function + Properties: + Runtime: python3.13 + Handler: index.lambda_handler + Role: !GetAtt LambdaExecutionRole.Arn + Code: + ZipFile: | + def lambda_handler(event, context): + return { + 'statusCode': 200, + 'body': 'Hello from Private REST API backend!' + } + + LambdaPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !Ref PythonLambda + Action: lambda:InvokeFunction + Principal: apigateway.amazonaws.com + + ApiVPCEndpoint: + Type: AWS::EC2::VPCEndpoint + Properties: + VpcId: !Ref VpcIdParameter + ServiceName: !Sub "com.amazonaws.${AWS::Region}.execute-api" + VpcEndpointType: Interface + PrivateDnsEnabled: true + SubnetIds: !Ref VpcEndpointSubnetIdsParameter + SecurityGroupIds: !Ref ApiVPCESecurityGroup + + PrivateApiGateway: + Type: AWS::ApiGateway::RestApi + Properties: + Name: PrivateAPI + EndpointConfiguration: + Types: + - PRIVATE + VpcEndpointIds: + - !Ref ApiVPCEndpoint + Policy: + Version: "2012-10-17" + Statement: + - Effect: Deny + Principal: "*" + Action: execute-api:Invoke + Resource: execute-api:/* + Condition: + StringNotEquals: + aws:sourceVpce: !Ref ApiVPCEndpoint + - Effect: Allow + Principal: "*" + Action: execute-api:Invoke + Resource: execute-api:/* + + ApiResource: + Type: AWS::ApiGateway::Resource + Properties: + RestApiId: !Ref PrivateApiGateway + ParentId: !GetAtt PrivateApiGateway.RootResourceId + PathPart: mypath + + ApiMethod: + Type: AWS::ApiGateway::Method + DependsOn: + - LambdaPermission + Properties: + RestApiId: !Ref PrivateApiGateway + ResourceId: !Ref ApiResource + HttpMethod: GET + AuthorizationType: NONE + Integration: + Type: AWS_PROXY + IntegrationHttpMethod: POST + Uri: !Sub + - "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations" + - lambdaArn: !GetAtt PythonLambda.Arn + MethodResponses: + - StatusCode: 200 + + ApiDeployment: + Type: AWS::ApiGateway::Deployment + DependsOn: ApiMethod + Properties: + RestApiId: !Ref PrivateApiGateway + + ApiStage: + Type: AWS::ApiGateway::Stage + Properties: + StageName: prod + RestApiId: !Ref PrivateApiGateway + DeploymentId: !Ref ApiDeployment + + ApiGatewayCustomDomain: + Type: AWS::ApiGateway::DomainNameV2 + Properties: + DomainName: !FindInMap [Constants, CustomDomain, Value] + EndpointConfiguration: + Types: + - PRIVATE + CertificateArn: !Ref AcmCertificateImport + SecurityPolicy: TLS_1_2 + Policy: + Fn::ToJsonString: + Statement: + - Effect: Deny + Principal: '*' + Action: execute-api:Invoke + Resource: + - execute-api:/* + Condition: + StringNotEquals: + aws:SourceVpce: !Ref ApiVPCEndpoint + - Effect: Allow + Principal: '*' + Action: execute-api:Invoke + Resource: + - execute-api:/* + + Association: + Type: AWS::ApiGateway::DomainNameAccessAssociation + Properties: + AccessAssociationSource: !Ref ApiVPCEndpoint + AccessAssociationSourceType: VPCE + DomainNameArn: !GetAtt ApiGatewayCustomDomain.DomainNameArn + + Mapping: + Type: AWS::ApiGateway::BasePathMappingV2 + Properties: + BasePath: prod + DomainNameArn: !Ref ApiGatewayCustomDomain + RestApiId: !Ref PrivateApiGateway + Stage: !Ref ApiStage + + ClientLambdaExecutionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: [lambda.amazonaws.com] + Action: ['sts:AssumeRole'] + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole + + APITestingLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Runtime: python3.13 + Handler: index.lambda_handler + Role: !GetAtt ClientLambdaExecutionRole.Arn + Code: ./api-testing/ + VpcConfig: + SecurityGroupIds: !Ref ApiVPCESecurityGroup + SubnetIds: !Ref VpcEndpointSubnetIdsParameter + Environment: + Variables: + CUSTOM_DOMAIN_NAME: !FindInMap [Constants, CustomDomain, Value] + + MyPrivateHostedZone: + Type: AWS::Route53::HostedZone + Properties: + Name: !FindInMap [Constants, DomainName, Value] + VPCs: + - VPCId: !Ref VpcIdParameter + VPCRegion: !Sub '${AWS::Region}' + HostedZoneConfig: + Comment: Private Hosted Zone for API Gateway + + MyRecordSet: + Type: AWS::Route53::RecordSet + Properties: + HostedZoneId: !Ref MyPrivateHostedZone + Name: !FindInMap [Constants, CustomDomain, Value] + ResourceRecords: + - !Select ['1', !Split [':', !Select ['0', !GetAtt ApiVPCEndpoint.DnsEntries]]] + Type: CNAME + TTL: 300 \ No newline at end of file From e8c768469db33ae91c16ffe1d7c9403c2199992e Mon Sep 17 00:00:00 2001 From: tustha <135399114+tustha@users.noreply.github.com> Date: Sun, 6 Apr 2025 12:16:45 +1000 Subject: [PATCH 2/4] Update README.md Updated the steps on how this pattern works. --- apigw-private-cdn-acm/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/apigw-private-cdn-acm/README.md b/apigw-private-cdn-acm/README.md index 5d7a72cad..654bde305 100644 --- a/apigw-private-cdn-acm/README.md +++ b/apigw-private-cdn-acm/README.md @@ -16,7 +16,7 @@ Important: This application uses various AWS Services and there are costs associ - [A VPC with subnets and a security group](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-getting-started.html). The security group must have following conditions: 1. Inbound rule allowing 443 traffic on the VPC CIDR range. 2. Outbound rule allowing 443 traffic on VPC CIDR range. -- [An Amazon S3 bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html) that stores local artifacts, including Lambda function source code required for this deployment. +- [An Amazon S3 bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html) located in the same region as the CloudFormation stack, used to store local artifacts including Lambda function source code required for this deployment. ### How it works @@ -29,17 +29,17 @@ This implementation consists of three major components: 1. Certificate and API Gateway Setup 1. Import a private SSL certificate into ACM 2. Create a private REST API in API gateway - 3. Associate the ACM certificate with API Gateway's private custom domain + 3. Create API Gateway's private custom domain configured with ACM certificate created in step 1 4. Configure a Lambda function as the API Gateway backend processor - 5. Deploys a private REST API through API Gateway + 5. Deploy the private REST API through API Gateway 6. Associate the custom domain with the API Gateway stage -2. "execute-api" VPC Endpoint configuration - Provides private access to the private REST API +2. "execute-api" VPC Endpoint configuration - Provide private access to the private REST API 3. DNS Configuration 1. Establish a private hosted zone for the domain name - 2. Creates a CNAME record within the hosted zone for custom domain name - 3. Points API Gateway's private custom domain name to the "execute-api" VPC Endpoint DNS name + 2. Create a CNAME record within the hosted zone for custom domain name + 3. Point API Gateway's private custom domain name to the "execute-api" VPC Endpoint DNS name ### Deployment Instructions @@ -51,7 +51,7 @@ This implementation consists of three major components: ``` 2. Change directory to the pattern directory: ```bash - cd serverless-patterns/apigw-private-cdn + cd serverless-patterns/apigw-private-cdn-acm ``` 3. Execute the following AWS CLI command after replacing the placeholders (indicated by <>) with their corresponding values: ```bash @@ -64,7 +64,7 @@ This implementation consists of three major components: ```bash aws cloudformation deploy \ --template-file output.yaml \ - --stack-name apigw-private-cdn \ + --stack-name apigw-private-cdn-acm \ --parameter-overrides VpcIdParameter= VpcEndpointSubnetIdsParameter= ApiVPCESecurityGroup= \ --capabilities CAPABILITY_IAM ``` @@ -103,7 +103,7 @@ This implementation consists of three major components: To remove all resources deployed to your AWS account through CloudFormation: ```bash -aws cloudformation delete-stack --stack-name apigw-private-cdn +aws cloudformation delete-stack --stack-name apigw-private-cdn-acm ``` @@ -111,4 +111,4 @@ aws cloudformation delete-stack --stack-name apigw-private-cdn Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. -SPDX-License-Identifier: MIT-0 \ No newline at end of file +SPDX-License-Identifier: MIT-0 From bbecb79f5a8dad8d7013b5fd32e62ea0239cbfda Mon Sep 17 00:00:00 2001 From: tustha <135399114+tustha@users.noreply.github.com> Date: Mon, 7 Apr 2025 09:31:48 +1000 Subject: [PATCH 3/4] Update README.md Updated the title of this pattern to be less than 75 characters. --- apigw-private-cdn-acm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apigw-private-cdn-acm/README.md b/apigw-private-cdn-acm/README.md index 654bde305..58eee52e4 100644 --- a/apigw-private-cdn-acm/README.md +++ b/apigw-private-cdn-acm/README.md @@ -1,4 +1,4 @@ -# Amazon API gateway private REST API with private custom domain name configured with private SSL cert imported and managed by ACM +# Private Custom Domain for API Gateway API Using ACM Private Certificate This pattern enables secure access to a private REST API Gateway using a private custom domain name. The solution utilizes SSL certificates, imported and managed through AWS Certificate Manager (ACM). From 1f05d6f23175ada544e6c03aa6ac41ac7f266ed0 Mon Sep 17 00:00:00 2001 From: tustha <135399114+tustha@users.noreply.github.com> Date: Mon, 7 Apr 2025 09:32:24 +1000 Subject: [PATCH 4/4] Update example-pattern.json Updated the title of this pattern to be less than 75 characters. --- apigw-private-cdn-acm/example-pattern.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apigw-private-cdn-acm/example-pattern.json b/apigw-private-cdn-acm/example-pattern.json index 868056f8a..17cb4d962 100644 --- a/apigw-private-cdn-acm/example-pattern.json +++ b/apigw-private-cdn-acm/example-pattern.json @@ -1,5 +1,5 @@ { - "title": "Amazon API Gateway Private Custom Domain Name", + "title": "Private Custom Domain for API Gateway API Using ACM Private Certificate", "description": "Create Amazon API Gateway private REST API with private custom domain name configured with private SSL certificate managed my ACM signed by Amazon Private Certificate Authority.", "language": "Python", "level": "200",