mirror of
https://github.com/seemueller-io/hyper-custom-cert.git
synced 2025-09-08 22:46:45 +00:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3c057be552 | ||
![]() |
5165fe791a | ||
![]() |
4b6e203d2b | ||
![]() |
99086fb4c5 | ||
![]() |
612c1d30dd | ||
![]() |
5676dbef76 | ||
![]() |
dcae449dc6 |
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
@@ -70,3 +70,8 @@ jobs:
|
||||
if [ -n "${{ matrix.features }}" ]; then FLAGS="$FLAGS --features ${{ matrix.features }}"; fi
|
||||
echo "Running: cargo test $FLAGS -- --nocapture"
|
||||
cargo test $FLAGS -- --nocapture
|
||||
|
||||
- name: Build Docs
|
||||
shell: bash
|
||||
run: |
|
||||
cargo doc -p hyper-custom-cert --no-deps
|
||||
|
153
.github/workflows/docs.yml
vendored
153
.github/workflows/docs.yml
vendored
@@ -1,153 +0,0 @@
|
||||
name: Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
name: Build and validate documentation
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: crates/hyper-custom-cert
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: default-features
|
||||
features: ""
|
||||
no-default-features: false
|
||||
- name: no-default-features
|
||||
features: ""
|
||||
no-default-features: true
|
||||
- name: rustls
|
||||
features: "rustls"
|
||||
no-default-features: true
|
||||
- name: insecure-dangerous
|
||||
features: "insecure-dangerous"
|
||||
no-default-features: false
|
||||
- name: all-features
|
||||
features: "rustls,insecure-dangerous"
|
||||
no-default-features: true
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Setup Rust
|
||||
run: rustup update stable && rustup default stable
|
||||
|
||||
- name: Build documentation
|
||||
shell: bash
|
||||
run: |
|
||||
FLAGS=""
|
||||
if [ "${{ matrix.no-default-features }}" = "true" ]; then FLAGS="$FLAGS --no-default-features"; fi
|
||||
if [ -n "${{ matrix.features }}" ]; then FLAGS="$FLAGS --features ${{ matrix.features }}"; fi
|
||||
echo "Running: cargo doc $FLAGS --no-deps"
|
||||
cargo doc $FLAGS --no-deps
|
||||
|
||||
- name: Check documentation warnings
|
||||
shell: bash
|
||||
run: |
|
||||
FLAGS=""
|
||||
if [ "${{ matrix.no-default-features }}" = "true" ]; then FLAGS="$FLAGS --no-default-features"; fi
|
||||
if [ -n "${{ matrix.features }}" ]; then FLAGS="$FLAGS --features ${{ matrix.features }}"; fi
|
||||
echo "Running: cargo doc $FLAGS --no-deps"
|
||||
RUSTDOCFLAGS="-D warnings" cargo doc $FLAGS --no-deps
|
||||
|
||||
- name: Test documentation examples
|
||||
shell: bash
|
||||
run: |
|
||||
FLAGS=""
|
||||
if [ "${{ matrix.no-default-features }}" = "true" ]; then FLAGS="$FLAGS --no-default-features"; fi
|
||||
if [ -n "${{ matrix.features }}" ]; then FLAGS="$FLAGS --features ${{ matrix.features }}"; fi
|
||||
echo "Running: cargo test --doc $FLAGS"
|
||||
cargo test --doc $FLAGS
|
||||
|
||||
readme-sync:
|
||||
name: Check README synchronization
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Setup Rust
|
||||
run: rustup update stable && rustup default stable
|
||||
|
||||
|
||||
- name: Install cargo-readme
|
||||
run: cargo install cargo-readme
|
||||
|
||||
- name: Check README is up to date
|
||||
working-directory: crates/hyper-custom-cert
|
||||
run: |
|
||||
# Generate README from lib.rs documentation
|
||||
cargo readme > README_generated.md
|
||||
|
||||
# Compare with existing README
|
||||
if ! diff -u README.md README_generated.md; then
|
||||
echo "ERROR: README.md is not synchronized with lib.rs documentation"
|
||||
echo "Run 'cargo readme > README.md' in crates/hyper-custom-cert/ to update"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean up
|
||||
rm README_generated.md
|
||||
|
||||
link-check:
|
||||
name: Check documentation links
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Setup Rust
|
||||
run: rustup update stable && rustup default stable
|
||||
|
||||
- name: Build documentation
|
||||
working-directory: crates/hyper-custom-cert
|
||||
run: cargo doc --all-features --no-deps
|
||||
|
||||
- name: Install lychee
|
||||
run: |
|
||||
curl -sSL https://github.com/lycheeverse/lychee/releases/latest/download/lychee-x86_64-unknown-linux-gnu.tar.gz | tar xz
|
||||
sudo mv lychee /usr/local/bin/
|
||||
|
||||
- name: Check links in documentation
|
||||
run: |
|
||||
# Check links in generated documentation
|
||||
lychee 'crates/hyper-custom-cert/target/doc/**/*.html' --exclude-path target --base crates/hyper-custom-cert/target/doc
|
||||
|
||||
# Check links in README files
|
||||
lychee README.md crates/hyper-custom-cert/README.md
|
82
.github/workflows/release.yml
vendored
82
.github/workflows/release.yml
vendored
@@ -9,9 +9,79 @@ env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
name: Build and validate documentation
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: crates/hyper-custom-cert
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: default-features
|
||||
features: ""
|
||||
no-default-features: false
|
||||
- name: no-default-features
|
||||
features: ""
|
||||
no-default-features: true
|
||||
- name: rustls
|
||||
features: "rustls"
|
||||
no-default-features: true
|
||||
- name: insecure-dangerous
|
||||
features: "insecure-dangerous"
|
||||
no-default-features: false
|
||||
- name: all-features
|
||||
features: "rustls,insecure-dangerous"
|
||||
no-default-features: true
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Setup Rust
|
||||
run: rustup update stable && rustup default stable
|
||||
|
||||
- name: Build documentation
|
||||
shell: bash
|
||||
run: |
|
||||
FLAGS=""
|
||||
if [ "${{ matrix.no-default-features }}" = "true" ]; then FLAGS="$FLAGS --no-default-features"; fi
|
||||
if [ -n "${{ matrix.features }}" ]; then FLAGS="$FLAGS --features ${{ matrix.features }}"; fi
|
||||
echo "Running: cargo doc $FLAGS --no-deps"
|
||||
cargo doc $FLAGS --no-deps
|
||||
|
||||
- name: Check documentation warnings
|
||||
shell: bash
|
||||
run: |
|
||||
FLAGS=""
|
||||
if [ "${{ matrix.no-default-features }}" = "true" ]; then FLAGS="$FLAGS --no-default-features"; fi
|
||||
if [ -n "${{ matrix.features }}" ]; then FLAGS="$FLAGS --features ${{ matrix.features }}"; fi
|
||||
echo "Running: cargo doc $FLAGS --no-deps"
|
||||
RUSTDOCFLAGS="-D warnings" cargo doc $FLAGS --no-deps
|
||||
|
||||
- name: Test documentation examples
|
||||
shell: bash
|
||||
run: |
|
||||
FLAGS=""
|
||||
if [ "${{ matrix.no-default-features }}" = "true" ]; then FLAGS="$FLAGS --no-default-features"; fi
|
||||
if [ -n "${{ matrix.features }}" ]; then FLAGS="$FLAGS --features ${{ matrix.features }}"; fi
|
||||
echo "Running: cargo test --doc $FLAGS"
|
||||
cargo test --doc $FLAGS
|
||||
|
||||
test:
|
||||
name: Test before release
|
||||
runs-on: ubuntu-latest
|
||||
needs: docs
|
||||
defaults:
|
||||
run:
|
||||
working-directory: crates/hyper-custom-cert
|
||||
@@ -75,9 +145,12 @@ jobs:
|
||||
echo "Running: cargo test $FLAGS -- --nocapture"
|
||||
cargo test $FLAGS -- --nocapture
|
||||
|
||||
|
||||
publish:
|
||||
name: Publish to crates.io
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write # Required for OIDC token exchange https://crates.io/docs/trusted-publishing
|
||||
needs: test
|
||||
defaults:
|
||||
run:
|
||||
@@ -108,10 +181,13 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Publish to crates.io
|
||||
# See Trusted publishing: https://crates.io/docs/trusted-publishing
|
||||
- uses: rust-lang/crates-io-auth-action@v1
|
||||
id: auth
|
||||
|
||||
- run: cargo publish
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
run: cargo publish
|
||||
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
|
||||
|
||||
release:
|
||||
name: Create GitHub Release
|
||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -364,7 +364,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-custom-cert"
|
||||
version = "0.1.4"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"hyper-rustls",
|
||||
"hyper-tls",
|
||||
|
14
LICENSE
Normal file
14
LICENSE
Normal file
@@ -0,0 +1,14 @@
|
||||
Licensed under either of
|
||||
|
||||
* Apache License, Version 2.0
|
||||
(LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license
|
||||
(LICENSE-MIT or http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
## Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
|
||||
dual licensed as above, without any additional terms or conditions.
|
193
LICENSE-APACHE
Normal file
193
LICENSE-APACHE
Normal file
@@ -0,0 +1,193 @@
|
||||
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 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
|
||||
(which shall not include communications that are conspicuously
|
||||
marked or otherwise designated in writing by the copyright owner
|
||||
as "Not a Contribution").
|
||||
|
||||
"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 use, reproduce, modify, 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, trademark, patent,
|
||||
attribution and other 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 notice and additional terms or conditions
|
||||
for use, reproduction, or distribution of Your Work 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 Support. When 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 support.
|
||||
|
||||
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.
|
21
LICENSE-MIT
Normal file
21
LICENSE-MIT
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 hyper-custom-cert 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.
|
@@ -17,12 +17,7 @@ A small, ergonomic HTTP client wrapper around hyper with optional support for cu
|
||||
|
||||
## Quick Start
|
||||
|
||||
Add this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
hyper-custom-cert = "0.1.0"
|
||||
```
|
||||
`cargo add hyper-custom-cert`
|
||||
|
||||
### Basic Usage (Secure Default)
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "hyper-custom-cert"
|
||||
version = "0.1.6"
|
||||
edition = "2021"
|
||||
version = "0.3.1"
|
||||
edition = "2024"
|
||||
description = "A small, ergonomic HTTP client wrapper around hyper with optional support for custom Root CAs and a dev-only insecure mode for self-signed certificates."
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/seemueller-io/hyper-custom-cert"
|
||||
@@ -38,5 +38,5 @@ rustls = ["dep:hyper-rustls", "dep:rustls-pemfile"]
|
||||
insecure-dangerous = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = false
|
||||
all-features = true
|
||||
no-default-features = false
|
||||
|
@@ -1,232 +1,286 @@
|
||||
# hyper-custom-cert
|
||||
|
||||
[](https://crates.io/crates/hyper-custom-cert)
|
||||
[](https://docs.rs/hyper-custom-cert)
|
||||
[](https://github.com/seemueller-io/http_client/actions)
|
||||
[](https://docs.rs/hyper-custom-cert)
|
||||
[](LICENSE)
|
||||
|
||||
A reusable HTTP client builder API with clear, security‑focused feature flags for selecting your TLS backend and security posture.
|
||||
A small, ergonomic HTTP client wrapper around hyper with optional support for custom Root CAs and a dev-only insecure mode for self-signed certificates.
|
||||
|
||||
This crate is derived from a reference implementation in this repository (under `reference-implementation/`), but is designed as a reusable library with a more robust and explicit configuration surface. Networking internals are intentionally abstracted for now; the focus is on a secure, ergonomic API.
|
||||
## Features
|
||||
|
||||
## Features and TLS strategy
|
||||
- **Secure by Default**: Uses the operating system's native trust store via `native-tls`
|
||||
- **Custom CA Support**: Optional `rustls` feature for connecting to services with custom Certificate Authorities
|
||||
- **Development Mode**: Optional `insecure-dangerous` feature for testing with self-signed certificates (⚠️ **NEVER use in production**)
|
||||
- **WebAssembly Compatible**: Proper WASM support with appropriate security constraints
|
||||
- **Certificate Pinning**: Advanced security feature for production environments
|
||||
- **Builder Pattern**: Ergonomic configuration with sensible defaults
|
||||
|
||||
- Default: `native-tls`
|
||||
- Uses the operating system trust store via `hyper-tls`/`native-tls`.
|
||||
- Secure default for connecting to standard, publicly trusted endpoints.
|
||||
## Quick Start
|
||||
|
||||
- Optional: `rustls`
|
||||
- Uses `hyper-rustls`.
|
||||
- Activates the `with_root_ca_pem` method on the builder, allowing you to trust a custom Root CA (recommended approach for custom/private CAs).
|
||||
`cargo add hyper-custom-cert`
|
||||
|
||||
- Optional: `insecure-dangerous`
|
||||
- Unlocks `insecure_accept_invalid_certs(true)` and `HttpClient::with_self_signed_certs()`.
|
||||
- IMPORTANT: This is for local development/testing only and must NEVER be used in production.
|
||||
### Basic Usage (Secure Default)
|
||||
|
||||
See SECURITY.md for a thorough discussion of these modes and when to use them.
|
||||
```rust
|
||||
use hyper_custom_cert::HttpClient;
|
||||
|
||||
## Quick start
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Uses OS trust store by default - secure for public HTTPS endpoints
|
||||
let client = HttpClient::new();
|
||||
|
||||
- Default (native-tls):
|
||||
```bash
|
||||
cargo build -p hyper-custom-cert
|
||||
cargo run -p hyper-custom-cert --example self-signed-certs
|
||||
// Make requests to publicly trusted endpoints
|
||||
client.request("https://httpbin.org/get").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
- With rustls (custom Root CA support):
|
||||
```bash
|
||||
cargo build -p hyper-custom-cert --no-default-features --features rustls
|
||||
cargo run -p hyper-custom-cert --no-default-features --features rustls --example self-signed-certs
|
||||
### Custom Root CA (Production)
|
||||
|
||||
For connecting to services with custom/private Certificate Authorities:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
hyper-custom-cert = { version = "0.1.0", features = ["rustls"] }
|
||||
```
|
||||
|
||||
- Insecure (dangerous, dev only):
|
||||
```bash
|
||||
# With native-tls
|
||||
cargo build -p hyper-custom-cert --features insecure-dangerous
|
||||
cargo run -p hyper-custom-cert --features insecure-dangerous --example self-signed-certs
|
||||
```rust
|
||||
use hyper_custom_cert::HttpClient;
|
||||
|
||||
# With rustls
|
||||
cargo build -p hyper-custom-cert --no-default-features --features rustls,insecure-dangerous
|
||||
cargo run -p hyper-custom-cert --no-default-features --features rustls,insecure-dangerous --example self-signed-certs
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Load your organization's Root CA
|
||||
let client = HttpClient::builder()
|
||||
.with_root_ca_file("path/to/your-org-root-ca.pem")
|
||||
.build();
|
||||
|
||||
// Now you can connect to services signed by your custom CA
|
||||
client.request("https://internal.your-org.com/api").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Builder API overview
|
||||
### Certificate Pinning (Enhanced Security)
|
||||
|
||||
```rust,ignore
|
||||
For high-security environments where you want to pin specific certificates:
|
||||
|
||||
```rust
|
||||
use hyper_custom_cert::HttpClient;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// SHA-256 fingerprints of certificates you want to accept
|
||||
let pin1 = [0x12, 0x34, /* ... 30 more bytes */];
|
||||
let pin2 = [0xab, 0xcd, /* ... 30 more bytes */];
|
||||
|
||||
let client = HttpClient::builder()
|
||||
.with_pinned_cert_sha256(vec![pin1, pin2])
|
||||
.build();
|
||||
|
||||
// Only accepts connections to certificates matching the pins
|
||||
client.request("https://secure-api.example.com").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### Development/Testing Only (⚠️ Dangerous)
|
||||
|
||||
**WARNING**: This mode disables certificate validation. Only use for local development and testing.
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
hyper-custom-cert = { version = "0.1.0", features = ["insecure-dangerous"] }
|
||||
```
|
||||
|
||||
```rust
|
||||
use hyper_custom_cert::HttpClient;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// ⚠️ EXTREMELY DANGEROUS - Only for local development
|
||||
let client = HttpClient::builder()
|
||||
.insecure_accept_invalid_certs(true)
|
||||
.build();
|
||||
|
||||
// Can connect to self-signed certificates (NOT for production!)
|
||||
client.request("https://localhost:8443").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Builder Methods
|
||||
|
||||
```rust
|
||||
use hyper_custom_cert::HttpClient;
|
||||
use std::time::Duration;
|
||||
use std::collections::HashMap;
|
||||
|
||||
let mut headers = HashMap::new();
|
||||
headers.insert("x-app".into(), "demo".into());
|
||||
headers.insert("User-Agent".to_string(), "MyApp/1.0".to_string());
|
||||
|
||||
let mut builder = HttpClient::builder()
|
||||
.with_timeout(Duration::from_secs(10))
|
||||
.with_default_headers(headers);
|
||||
|
||||
// When the `rustls` feature is enabled, you can add a custom Root CA:
|
||||
#[cfg(feature = "rustls")]
|
||||
{
|
||||
// Option 1: Load CA certificate from raw PEM bytes
|
||||
builder = builder.with_root_ca_pem(include_bytes!("../examples-data/root-ca.pem"));
|
||||
|
||||
// Option 2: Load CA certificate from a file path
|
||||
builder = builder.with_root_ca_file("path/to/root-ca.pem");
|
||||
|
||||
// Option 3: Using std::path::Path
|
||||
use std::path::Path;
|
||||
let ca_path = Path::new("certs/custom-ca.pem");
|
||||
builder = builder.with_root_ca_file(ca_path);
|
||||
|
||||
// Option 4: Certificate pinning for additional security
|
||||
let pin1: [u8; 32] = [
|
||||
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
|
||||
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00,
|
||||
0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07, 0x18
|
||||
];
|
||||
let pin2: [u8; 32] = [
|
||||
0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
|
||||
0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
|
||||
];
|
||||
builder = builder.with_pinned_cert_sha256(vec![pin1, pin2]);
|
||||
}
|
||||
|
||||
let client = builder.build();
|
||||
|
||||
// During local development only:
|
||||
#[cfg(feature = "insecure-dangerous")]
|
||||
{
|
||||
let dev_client = HttpClient::with_self_signed_certs();
|
||||
let dev_client2 = HttpClient::builder()
|
||||
.insecure_accept_invalid_certs(true)
|
||||
.build();
|
||||
}
|
||||
```
|
||||
|
||||
## Selecting features
|
||||
|
||||
- Native TLS (default):
|
||||
- `cargo add hyper-custom-cert` (or no extra flags if in this workspace)
|
||||
- `cargo build`
|
||||
|
||||
- Rustls:
|
||||
- `cargo build --no-default-features --features rustls`
|
||||
|
||||
- Insecure (dangerous, dev only):
|
||||
- With native TLS: `cargo build --features insecure-dangerous`
|
||||
- With rustls: `cargo build --no-default-features --features rustls,insecure-dangerous`
|
||||
|
||||
## WASM Support
|
||||
|
||||
This library's WASM build is **primarily intended for edge runtime environments** such as Cloudflare Workers, Deno Deploy, Vercel Edge Functions, and similar serverless edge computing platforms.
|
||||
|
||||
### Edge Runtime Usage (Primary Use Case)
|
||||
|
||||
Edge runtimes provide a more capable WASM environment compared to browsers, often supporting custom certificate configuration and advanced TLS features:
|
||||
|
||||
**Capabilities in Edge Runtimes:**
|
||||
- **Custom Root CA Support:** Methods like `with_root_ca_pem()` and `with_root_ca_file()` are typically supported
|
||||
- **Certificate Pinning:** The `with_pinned_cert_sha256()` method may be available depending on the runtime
|
||||
- **Flexible TLS Configuration:** Full control over certificate validation and TLS settings
|
||||
- **No Same-Origin Policy:** Direct network access without browser security restrictions
|
||||
|
||||
**Recommended Approach for Edge Runtimes:**
|
||||
```rust,ignore
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
// For edge runtimes, full custom CA support is typically available
|
||||
#[cfg(feature = "rustls")]
|
||||
let client = HttpClient::builder()
|
||||
.with_timeout(Duration::from_secs(10))
|
||||
.with_root_ca_pem(include_bytes!("../certs/root-ca.pem"))
|
||||
.with_timeout(Duration::from_secs(30))
|
||||
.with_default_headers(headers)
|
||||
.with_root_ca_file("custom-ca.pem") // Requires 'rustls' feature
|
||||
.build();
|
||||
```
|
||||
|
||||
// Certificate pinning for additional security
|
||||
let pin: [u8; 32] = [/* your certificate SHA-256 hash */];
|
||||
let client_with_pinning = HttpClient::builder()
|
||||
.with_pinned_cert_sha256(vec![pin])
|
||||
.build();
|
||||
### Available Methods
|
||||
|
||||
| Method | Feature Required | Description |
|
||||
|--------|-----------------|-------------|
|
||||
| `new()` | None | Creates client with OS trust store (secure default) |
|
||||
| `builder()` | None | Returns a builder for custom configuration |
|
||||
| `with_timeout(Duration)` | None | Sets request timeout |
|
||||
| `with_default_headers(HashMap)` | None | Sets default headers for all requests |
|
||||
| `with_root_ca_pem(&[u8])` | `rustls` | Adds custom CA from PEM bytes |
|
||||
| `with_root_ca_file(Path)` | `rustls` | Adds custom CA from PEM file |
|
||||
| `with_pinned_cert_sha256(Vec<[u8; 32]>)` | `rustls` | Enables certificate pinning |
|
||||
| `insecure_accept_invalid_certs(bool)` | `insecure-dangerous` | ⚠️ Disables certificate validation |
|
||||
| `with_self_signed_certs()` | `insecure-dangerous` | ⚠️ Convenience for self-signed certs |
|
||||
|
||||
## Feature Flags
|
||||
|
||||
### `native-tls` (Default)
|
||||
|
||||
- **Default**: ✅ Enabled
|
||||
- **Security**: ✅ Secure - Uses OS trust store
|
||||
- **Use Case**: Public HTTPS endpoints with standard certificates
|
||||
- **Dependencies**: `hyper-tls`, `native-tls`
|
||||
|
||||
### `rustls`
|
||||
|
||||
- **Default**: ❌ Disabled
|
||||
- **Security**: ✅ Secure - Custom CA validation
|
||||
- **Use Case**: Private/custom Certificate Authorities
|
||||
- **Dependencies**: `hyper-rustls`, `rustls-pemfile`
|
||||
- **Enables**: `with_root_ca_pem()`, `with_root_ca_file()`, `with_pinned_cert_sha256()`
|
||||
|
||||
### `insecure-dangerous`
|
||||
|
||||
- **Default**: ❌ Disabled
|
||||
- **Security**: ❌ **EXTREMELY DANGEROUS**
|
||||
- **Use Case**: **Development/testing ONLY**
|
||||
- **Warning**: **NEVER enable in production**
|
||||
- **Enables**: `insecure_accept_invalid_certs()`, `with_self_signed_certs()`
|
||||
|
||||
## WebAssembly (WASM) Support
|
||||
|
||||
This crate supports WebAssembly targets with important security considerations:
|
||||
|
||||
```rust
|
||||
// WASM builds will compile, but certain operations are restricted
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
let client = HttpClient::new(); // ✅ Works
|
||||
// Custom CA operations may return WasmNotImplemented errors
|
||||
}
|
||||
```
|
||||
|
||||
**Popular Edge Runtime Platforms:**
|
||||
- **Cloudflare Workers:** Full WASM support with network capabilities
|
||||
- **Deno Deploy:** TypeScript/JavaScript runtime with WASM modules
|
||||
- **Vercel Edge Functions:** Next.js edge runtime environment
|
||||
- **Fastly Compute@Edge:** High-performance edge computing platform
|
||||
- **AWS Lambda@Edge:** Serverless edge functions
|
||||
**WASM Limitations:**
|
||||
- Custom Root CA installation requires browser/OS-level certificate management
|
||||
- Some TLS configuration options may not be available
|
||||
- Certificate pinning may be limited by browser security policies
|
||||
|
||||
### Browser Usage (Limited Support)
|
||||
**Browser Certificate Installation:**
|
||||
1. Download your organization's Root CA certificate
|
||||
2. Install it in your browser's certificate store
|
||||
3. Mark it as trusted for websites
|
||||
4. Your WASM application will then trust endpoints signed by that CA
|
||||
|
||||
When running in browser environments, WASM operates under significant security restrictions:
|
||||
## Error Handling
|
||||
|
||||
**Browser Limitations:**
|
||||
- **No Custom Root CA Support:** Methods like `with_root_ca_pem()` and `with_root_ca_file()` may return `WasmNotImplemented` errors
|
||||
- **No Certificate Pinning:** The `with_pinned_cert_sha256()` method is not available in browser environments
|
||||
- **Browser-Controlled Trust:** All certificate validation is handled by the browser's built-in certificate store
|
||||
- **Same-Origin Policy:** Cross-origin requests are subject to CORS policies and browser security models
|
||||
```rust
|
||||
use hyper_custom_cert::{HttpClient, ClientError};
|
||||
|
||||
**Browser Development Guidance:**
|
||||
```rust,ignore
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
// For browser WASM, rely on browser's built-in certificate validation
|
||||
match client.request("https://example.com").await {
|
||||
Ok(_) => println!("Request successful"),
|
||||
Err(ClientError::WasmNotImplemented) => {
|
||||
println!("This operation isn't supported in WASM");
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Request failed: {}", e);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### Production Recommendations
|
||||
|
||||
1. **Use Default Mode**: Stick with `native-tls` for public endpoints
|
||||
2. **Custom CA Only When Needed**: Only use `rustls` feature when connecting to private CAs
|
||||
3. **Never Use `insecure-dangerous`**: This feature should never be enabled in production
|
||||
4. **Keep Dependencies Updated**: Monitor for security advisories
|
||||
5. **Certificate Pinning**: Consider pinning for high-security applications
|
||||
|
||||
### Development vs Production
|
||||
|
||||
```rust
|
||||
// ✅ GOOD: Production configuration
|
||||
#[cfg(not(debug_assertions))]
|
||||
let client = HttpClient::new(); // Uses OS trust store
|
||||
|
||||
// ✅ GOOD: Development configuration
|
||||
#[cfg(debug_assertions)]
|
||||
let client = HttpClient::builder()
|
||||
.with_timeout(Duration::from_secs(10))
|
||||
.insecure_accept_invalid_certs(true) // Only in debug builds
|
||||
.build();
|
||||
}
|
||||
```
|
||||
|
||||
For development with self-signed certificates in browsers, you'll need to install certificates in the browser's certificate store rather than configuring them programmatically.
|
||||
## Examples
|
||||
|
||||
### Environment Detection
|
||||
See the `examples/` directory for complete working examples:
|
||||
|
||||
To handle both edge runtime and browser environments gracefully:
|
||||
- `examples/self-signed-certs/` - Comprehensive examples for all modes
|
||||
- Example of connecting to public endpoints (default mode)
|
||||
- Example of using custom Root CA for private services
|
||||
- Example of development mode with self-signed certificates
|
||||
|
||||
```rust,ignore
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
// Attempt edge runtime configuration, fall back to basic setup
|
||||
let mut builder = HttpClient::builder()
|
||||
.with_timeout(Duration::from_secs(10));
|
||||
## Testing
|
||||
|
||||
#[cfg(feature = "rustls")]
|
||||
{
|
||||
// Try to use custom CA - this will work in edge runtimes
|
||||
// but may fail in browsers
|
||||
match std::panic::catch_unwind(|| {
|
||||
builder.with_root_ca_pem(include_bytes!("../certs/root-ca.pem"))
|
||||
}) {
|
||||
Ok(configured_builder) => builder = configured_builder,
|
||||
Err(_) => {
|
||||
// Fallback for browser environments
|
||||
eprintln!("Custom CA configuration not supported in this WASM environment");
|
||||
}
|
||||
}
|
||||
}
|
||||
```bash
|
||||
# Test with default features
|
||||
cargo test
|
||||
|
||||
let client = builder.build();
|
||||
}
|
||||
# Test with rustls features
|
||||
cargo test --features rustls
|
||||
|
||||
# Test with all features (for development)
|
||||
cargo test --features rustls,insecure-dangerous
|
||||
|
||||
# Test WASM compatibility
|
||||
cargo test --target wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
### Production Considerations
|
||||
## Contributing
|
||||
|
||||
**For Edge Runtimes:**
|
||||
- Leverage full TLS configuration capabilities available in your edge platform
|
||||
- Use custom CAs and certificate pinning for enhanced security
|
||||
- Test certificate handling across different edge runtime providers
|
||||
- Consider platform-specific TLS optimizations
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Add tests for new functionality
|
||||
5. Ensure all tests pass: `cargo test --all-features`
|
||||
6. Submit a pull request
|
||||
|
||||
**For Browser Applications:**
|
||||
- Always use proper SSL/TLS certificates from trusted CAs
|
||||
- Consider using Let's Encrypt or other automated certificate management solutions
|
||||
- Document any certificate requirements clearly for end users
|
||||
- Plan for browser security policy limitations
|
||||
## License
|
||||
|
||||
## Security Notes
|
||||
This project is licensed under either of:
|
||||
|
||||
- Prefer the default `native-tls` or the `rustls` feature for production.
|
||||
- The `insecure-dangerous` feature must never be enabled in production; it bypasses certificate validation and exposes you to active MITM risk.
|
||||
- On WASM platforms, certificate handling varies by environment: edge runtimes typically support full custom CA configuration, while browser environments manage certificate validation through built-in certificate stores.
|
||||
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
- MIT License ([LICENSE-MIT](LICENSE-MIT))
|
||||
|
||||
at your option.
|
||||
|
||||
## Security Policy
|
||||
|
||||
For security vulnerabilities, please see [SECURITY.md](SECURITY.md) for our responsible disclosure policy.
|
||||
|
||||
---
|
||||
|
||||
**Remember**: This library prioritizes security by default. The `insecure-dangerous` feature exists solely for development convenience and should never be used in production environments.
|
Reference in New Issue
Block a user