mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 02:34:26 +08:00
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
145
tools/openapi/generates.py
Normal file
145
tools/openapi/generates.py
Normal 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()
|
40
tools/openapi/options.json
Normal file
40
tools/openapi/options.json
Normal 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": ""
|
||||||
|
}
|
||||||
|
}
|
BIN
www/swagger/favicon-16x16.png
Normal file
BIN
www/swagger/favicon-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 665 B |
BIN
www/swagger/favicon-32x32.png
Normal file
BIN
www/swagger/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
16
www/swagger/index.css
Normal file
16
www/swagger/index.css
Normal 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
19
www/swagger/index.html
Normal 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>
|
79
www/swagger/oauth2-redirect.html
Normal file
79
www/swagger/oauth2-redirect.html
Normal 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
4233
www/swagger/openapi.json
Normal file
File diff suppressed because it is too large
Load Diff
20
www/swagger/swagger-initializer.js
Normal file
20
www/swagger/swagger-initializer.js
Normal 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>
|
||||||
|
};
|
3
www/swagger/swagger-ui-bundle.js
Normal file
3
www/swagger/swagger-ui-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
www/swagger/swagger-ui-bundle.js.map
Normal file
1
www/swagger/swagger-ui-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
3
www/swagger/swagger-ui-es-bundle-core.js
Normal file
3
www/swagger/swagger-ui-es-bundle-core.js
Normal file
File diff suppressed because one or more lines are too long
1
www/swagger/swagger-ui-es-bundle-core.js.map
Normal file
1
www/swagger/swagger-ui-es-bundle-core.js.map
Normal file
File diff suppressed because one or more lines are too long
3
www/swagger/swagger-ui-es-bundle.js
Normal file
3
www/swagger/swagger-ui-es-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
www/swagger/swagger-ui-es-bundle.js.map
Normal file
1
www/swagger/swagger-ui-es-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
3
www/swagger/swagger-ui-standalone-preset.js
Normal file
3
www/swagger/swagger-ui-standalone-preset.js
Normal file
File diff suppressed because one or more lines are too long
1
www/swagger/swagger-ui-standalone-preset.js.map
Normal file
1
www/swagger/swagger-ui-standalone-preset.js.map
Normal file
File diff suppressed because one or more lines are too long
3
www/swagger/swagger-ui.css
Normal file
3
www/swagger/swagger-ui.css
Normal file
File diff suppressed because one or more lines are too long
1
www/swagger/swagger-ui.css.map
Normal file
1
www/swagger/swagger-ui.css.map
Normal file
File diff suppressed because one or more lines are too long
2
www/swagger/swagger-ui.js
Normal file
2
www/swagger/swagger-ui.js
Normal file
File diff suppressed because one or more lines are too long
1
www/swagger/swagger-ui.js.map
Normal file
1
www/swagger/swagger-ui.js.map
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user