Add swagger ui for test http-api (#3012)

`python generates.py`

Convert postman files to openapi format files
Visit http://127.0.0.1:8081/swagger/ to conveniently debug the API.
This commit is contained in:
alexliyu7352 2023-11-23 17:19:36 +08:00 committed by GitHub
parent d593267f61
commit aacc95867f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 4575 additions and 0 deletions

145
tools/openapi/generates.py Normal file
View File

@ -0,0 +1,145 @@
# -*- coding:utf-8 -*-
import copy
import os
import re
import subprocess
import sys
import json
def check_installed(command: str) -> bool:
"""
check command is installed
:param command:
:return:
"""
if os.system(f"command -v {command} > /dev/null") == 0:
return True
else:
return False
def run_cmd(cmd: str, assert_success=False, capture_output=False, env=None) -> bool:
"""
run cmd
:param cmd:
:param assert_success:
:param env:
:param capture_output:
:param env:
:return:
"""
if not env:
env = os.environ.copy()
result = subprocess.run(cmd, shell=True, env=env, capture_output=capture_output)
# Assert the command ran successfully
if assert_success and result.returncode != 0:
print("Command '" + cmd + "' failed with exit status code '" + str(
result.returncode) + "'.\n\nExiting now.\nTry running the script again.")
print(result.stderr.decode())
sys.stdout.flush()
sys.stderr.flush()
sys.exit(1)
return True
def check_dependencies() -> None:
"""
check dependencies
:return:
"""
if not check_installed("p2o"):
print()
print("p2o is not installed, please install it first!")
print("If you use npm, you can install it by the following command:")
print("npm install -g postman-to-openapi")
print()
sys.exit(1)
else:
print("p2o is installed")
def get_version() -> str:
"""
get version
:return:
"""
if os.path.isfile("../../cmake-build-debug/version.h"):
print("Found version.h in cmake-build-debug")
version_h_path = "../../cmake-build-debug/version.h"
elif os.path.isfile("../../cmake-build-release/version.h"):
print("Found version.h in cmake-build-release")
version_h_path = "../../cmake-build-release/version.h"
else:
print("version.h not found")
print("Please compile first")
exit()
with open(version_h_path, 'r') as f:
content = f.read()
commit_hash = re.search(r'define COMMIT_HASH (.*)', content).group(1)
commit_time = re.search(r'define COMMIT_TIME (.*)', content).group(1)
branch_name = re.search(r'define BRANCH_NAME (.*)', content).group(1)
build_time = re.search(r'define BUILD_TIME (.*)', content).group(1)
version = f"ZLMediaKit(git hash:{commit_hash}/{commit_time},branch:{branch_name},build time:{build_time})"
print(f"version: {version}")
return version
def get_secret() -> str:
"""
get secret from default config file or user config file
:return:
"""
default_postman = json.load(open("../../postman/127.0.0.1.postman_environment.json", 'r'))
secret = "035c73f7-bb6b-4889-a715-d9eb2d1925cc"
for item in default_postman["values"]:
if item["key"] == "ZLMediaKit_secret":
secret = item["value"]
break
for root, dirs, files in os.walk("../../release/"):
for file in files:
if file == "config.ini":
config_path = os.path.join(root, file)
with open(config_path, 'r') as f:
content = f.read()
secret = re.search(r'secret=(.*)', content).group(1)
return secret
def update_options(version: str, secret: str) -> None:
"""
update options
:param version:
:param secret:
:return:
"""
print("update options")
options = json.load(open("./options.json", 'r'))
options["info"]["version"] = version
options["additionalVars"]["ZLMediaKit_secret"] = secret
json.dump(options, open("./options.json", 'w'), indent=4)
def generate() -> None:
"""
generate
:return:
"""
print("generate")
run_cmd("p2o ../../postman/ZLMediaKit.postman_collection.json -f ../../www/swagger/openapi.json -o ./options.json",
True, True)
openapi = json.load(open("../../www/swagger/openapi.json", 'r'))
for path in openapi["paths"]:
openapi["paths"][path]["post"] = copy.deepcopy(openapi["paths"][path]["get"])
openapi["paths"][path]["post"]["tags"] = ["POST"]
# save
json.dump(openapi, open("../../www/swagger/openapi.json", 'w'), indent=4)
print("generate success")
if __name__ == "__main__":
check_dependencies()
version = get_version()
secret = get_secret()
update_options(version, secret)
generate()

View File

@ -0,0 +1,40 @@
{
"info": {
"title": "ZLMediaKit HTTP API",
"version": "ZLMediaKit(git hash:\"a78ca2e\"/\"2023-11-17T11:12:51+08:00\",branch:\"patch-63\",build time:\"2023-11-23T14:35:02\")",
"description": "You can test the HTTP API provided by ZlMediaKit here. For usage documentation, please refer to [here](https://docs.zlmediakit.com/guide/media_server/restful_api.html)",
"termsOfService": "https://docs.zlmediakit.com",
"license": {
"name": "MIT",
"url": "https://docs.zlmediakit.com/more/license.html"
},
"contact": {
"name": "Contact Support",
"url": "https://docs.zlmediakit.com/more/contact.html",
"email": "1213642868@qq.com"
},
"xLogo": {
"url": "/logo.png",
"backgroundColor": "#FFFFFF",
"altText": "ZLMediaKit"
}
},
"defaultTag": "GET",
"outputFormat": "json",
"replaceVars": true,
"servers": [
{
"url": "/",
"description": "Localhost"
}
],
"externalDocs": {
"description": "ZLMediaKit Documentation",
"url": "https://docs.zlmediakit.com"
},
"additionalVars": {
"defaultVhost": "__defaultVhost__",
"ZLMediaKit_secret": "1oV1R5Z9xlrjH4QN7GXNvS5IUaYtuFgX",
"ZLMediaKit_URL": ""
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

16
www/swagger/index.css Normal file
View File

@ -0,0 +1,16 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}

19
www/swagger/index.html Normal file
View File

@ -0,0 +1,19 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="stylesheet" type="text/css" href="index.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
</body>
</html>

View File

@ -0,0 +1,79 @@
<!doctype html>
<html lang="en-US">
<head>
<title>Swagger UI: OAuth2 Redirect</title>
</head>
<body>
<script>
'use strict';
function run () {
var oauth2 = window.opener.swaggerUIRedirectOauth2;
var sentState = oauth2.state;
var redirectUrl = oauth2.redirectUrl;
var isValid, qp, arr;
if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1).replace('?', '&');
} else {
qp = location.search.substring(1);
}
arr = qp.split("&");
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
qp = qp ? JSON.parse('{' + arr.join() + '}',
function (key, value) {
return key === "" ? value : decodeURIComponent(value);
}
) : {};
isValid = qp.state === sentState;
if ((
oauth2.auth.schema.get("flow") === "accessCode" ||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
oauth2.auth.schema.get("flow") === "authorization_code"
) && !oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
});
}
if (qp.code) {
delete oauth2.state;
oauth2.auth.code = qp.code;
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
} else {
let oauthErrorMsg;
if (qp.error) {
oauthErrorMsg = "["+qp.error+"]: " +
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
(qp.error_uri ? "More info: "+qp.error_uri : "");
}
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
});
}
} else {
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
}
window.close();
}
if (document.readyState !== 'loading') {
run();
} else {
document.addEventListener('DOMContentLoaded', function () {
run();
});
}
</script>
</body>
</html>

4233
www/swagger/openapi.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
window.onload = function() {
//<editor-fold desc="Changeable Configuration Block">
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
window.ui = SwaggerUIBundle({
url: "/swagger/openapi.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
//</editor-fold>
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long