http-api-tool 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- http_api_tool-0.1.1/LICENSE +201 -0
- http_api_tool-0.1.1/PKG-INFO +504 -0
- http_api_tool-0.1.1/README.md +454 -0
- http_api_tool-0.1.1/pyproject.toml +179 -0
- http_api_tool-0.1.1/src/http_api_tool/__init__.py +17 -0
- http_api_tool-0.1.1/src/http_api_tool/__main__.py +16 -0
- http_api_tool-0.1.1/src/http_api_tool/cli.py +337 -0
- http_api_tool-0.1.1/src/http_api_tool/verifier.py +682 -0
- http_api_tool-0.1.1/tests/test_http_api_tool.py +816 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: http-api-tool
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: A Python HTTP/HTTPS API testing tool for GitHub Actions and CLI usage
|
|
5
|
+
Keywords: http,api,testing,verification,github-actions,curl,monitoring,health-check
|
|
6
|
+
Author-Email: Matthew Watkins <93649628+ModeSevenIndustrialSolutions@users.noreply.github.com>
|
|
7
|
+
Maintainer-Email: Matthew Watkins <93649628+ModeSevenIndustrialSolutions@users.noreply.github.com>
|
|
8
|
+
License: Apache-2.0
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: System Administrators
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
21
|
+
Classifier: Topic :: Software Development :: Testing
|
|
22
|
+
Classifier: Topic :: System :: Monitoring
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Project-URL: Homepage, https://github.com/lfreleng-actions/http-api-tool-docker
|
|
25
|
+
Project-URL: Repository, https://github.com/lfreleng-actions/http-api-tool-docker
|
|
26
|
+
Project-URL: Documentation, https://github.com/lfreleng-actions/http-api-tool-docker/blob/main/README.md
|
|
27
|
+
Project-URL: Bug Tracker, https://github.com/lfreleng-actions/http-api-tool-docker/issues
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
|
+
Requires-Dist: pycurl>=7.45.0
|
|
30
|
+
Requires-Dist: typer[all]>=0.9.0
|
|
31
|
+
Requires-Dist: certifi>=2025.6.15
|
|
32
|
+
Requires-Dist: requests>=2.32.4
|
|
33
|
+
Provides-Extra: test
|
|
34
|
+
Requires-Dist: pytest>=8.0.0; extra == "test"
|
|
35
|
+
Requires-Dist: pytest-cov>=6.2.1; extra == "test"
|
|
36
|
+
Requires-Dist: requests>=2.32.4; extra == "test"
|
|
37
|
+
Requires-Dist: responses>=0.25.0; extra == "test"
|
|
38
|
+
Requires-Dist: coverage[toml]>=7.9.1; extra == "test"
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-cov>=6.2.1; extra == "dev"
|
|
42
|
+
Requires-Dist: black>=24.0.0; extra == "dev"
|
|
43
|
+
Requires-Dist: isort>=5.13.0; extra == "dev"
|
|
44
|
+
Requires-Dist: flake8>=7.0.0; extra == "dev"
|
|
45
|
+
Requires-Dist: bandit>=1.8.0; extra == "dev"
|
|
46
|
+
Requires-Dist: pre-commit>=4.0.0; extra == "dev"
|
|
47
|
+
Requires-Dist: mypy>=1.11.0; extra == "dev"
|
|
48
|
+
Requires-Dist: coverage[toml]>=7.9.1; extra == "dev"
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
|
|
51
|
+
<!--
|
|
52
|
+
SPDX-License-Identifier: Apache-2.0
|
|
53
|
+
SPDX-FileCopyrightText: 2025 The Linux Foundation
|
|
54
|
+
-->
|
|
55
|
+
|
|
56
|
+
# HTTP API Test Tool
|
|
57
|
+
|
|
58
|
+
An HTTP API testing tool for GitHub Actions and command-line usage.
|
|
59
|
+
|
|
60
|
+
This action performs HTTP requests with configurable verification of response
|
|
61
|
+
status, content, headers, and timing. Implemented in Python to modern PEP
|
|
62
|
+
standards, using Typer and pycurl. Avoids JSON escaping issues associated with
|
|
63
|
+
shell code implementations in GitHub actions.
|
|
64
|
+
|
|
65
|
+
## http-api-tool-docker
|
|
66
|
+
|
|
67
|
+
A containerized version of the HTTP API test tool with secure,
|
|
68
|
+
multi-architecture support.
|
|
69
|
+
|
|
70
|
+
### Docker Security Features
|
|
71
|
+
|
|
72
|
+
The Dockerfile implements these security best practices:
|
|
73
|
+
|
|
74
|
+
- **Version Pinning**: uv binary version is explicitly pinned (0.8.4)
|
|
75
|
+
- **Checksum Validation**: Downloads verify against SHA256 checksums to
|
|
76
|
+
prevent MITM attacks
|
|
77
|
+
- **Multi-Architecture Support**: Automatically detects and downloads the
|
|
78
|
+
correct binary for:
|
|
79
|
+
- `linux/amd64` (Intel/AMD x86_64)
|
|
80
|
+
- `linux/arm64` (Apple Silicon/ARM64)
|
|
81
|
+
|
|
82
|
+
### Building the Container
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Build for current platform
|
|
86
|
+
docker build -t http-api-tool .
|
|
87
|
+
|
|
88
|
+
# Build for specific platform
|
|
89
|
+
docker build --platform linux/amd64 -t http-api-tool .
|
|
90
|
+
docker build --platform linux/arm64 -t http-api-tool .
|
|
91
|
+
|
|
92
|
+
# Override uv version
|
|
93
|
+
docker build --build-arg UV_VERSION=0.8.5 -t http-api-tool .
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Container Usage
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Run the tool
|
|
100
|
+
docker run --rm http-api-tool --help
|
|
101
|
+
|
|
102
|
+
# Check uv version in container
|
|
103
|
+
docker run --rm --entrypoint=/usr/local/bin/uv http-api-tool --version
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Features
|
|
107
|
+
|
|
108
|
+
- **Supported HTTP Methods**: Supports GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
|
|
109
|
+
- **Authentication**: Basic Auth via auth_string and custom headers support
|
|
110
|
+
- **Response Validation**: Status code, regex pattern matching, response time limits
|
|
111
|
+
- **Retry Logic**: Configurable exponential backoff with jitter
|
|
112
|
+
- **Dual Usage**: Works as both a CLI tool and GitHub Action
|
|
113
|
+
- **Robust Error Handling**: Detailed error messages and proper exit codes
|
|
114
|
+
- **JSON Safety**: Uses pycurl instead of shell commands to avoid escaping issues
|
|
115
|
+
- **SSL/TLS Support**: Full SSL verification with custom CA bundle support
|
|
116
|
+
- **Response Metrics**: Comprehensive timing and size measurements
|
|
117
|
+
|
|
118
|
+
## Usage
|
|
119
|
+
|
|
120
|
+
### As a GitHub Action
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
- name: Test API Endpoint
|
|
124
|
+
uses: lfreleng-actions/http-api-tool-docker@main
|
|
125
|
+
with:
|
|
126
|
+
url: 'https://api.example.com/health'
|
|
127
|
+
http_method: 'GET'
|
|
128
|
+
expected_http_code: '200'
|
|
129
|
+
curl_timeout: '30'
|
|
130
|
+
max_response_time: '10'
|
|
131
|
+
retries: '3'
|
|
132
|
+
initial_sleep_time: '2'
|
|
133
|
+
|
|
134
|
+
# Example with custom CA certificate
|
|
135
|
+
- name: Test API with Custom CA
|
|
136
|
+
uses: lfreleng-actions/http-api-tool-docker@main
|
|
137
|
+
with:
|
|
138
|
+
url: 'https://internal-api.company.com/health'
|
|
139
|
+
ca_bundle_path: '/path/to/ca-certificates.pem'
|
|
140
|
+
expected_http_code: '200'
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### As a CLI Tool
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Install PDM (if not already installed)
|
|
147
|
+
pip install --no-cache-dir pdm==2.24.2
|
|
148
|
+
|
|
149
|
+
# Install dependencies using PDM with hash verification
|
|
150
|
+
pdm install
|
|
151
|
+
|
|
152
|
+
# Basic usage
|
|
153
|
+
pdm run python -m http_api_tool test --url https://api.example.com/health
|
|
154
|
+
|
|
155
|
+
# Advanced usage
|
|
156
|
+
pdm run python -m http_api_tool test \
|
|
157
|
+
--url https://api.example.com/users \
|
|
158
|
+
--http-method POST \
|
|
159
|
+
--request-body '{"name": "John", "email": "john@example.com"}' \
|
|
160
|
+
--request-headers '{"Content-Type": "application/json"}' \
|
|
161
|
+
--auth-string username:password \
|
|
162
|
+
--expected-http-code 201 \
|
|
163
|
+
--regex '"id":\s*\d+' \
|
|
164
|
+
--curl-timeout 30 \
|
|
165
|
+
--max-response-time 10 \
|
|
166
|
+
--retries 3
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Inputs
|
|
170
|
+
|
|
171
|
+
<!-- markdownlint-disable MD013 -->
|
|
172
|
+
|
|
173
|
+
| Input | Description | Required | Default |
|
|
174
|
+
|-------|-------------|----------|---------|
|
|
175
|
+
| `url` | URL of API server/interface to check | Yes | - |
|
|
176
|
+
| `auth_string` | Authentication string, colon separated username/password | No | - |
|
|
177
|
+
| `service_name` | Name of HTTP/HTTPS API service tested | No | `API Service` |
|
|
178
|
+
| `initial_sleep_time` | Time in seconds between API service connection attempts | No | `1` |
|
|
179
|
+
| `max_delay` | Max delay in seconds between retries | No | `30` |
|
|
180
|
+
| `retries` | Number of retries before declaring service unavailable | No | `3` |
|
|
181
|
+
| `expected_http_code` | HTTP response code to accept from the API service | No | `200` |
|
|
182
|
+
| `regex` | Verify server response with regular expression | No | - |
|
|
183
|
+
| `show_header_json` | Display response header as JSON in action output | No | `false` |
|
|
184
|
+
| `curl_timeout` | Max time in seconds for cURL to wait for a response | No | `5` |
|
|
185
|
+
| `http_method` | HTTP method to use (GET, POST, PUT, etc.) | No | `GET` |
|
|
186
|
+
| `request_body` | Data to send with POST/PUT/PATCH requests | No | - |
|
|
187
|
+
| `content_type` | Content type for the request body | No | `application/json` |
|
|
188
|
+
| `request_headers` | Custom HTTP headers sent in JSON format | No | - |
|
|
189
|
+
| `verify_ssl` | Verify SSL certificates | No | `true` |
|
|
190
|
+
| `ca_bundle_path` | Path to CA bundle file for SSL verification | No | - |
|
|
191
|
+
| `include_response_body` | Include response body in outputs (base64) | No | `false` |
|
|
192
|
+
| `follow_redirects` | Follow HTTP redirects | No | `true` |
|
|
193
|
+
| `max_response_time` | Max acceptable response time in seconds | No | `0` |
|
|
194
|
+
| `connection_reuse` | Reuse connections between requests | No | `true` |
|
|
195
|
+
| `debug` | Enables debugging output | No | `false` |
|
|
196
|
+
| `fail_on_timeout` | Fail if response time exceeds max_response_time | No | `false` |
|
|
197
|
+
|
|
198
|
+
<!-- markdownlint-enable MD013 -->
|
|
199
|
+
|
|
200
|
+
## Outputs
|
|
201
|
+
|
|
202
|
+
| Output | Description |
|
|
203
|
+
|--------|-------------|
|
|
204
|
+
| `time_delay` | Number of seconds waiting for service availability/failure |
|
|
205
|
+
| `response_http_code` | HTTP response code received from the server |
|
|
206
|
+
| `response_header_json` | HTTP response header as JSON |
|
|
207
|
+
| `response_header_size` | HTTP response header size in bytes |
|
|
208
|
+
| `response_body_size` | HTTP response body size in bytes |
|
|
209
|
+
| `regex_match` | Whether the regular expression matched the server reply |
|
|
210
|
+
| `response_body_base64` | Response body base64 encoded (when enabled) |
|
|
211
|
+
| `total_time` | Total time for the request in seconds |
|
|
212
|
+
| `connect_time` | Time to establish connection in seconds |
|
|
213
|
+
| `response_time_exceeded` | Whether response time exceeded max time |
|
|
214
|
+
|
|
215
|
+
## Authentication
|
|
216
|
+
|
|
217
|
+
### Authentication String
|
|
218
|
+
|
|
219
|
+
```yaml
|
|
220
|
+
with:
|
|
221
|
+
auth_string: 'username:password'
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Custom Headers
|
|
225
|
+
|
|
226
|
+
```yaml
|
|
227
|
+
with:
|
|
228
|
+
request_headers: |
|
|
229
|
+
{
|
|
230
|
+
"Authorization": "Bearer your-jwt-token",
|
|
231
|
+
"X-API-Key": "your-api-key",
|
|
232
|
+
"X-Custom-Header": "value"
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Examples
|
|
237
|
+
|
|
238
|
+
### Simple Health Check
|
|
239
|
+
|
|
240
|
+
```yaml
|
|
241
|
+
- name: Health Check
|
|
242
|
+
uses: lfreleng-actions/http-api-tool-docker@main
|
|
243
|
+
with:
|
|
244
|
+
url: 'https://api.example.com/health'
|
|
245
|
+
expected_http_code: '200'
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### POST with JSON Data
|
|
249
|
+
|
|
250
|
+
```yaml
|
|
251
|
+
- name: Create User
|
|
252
|
+
uses: lfreleng-actions/http-api-tool-docker@main
|
|
253
|
+
with:
|
|
254
|
+
url: 'https://api.example.com/users'
|
|
255
|
+
http_method: 'POST'
|
|
256
|
+
request_headers: '{"Content-Type": "application/json"}'
|
|
257
|
+
request_body: '{"name": "John Doe", "email": "john@example.com"}'
|
|
258
|
+
expected_http_code: '201'
|
|
259
|
+
regex: '"id":\s*\d+'
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Authenticated Request with Retry
|
|
263
|
+
|
|
264
|
+
```yaml
|
|
265
|
+
- name: Get Protected Resource
|
|
266
|
+
uses: lfreleng-actions/http-api-tool-docker@main
|
|
267
|
+
with:
|
|
268
|
+
url: 'https://api.example.com/protected'
|
|
269
|
+
request_headers: '{"Authorization": "Bearer ${{ secrets.API_TOKEN }}"}'
|
|
270
|
+
retries: '5'
|
|
271
|
+
initial_sleep_time: '2'
|
|
272
|
+
curl_timeout: '30'
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Response Validation
|
|
276
|
+
|
|
277
|
+
```yaml
|
|
278
|
+
- name: Test API Response
|
|
279
|
+
uses: lfreleng-actions/http-api-tool-docker@main
|
|
280
|
+
with:
|
|
281
|
+
url: 'https://api.example.com/status'
|
|
282
|
+
regex: '"status":\s*"ok"'
|
|
283
|
+
max_response_time: '5'
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Error Handling
|
|
287
|
+
|
|
288
|
+
The action provides detailed error messages for common scenarios:
|
|
289
|
+
|
|
290
|
+
- **Connection Errors**: Network connectivity issues
|
|
291
|
+
- **Timeout Errors**: Request or connection timeouts
|
|
292
|
+
- **Authentication Errors**: Invalid credentials
|
|
293
|
+
- **Validation Errors**: Unexpected status codes or response patterns
|
|
294
|
+
- **SSL Errors**: Certificate verification failures
|
|
295
|
+
|
|
296
|
+
## Development
|
|
297
|
+
|
|
298
|
+
### Running Tests
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
# Install PDM (if not already installed)
|
|
302
|
+
pip install --no-cache-dir pdm==2.24.2
|
|
303
|
+
|
|
304
|
+
# Install development dependencies with hash verification
|
|
305
|
+
pdm install --dev
|
|
306
|
+
|
|
307
|
+
# Run tests
|
|
308
|
+
pdm run pytest tests/ -v
|
|
309
|
+
|
|
310
|
+
# Run with coverage
|
|
311
|
+
pdm run pytest tests/ --cov=http_api_tool --cov-report=html
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Pre-commit Hooks
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
# Install pre-commit (included in dev dependencies)
|
|
318
|
+
pdm install --dev
|
|
319
|
+
|
|
320
|
+
# Install hooks
|
|
321
|
+
pdm run pre-commit install
|
|
322
|
+
|
|
323
|
+
# Run hooks manually
|
|
324
|
+
pdm run pre-commit run --all-files
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Docker Requirements Management
|
|
328
|
+
|
|
329
|
+
The Docker image uses a **dynamic requirements generation** approach where the
|
|
330
|
+
Docker build process generates the `requirements-docker.txt` file to
|
|
331
|
+
ensure correct platform compatibility.
|
|
332
|
+
|
|
333
|
+
If you need to manually regenerate for local development:
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
# Regenerate requirements-docker.txt with all dependencies and hashes
|
|
337
|
+
python3 scripts/generate_requirements.py \
|
|
338
|
+
--platform linux_x86_64 \
|
|
339
|
+
--python-version 311 \
|
|
340
|
+
--output requirements-docker.txt \
|
|
341
|
+
--comment "PDM and all its dependencies for Linux x86_64 platform" \
|
|
342
|
+
pdm==2.24.2
|
|
343
|
+
|
|
344
|
+
# Or specify a different PDM version
|
|
345
|
+
python3 scripts/generate_requirements.py \
|
|
346
|
+
--platform linux_x86_64 \
|
|
347
|
+
--python-version 311 \
|
|
348
|
+
--output requirements-docker.txt \
|
|
349
|
+
--comment "PDM and all its dependencies for Linux x86_64 platform" \
|
|
350
|
+
pdm==2.26.0
|
|
351
|
+
|
|
352
|
+
# Test the Docker build
|
|
353
|
+
docker build . --platform linux/arm64 -t http-api-tool-test
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
The `requirements-docker.txt` file contains:
|
|
357
|
+
|
|
358
|
+
- PDM and all its transitive dependencies
|
|
359
|
+
- SHA256 hashes for Linux ARM64 platform
|
|
360
|
+
- Security protection against supply chain attacks
|
|
361
|
+
- Ensures reproducible Docker builds
|
|
362
|
+
|
|
363
|
+
**When to regenerate:**
|
|
364
|
+
|
|
365
|
+
- Updating PDM version in the project
|
|
366
|
+
- Docker build failures with hash verification errors
|
|
367
|
+
- Setting up the project for the first time
|
|
368
|
+
- After changes to `pyproject.toml` affecting PDM dependencies
|
|
369
|
+
|
|
370
|
+
### Local Development
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
# Test CLI functionality
|
|
374
|
+
pdm run python -m http_api_tool test --help
|
|
375
|
+
|
|
376
|
+
# Test against local server
|
|
377
|
+
python -m http.server 8000 &
|
|
378
|
+
pdm run python -m http_api_tool test --url http://localhost:8000
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Testing with go-httpbin Service
|
|
382
|
+
|
|
383
|
+
For testing HTTP API functionality, you can either use the go-httpbin GitHub
|
|
384
|
+
Action for workflows or set up a local go-httpbin service for development.
|
|
385
|
+
|
|
386
|
+
#### Using the go-httpbin GitHub Action
|
|
387
|
+
|
|
388
|
+
For GitHub Actions workflows, use the standalone go-httpbin action to set up an
|
|
389
|
+
HTTPS testing service:
|
|
390
|
+
|
|
391
|
+
<!-- markdownlint-disable MD013 -->
|
|
392
|
+
|
|
393
|
+
```yaml
|
|
394
|
+
steps:
|
|
395
|
+
- name: Setup go-httpbin HTTPS service
|
|
396
|
+
uses: lfreleng-actions/go-httpbin-action@fd9c3701056fc2e667542ac66b4a63c44faea6c5 # v0.1.0
|
|
397
|
+
id: httpbin
|
|
398
|
+
with:
|
|
399
|
+
debug: 'true'
|
|
400
|
+
port: '8080'
|
|
401
|
+
|
|
402
|
+
- name: Test API with go-httpbin
|
|
403
|
+
uses: lfreleng-actions/http-api-tool-docker@main
|
|
404
|
+
with:
|
|
405
|
+
url: 'https://localhost:8080/get'
|
|
406
|
+
ca_bundle_path: 'mkcert-ca.pem'
|
|
407
|
+
expected_http_code: '200'
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
<!-- markdownlint-enable MD013 -->
|
|
411
|
+
|
|
412
|
+
#### Using Local go-httpbin Service for Development
|
|
413
|
+
|
|
414
|
+
For local development and testing:
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
# Start local go-httpbin service
|
|
418
|
+
make setup-go-httpbin
|
|
419
|
+
|
|
420
|
+
# Test Docker container against local service
|
|
421
|
+
make test-with-httpbin
|
|
422
|
+
|
|
423
|
+
# Manual testing with local service
|
|
424
|
+
docker run --rm --network host \
|
|
425
|
+
-v $(PWD)/mkcert-ca.pem:/tmp/mkcert-ca.pem:ro \
|
|
426
|
+
http-api-tool \
|
|
427
|
+
test \
|
|
428
|
+
--url https://localhost:8080/get \
|
|
429
|
+
--http-method GET \
|
|
430
|
+
--expected-http-code 200 \
|
|
431
|
+
--ca-bundle-path /tmp/mkcert-ca.pem
|
|
432
|
+
|
|
433
|
+
# Stop local service when done
|
|
434
|
+
make stop-go-httpbin
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
The local go-httpbin service provides all the same endpoints as httpbin.org
|
|
438
|
+
but runs locally for faster, more reliable testing.
|
|
439
|
+
|
|
440
|
+
The `setup-go-httpbin` target automatically:
|
|
441
|
+
|
|
442
|
+
- Installs mkcert if not present
|
|
443
|
+
- Creates a local Certificate Authority (CA)
|
|
444
|
+
- Generates SSL certificates for localhost
|
|
445
|
+
- Saves the CA certificate as `mkcert-ca.pem` in the project root
|
|
446
|
+
- Starts the go-httpbin service with proper HTTPS support
|
|
447
|
+
|
|
448
|
+
This ensures that SSL certificate validation remains enabled for all tests,
|
|
449
|
+
providing a more realistic testing environment.
|
|
450
|
+
|
|
451
|
+
## Migration from Shell Version
|
|
452
|
+
|
|
453
|
+
If you're migrating from the original shell-based implementation:
|
|
454
|
+
|
|
455
|
+
1. **Input Compatibility**: Most inputs remain the same with updated naming
|
|
456
|
+
2. **Output Compatibility**: Outputs are similar with enhanced information
|
|
457
|
+
3. **Behavior Changes**:
|
|
458
|
+
- Better JSON handling (no more escaping issues)
|
|
459
|
+
- More robust error reporting
|
|
460
|
+
- Improved retry logic with exponential backoff
|
|
461
|
+
- Better SSL/TLS handling
|
|
462
|
+
- Enhanced debugging output
|
|
463
|
+
- More comprehensive response metrics
|
|
464
|
+
|
|
465
|
+
## Migration to PDM
|
|
466
|
+
|
|
467
|
+
This project uses PDM (Python Dependency Manager) for dependency management:
|
|
468
|
+
|
|
469
|
+
### For Development
|
|
470
|
+
|
|
471
|
+
Install dependencies with:
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
pip install --no-cache-dir pdm==2.24.2
|
|
475
|
+
pdm install --dev
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
Run unit tests with:
|
|
479
|
+
|
|
480
|
+
```bash
|
|
481
|
+
pdm run pytest tests/ -v
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
## Requirements
|
|
485
|
+
|
|
486
|
+
- Python 3.10+
|
|
487
|
+
- PDM (Python Dependency Manager)
|
|
488
|
+
- pycurl
|
|
489
|
+
- typer (for CLI usage)
|
|
490
|
+
|
|
491
|
+
PDM manages dependencies, with hash-verified lock files for reproducible builds.
|
|
492
|
+
|
|
493
|
+
## License
|
|
494
|
+
|
|
495
|
+
Apache-2.0 License. See [LICENSE](LICENSE) for details.
|
|
496
|
+
|
|
497
|
+
## Contributing
|
|
498
|
+
|
|
499
|
+
1. Fork the repository
|
|
500
|
+
2. Create a feature branch
|
|
501
|
+
3. Make your changes
|
|
502
|
+
4. Add tests for new functionality
|
|
503
|
+
5. Run pre-commit hooks
|
|
504
|
+
6. Submit a pull request
|