├── .github └── workflows │ └── build.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE.md ├── Makefile ├── README.md ├── _typos.toml ├── cliff.toml ├── coverage └── .gitignore ├── deny.toml └── src ├── index.css └── lib.rs /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build-rust: 13 | strategy: 14 | matrix: 15 | platform: [ubuntu-latest] 16 | runs-on: ${{ matrix.platform }} 17 | steps: 18 | - uses: actions/checkout@v3 19 | with: 20 | fetch-depth: 0 21 | - name: Install Rust 22 | run: rustup toolchain install stable --component llvm-tools-preview 23 | - name: Install cargo-llvm-cov 24 | uses: taiki-e/install-action@cargo-llvm-cov 25 | - name: install nextest 26 | uses: taiki-e/install-action@nextest 27 | - uses: Swatinem/rust-cache@v1 28 | - name: Check code format 29 | run: cargo fmt -- --check 30 | - name: Check the package for errors 31 | run: cargo check --all 32 | - name: Lint rust sources 33 | run: cargo clippy --all-targets --all-features --tests --benches -- -D warnings 34 | - name: Execute rust tests 35 | run: cargo nextest run --all-features 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | fail_fast: false 2 | repos: 3 | - repo: https://github.com/pre-commit/pre-commit-hooks 4 | rev: v4.3.0 5 | hooks: 6 | - id: check-byte-order-marker 7 | - id: check-case-conflict 8 | - id: check-merge-conflict 9 | - id: check-symlinks 10 | - id: check-yaml 11 | - id: end-of-file-fixer 12 | - id: mixed-line-ending 13 | - id: trailing-whitespace 14 | - repo: https://github.com/psf/black 15 | rev: 22.10.0 16 | hooks: 17 | - id: black 18 | - repo: local 19 | hooks: 20 | - id: cargo-fmt 21 | name: cargo fmt 22 | description: Format files with rustfmt. 23 | entry: bash -c 'cargo fmt -- --check' 24 | language: rust 25 | files: \.rs$ 26 | args: [] 27 | - id: cargo-deny 28 | name: cargo deny check 29 | description: Check cargo dependencies 30 | entry: bash -c 'cargo deny check -d' 31 | language: rust 32 | files: \.rs$ 33 | args: [] 34 | - id: typos 35 | name: typos 36 | description: check typo 37 | entry: bash -c 'typos' 38 | language: rust 39 | files: \.*$ 40 | pass_filenames: false 41 | - id: cargo-check 42 | name: cargo check 43 | description: Check the package for errors. 44 | entry: bash -c 'cargo check --all' 45 | language: rust 46 | files: \.rs$ 47 | pass_filenames: false 48 | - id: cargo-clippy 49 | name: cargo clippy 50 | description: Lint rust sources 51 | entry: bash -c 'cargo clippy --all-targets --all-features --tests --benches -- -D warnings' 52 | language: rust 53 | files: \.rs$ 54 | pass_filenames: false 55 | - id: cargo-test 56 | name: cargo test 57 | description: unit test for the project 58 | entry: bash -c 'cargo nextest run --all-features' 59 | language: rust 60 | files: \.rs$ 61 | pass_filenames: false 62 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ## [0.2.0] - 2022-11-24 6 | 7 | [ca0b427](ca0b42710fd6557efdf286391f92187e8ebf6866)...[b59e361](b59e361899aa98feeb1fee05e54b7a657027f97f) 8 | 9 | ### Features 10 | 11 | - Upgrade axum to 0.6.0-rc.5 ([b59e361](b59e361899aa98feeb1fee05e54b7a657027f97f) - 2022-11-24 by Tyr Chen) 12 | 13 | 14 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axum-swagger-ui" 3 | version = "0.3.0" 4 | edition = "2021" 5 | license = "MIT" 6 | documentation = "https://docs.rs/axum-swagger-ui" 7 | repository = "https://github.com/tyrchen/axum-swagger-ui" 8 | homepage = "https://github.com/tyrchen/axum-swagger-ui" 9 | description = """ 10 | A simple swagger ui integration for axum 11 | """ 12 | readme = "README.md" 13 | categories = ["development-tools"] 14 | keywords = ["axum", "swagger", "openapi"] 15 | 16 | [dependencies] 17 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright <2022> 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | @cargo build 3 | 4 | cov: 5 | @cargo llvm-cov nextest --all-features --workspace --lcov --output-path coverage/lcov-$(shell date +%F).info 6 | 7 | test: 8 | @CELLA_ENV=test cargo nextest run --all-features 9 | 10 | release: 11 | @cargo release tag --execute 12 | @git cliff -o CHANGELOG.md 13 | @git commit -a -m "Update CHANGELOG.md" || true 14 | @cargo release push --execute 15 | 16 | .PHONY: build cov test release 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swagger UI 2 | 3 | Swagger UI code comes from: [https://github.com/swagger-api/swagger-ui](https://github.com/swagger-api/swagger-ui). 4 | 5 | Usage: 6 | 7 | ```rust 8 | let doc_url = "swagger/openapi.json"; 9 | let app = Router::new() 10 | .route("/swagger", get(|| async { swagger_ui(doc_url) })) 11 | .route(doc_url, get(|| async { include_str!("openapi.json") })) 12 | // your other routes 13 | .route("/", get(|| async { "Hello, World!" })); 14 | ``` 15 | -------------------------------------------------------------------------------- /_typos.toml: -------------------------------------------------------------------------------- 1 | [default.extend-words] 2 | -------------------------------------------------------------------------------- /cliff.toml: -------------------------------------------------------------------------------- 1 | [changelog] 2 | # changelog header 3 | header = """ 4 | # Changelog\n 5 | All notable changes to this project will be documented in this file.\n 6 | """ 7 | # template for the changelog body 8 | # https://tera.netlify.app/docs/#introduction 9 | body = """ 10 | {% if version %}\ 11 | ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} 12 | {% else %}\ 13 | ## [unreleased] 14 | {% endif %}\ 15 | {% if previous %}\ 16 | {% if previous.commit_id %} 17 | [{{ previous.commit_id | truncate(length=7, end="") }}]({{ previous.commit_id }})...\ 18 | [{{ commit_id | truncate(length=7, end="") }}]({{ commit_id }}) 19 | {% endif %}\ 20 | {% endif %}\ 21 | {% for group, commits in commits | group_by(attribute="group") %} 22 | ### {{ group | upper_first }} 23 | {% for commit in commits %} 24 | - {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ commit.id }}) - {{ commit.author.timestamp | date }} by {{ commit.author.name }})\ 25 | {% for footer in commit.footers -%} 26 | , {{ footer.token }}{{ footer.separator }}{{ footer.value }}\ 27 | {% endfor %}\ 28 | {% endfor %} 29 | {% endfor %}\n 30 | """ 31 | # remove the leading and trailing whitespace from the template 32 | trim = true 33 | # changelog footer 34 | footer = """ 35 | 36 | """ 37 | 38 | [git] 39 | # parse the commits based on https://www.conventionalcommits.org 40 | conventional_commits = true 41 | # filter out the commits that are not conventional 42 | filter_unconventional = true 43 | # process each line of a commit as an individual commit 44 | split_commits = false 45 | # regex for parsing and grouping commits 46 | commit_parsers = [ 47 | { message = "^feat", group = "Features"}, 48 | { message = "^fix", group = "Bug Fixes"}, 49 | { message = "^doc", group = "Documentation"}, 50 | { message = "^perf", group = "Performance"}, 51 | { message = "^refactor", group = "Refactor"}, 52 | { message = "^style", group = "Styling"}, 53 | { message = "^test", group = "Testing"}, 54 | { message = "^chore\\(release\\): prepare for", skip = true}, 55 | { message = "^chore", group = "Miscellaneous Tasks"}, 56 | { body = ".*security", group = "Security"}, 57 | ] 58 | # protect breaking changes from being skipped due to matching a skipping commit_parser 59 | protect_breaking_commits = false 60 | # filter out the commits that are not matched by commit parsers 61 | filter_commits = false 62 | # glob pattern for matching git tags 63 | tag_pattern = "v*" 64 | # regex for skipping tags 65 | skip_tags = "v0.1.0-beta.1" 66 | # regex for ignoring tags 67 | ignore_tags = "" 68 | # sort the tags chronologically 69 | date_order = false 70 | # sort the commits inside sections by oldest/newest order 71 | sort_commits = "oldest" 72 | -------------------------------------------------------------------------------- /coverage/.gitignore: -------------------------------------------------------------------------------- 1 | *.info 2 | -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | # This template contains all of the possible sections and their default values 2 | 3 | # Note that all fields that take a lint level have these possible values: 4 | # * deny - An error will be produced and the check will fail 5 | # * warn - A warning will be produced, but the check will not fail 6 | # * allow - No warning or error will be produced, though in some cases a note 7 | # will be 8 | 9 | # The values provided in this template are the default values that will be used 10 | # when any section or field is not specified in your own configuration 11 | 12 | # If 1 or more target triples (and optionally, target_features) are specified, 13 | # only the specified targets will be checked when running `cargo deny check`. 14 | # This means, if a particular package is only ever used as a target specific 15 | # dependency, such as, for example, the `nix` crate only being used via the 16 | # `target_family = "unix"` configuration, that only having windows targets in 17 | # this list would mean the nix crate, as well as any of its exclusive 18 | # dependencies not shared by any other crates, would be ignored, as the target 19 | # list here is effectively saying which targets you are building for. 20 | targets = [ 21 | # The triple can be any string, but only the target triples built in to 22 | # rustc (as of 1.40) can be checked against actual config expressions 23 | #{ triple = "x86_64-unknown-linux-musl" }, 24 | # You can also specify which target_features you promise are enabled for a 25 | # particular target. target_features are currently not validated against 26 | # the actual valid features supported by the target architecture. 27 | #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, 28 | ] 29 | 30 | # This section is considered when running `cargo deny check advisories` 31 | # More documentation for the advisories section can be found here: 32 | # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html 33 | [advisories] 34 | # The path where the advisory database is cloned/fetched into 35 | db-path = "~/.cargo/advisory-db" 36 | # The url(s) of the advisory databases to use 37 | db-urls = ["https://github.com/rustsec/advisory-db"] 38 | # The lint level for security vulnerabilities 39 | vulnerability = "deny" 40 | # The lint level for unmaintained crates 41 | unmaintained = "warn" 42 | # The lint level for crates that have been yanked from their source registry 43 | yanked = "warn" 44 | # The lint level for crates with security notices. Note that as of 45 | # 2019-12-17 there are no security notice advisories in 46 | # https://github.com/rustsec/advisory-db 47 | notice = "warn" 48 | # A list of advisory IDs to ignore. Note that ignored advisories will still 49 | # output a note when they are encountered. 50 | ignore = [ 51 | #"RUSTSEC-0000-0000", 52 | ] 53 | # Threshold for security vulnerabilities, any vulnerability with a CVSS score 54 | # lower than the range specified will be ignored. Note that ignored advisories 55 | # will still output a note when they are encountered. 56 | # * None - CVSS Score 0.0 57 | # * Low - CVSS Score 0.1 - 3.9 58 | # * Medium - CVSS Score 4.0 - 6.9 59 | # * High - CVSS Score 7.0 - 8.9 60 | # * Critical - CVSS Score 9.0 - 10.0 61 | #severity-threshold = 62 | 63 | # This section is considered when running `cargo deny check licenses` 64 | # More documentation for the licenses section can be found here: 65 | # https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html 66 | [licenses] 67 | # The lint level for crates which do not have a detectable license 68 | unlicensed = "allow" 69 | # List of explicitly allowed licenses 70 | # See https://spdx.org/licenses/ for list of possible licenses 71 | # [possible values: any SPDX 3.7 short identifier (+ optional exception)]. 72 | allow = ["MIT", "Apache-2.0", "Unicode-DFS-2016", "BSD-3-Clause"] 73 | # List of explicitly disallowed licenses 74 | # See https://spdx.org/licenses/ for list of possible licenses 75 | # [possible values: any SPDX 3.7 short identifier (+ optional exception)]. 76 | deny = [ 77 | #"Nokia", 78 | ] 79 | # Lint level for licenses considered copyleft 80 | copyleft = "warn" 81 | # Blanket approval or denial for OSI-approved or FSF Free/Libre licenses 82 | # * both - The license will be approved if it is both OSI-approved *AND* FSF 83 | # * either - The license will be approved if it is either OSI-approved *OR* FSF 84 | # * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF 85 | # * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved 86 | # * neither - This predicate is ignored and the default lint level is used 87 | allow-osi-fsf-free = "neither" 88 | # Lint level used when no other predicates are matched 89 | # 1. License isn't in the allow or deny lists 90 | # 2. License isn't copyleft 91 | # 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" 92 | default = "deny" 93 | # The confidence threshold for detecting a license from license text. 94 | # The higher the value, the more closely the license text must be to the 95 | # canonical license text of a valid SPDX license file. 96 | # [possible values: any between 0.0 and 1.0]. 97 | confidence-threshold = 0.8 98 | # Allow 1 or more licenses on a per-crate basis, so that particular licenses 99 | # aren't accepted for every possible crate as with the normal allow list 100 | exceptions = [ 101 | # Each entry is the crate and version constraint, and its specific allow 102 | # list 103 | #{ allow = ["Zlib"], name = "adler32", version = "*" }, 104 | ] 105 | 106 | # Some crates don't have (easily) machine readable licensing information, 107 | # adding a clarification entry for it allows you to manually specify the 108 | # licensing information 109 | #[[licenses.clarify]] 110 | # The name of the crate the clarification applies to 111 | #name = "ring" 112 | # The optional version constraint for the crate 113 | #version = "*" 114 | # The SPDX expression for the license requirements of the crate 115 | #expression = "MIT AND ISC AND OpenSSL" 116 | # One or more files in the crate's source used as the "source of truth" for 117 | # the license expression. If the contents match, the clarification will be used 118 | # when running the license check, otherwise the clarification will be ignored 119 | # and the crate will be checked normally, which may produce warnings or errors 120 | # depending on the rest of your configuration 121 | #license-files = [ 122 | # Each entry is a crate relative path, and the (opaque) hash of its contents 123 | #{ path = "LICENSE", hash = 0xbd0eed23 } 124 | #] 125 | 126 | [licenses.private] 127 | # If true, ignores workspace crates that aren't published, or are only 128 | # published to private registries 129 | ignore = false 130 | # One or more private registries that you might publish crates to, if a crate 131 | # is only published to private registries, and ignore is true, the crate will 132 | # not have its license(s) checked 133 | registries = [ 134 | #"https://sekretz.com/registry 135 | ] 136 | 137 | # This section is considered when running `cargo deny check bans`. 138 | # More documentation about the 'bans' section can be found here: 139 | # https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html 140 | [bans] 141 | # Lint level for when multiple versions of the same crate are detected 142 | multiple-versions = "warn" 143 | # Lint level for when a crate version requirement is `*` 144 | wildcards = "allow" 145 | # The graph highlighting used when creating dotgraphs for crates 146 | # with multiple versions 147 | # * lowest-version - The path to the lowest versioned duplicate is highlighted 148 | # * simplest-path - The path to the version with the fewest edges is highlighted 149 | # * all - Both lowest-version and simplest-path are used 150 | highlight = "all" 151 | # List of crates that are allowed. Use with care! 152 | allow = [ 153 | #{ name = "ansi_term", version = "=0.11.0" }, 154 | ] 155 | # List of crates to deny 156 | deny = [ 157 | # Each entry the name of a crate and a version range. If version is 158 | # not specified, all versions will be matched. 159 | #{ name = "ansi_term", version = "=0.11.0" }, 160 | # 161 | # Wrapper crates can optionally be specified to allow the crate when it 162 | # is a direct dependency of the otherwise banned crate 163 | #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, 164 | ] 165 | # Certain crates/versions that will be skipped when doing duplicate detection. 166 | skip = [ 167 | #{ name = "ansi_term", version = "=0.11.0" }, 168 | ] 169 | # Similarly to `skip` allows you to skip certain crates during duplicate 170 | # detection. Unlike skip, it also includes the entire tree of transitive 171 | # dependencies starting at the specified crate, up to a certain depth, which is 172 | # by default infinite 173 | skip-tree = [ 174 | #{ name = "ansi_term", version = "=0.11.0", depth = 20 }, 175 | ] 176 | 177 | # This section is considered when running `cargo deny check sources`. 178 | # More documentation about the 'sources' section can be found here: 179 | # https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html 180 | [sources] 181 | # Lint level for what to happen when a crate from a crate registry that is not 182 | # in the allow list is encountered 183 | unknown-registry = "warn" 184 | # Lint level for what to happen when a crate from a git repository that is not 185 | # in the allow list is encountered 186 | unknown-git = "warn" 187 | # List of URLs for allowed crate registries. Defaults to the crates.io index 188 | # if not specified. If it is specified but empty, no registries are allowed. 189 | allow-registry = ["https://github.com/rust-lang/crates.io-index"] 190 | # List of URLs for allowed Git repositories 191 | allow-git = [] 192 | 193 | [sources.allow-org] 194 | # 1 or more github.com organizations to allow git sources for 195 | github = [] 196 | # 1 or more gitlab.com organizations to allow git sources for 197 | gitlab = [] 198 | # 1 or more bitbucket.org organizations to allow git sources for 199 | bitbucket = [] 200 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | overflow: -moz-scrollbars-vertical; 4 | overflow-y: scroll; 5 | } 6 | 7 | *, 8 | *:before, 9 | *:after { 10 | box-sizing: inherit; 11 | } 12 | 13 | body { 14 | margin: 0; 15 | background: #fafafa; 16 | } 17 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | const INDEX_STYLE: &str = include_str!("index.css"); 2 | const SWAGGER_UI_TEMPLATE: &str = r#" 3 | 4 | 5 | 6 | 7 | 8 | Swagger UI 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 36 | 37 | 38 | "#; 39 | 40 | /// Returns the HTML for the Swagger UI page. 41 | pub fn swagger_ui(spec_url: &'static str) -> String { 42 | SWAGGER_UI_TEMPLATE 43 | .replace("{:index_style}", INDEX_STYLE) 44 | .replace("{:spec_url}", spec_url) 45 | } 46 | --------------------------------------------------------------------------------