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:
parent
d593267f61
commit
aacc95867f
|
|
@ -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()
|
||||
|
|
@ -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 |
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
Loading…
Reference in New Issue