mirror of
https://github.com/YMFE/yapi.git
synced 2024-11-21 01:13:51 +08:00
feat: 增加对大括号变量路径支持
This commit is contained in:
parent
d557287efd
commit
6ea790636c
@ -1,3 +1,9 @@
|
||||
### v1.2.9
|
||||
|
||||
#### Bug Fixed
|
||||
|
||||
1. Api 路径兼容 postman {varible}
|
||||
|
||||
### v1.2.8
|
||||
|
||||
#### Bug Fixed
|
||||
|
@ -13,4 +13,9 @@
|
||||
|
||||
.fullScreen {
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.ace_editor.ace-xcode {
|
||||
background-color: #f5f5f5;
|
||||
color: #000000;
|
||||
}
|
@ -105,6 +105,7 @@ function handleParams(interfaceData, handleValue, requestParams) {
|
||||
}
|
||||
|
||||
path = path.replace(`:${item.name}`, val || `:${item.name}`);
|
||||
path = path.replace(`{${item.name}}`, val || `{${item.name}}`)
|
||||
});
|
||||
|
||||
|
||||
|
@ -339,6 +339,15 @@ class InterfaceEditForm extends Component {
|
||||
|
||||
handlePath = (e) => {
|
||||
let val = e.target.value, queue = [];
|
||||
|
||||
let insertParams =(name)=>{
|
||||
let findExist = _.find(this.state.req_params, { name: name });
|
||||
if (findExist) {
|
||||
queue.push(findExist)
|
||||
} else {
|
||||
queue.push({ name: name, desc: '' })
|
||||
}
|
||||
}
|
||||
val = handlePath(val)
|
||||
this.props.form.setFieldsValue({
|
||||
path: val
|
||||
@ -348,15 +357,17 @@ class InterfaceEditForm extends Component {
|
||||
for (i = 1; i < paths.length; i++) {
|
||||
if (paths[i][0] === ':') {
|
||||
name = paths[i].substr(1);
|
||||
let findExist = _.find(this.state.req_params, { name: name });
|
||||
if (findExist) {
|
||||
queue.push(findExist)
|
||||
} else {
|
||||
queue.push({ name: name, desc: '' })
|
||||
}
|
||||
insertParams(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(val && val.length > 3){
|
||||
val.replace(/\{(.+?)\}/g, function(str, match){
|
||||
insertParams(match)
|
||||
})
|
||||
}
|
||||
|
||||
this.setState({
|
||||
req_params: queue
|
||||
})
|
||||
@ -595,6 +606,8 @@ class InterfaceEditForm extends Component {
|
||||
const requestBodyList = this.state.req_body_form.map((item, index) => {
|
||||
return requestBodyTpl(item, index)
|
||||
})
|
||||
|
||||
const DEMOPATH= '/api/user/{id}'
|
||||
return (
|
||||
<Form onSubmit={this.handleSubmit}>
|
||||
|
||||
@ -639,7 +652,7 @@ class InterfaceEditForm extends Component {
|
||||
<span>
|
||||
接口路径
|
||||
<Tooltip title={<div>
|
||||
<p>1. 支持动态路由,例如:/api/user/:id</p>
|
||||
<p>1. 支持动态路由,例如:{DEMOPATH}</p>
|
||||
<p>2. 支持 ?controller=xxx 的QueryRouter,非router的Query参数请定义到 Request设置->Query</p>
|
||||
</div>}>
|
||||
<Icon type="question-circle-o" style={{ width: "10px" }} />
|
||||
|
@ -75,12 +75,7 @@ function postman(importDataModule){
|
||||
if(!path) return '';
|
||||
|
||||
path = path.replace(/{{\w*}}/g, '');
|
||||
path = path.replace(/{(\w*)}/,function(data, match){
|
||||
if(match){
|
||||
return ':' + match;
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
if(path[0] != "/"){
|
||||
path = "/" + path;
|
||||
}
|
||||
|
@ -69,12 +69,7 @@ function postman(importDataModule){
|
||||
if(!path) return '';
|
||||
|
||||
path = path.replace(/{{\w*}}/g, '');
|
||||
path = path.replace(/{(\w*)}/,function(data, match){
|
||||
if(match){
|
||||
return ':' + match;
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
if(path[0] != "/"){
|
||||
path = "/" + path;
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ var jsf = require('common/json-schema-mockjs');
|
||||
function improtData(importDataModule){
|
||||
var SwaggerData;
|
||||
function handlePath(path){
|
||||
path = path.replace(/{(\w*)}/,":$1");
|
||||
if(path.charAt(0) != "/"){
|
||||
path = "/" + path;
|
||||
}
|
||||
|
@ -128,21 +128,7 @@ class interfaceController extends baseController {
|
||||
if (!_.isUndefined(params.req_body_form)) {
|
||||
data.req_body_form = params.req_body_form;
|
||||
}
|
||||
|
||||
if (params.path.indexOf(":") > 0) {
|
||||
let paths = params.path.split("/"), name, i;
|
||||
for (i = 1; i < paths.length; i++) {
|
||||
if (paths[i][0] === ':') {
|
||||
name = paths[i].substr(1);
|
||||
if (!_.find(params.req_params, { name: name })) {
|
||||
params.req_params.push({
|
||||
name: name,
|
||||
desc: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
yapi.commons.handleVarPath(params.path, params.req_params);
|
||||
|
||||
if (params.req_params.length > 0) {
|
||||
data.type = 'var'
|
||||
|
@ -28,7 +28,7 @@ class projectController extends baseController {
|
||||
if (basepath === '/') return "";
|
||||
if (basepath[0] !== '/') basepath = '/' + basepath;
|
||||
if (basepath[basepath.length - 1] === '/') basepath = basepath.substr(0, basepath.length - 1);
|
||||
if (!yapi.commons.verifyPath(basepath)) {
|
||||
if (!/^\/[a-zA-Z0-9\-\/_]+$/.test(basepath)) {
|
||||
return false;
|
||||
}
|
||||
return basepath;
|
||||
@ -42,6 +42,8 @@ class projectController extends baseController {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 添加项目分组
|
||||
* @interface /project/add
|
||||
|
@ -22,13 +22,29 @@ function matchApi(apiPath, apiRule) {
|
||||
apiRules[i] = apiRules[i].trim();
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
if (apiRules[i].indexOf(":") !== 0) {
|
||||
}
|
||||
if(apiRules[i].length > 2 && apiRules[i][0] === '{' && apiRules[i][apiRules[i].length - 1] === '}'){
|
||||
pathRules[apiRules[i].substr(1, apiRules[i].length - 2)] = apiPaths[i];
|
||||
}else if (apiRules[i].indexOf(":") === 0) {
|
||||
pathRules[apiRules[i].substr(1)] = apiPaths[i]
|
||||
}else if(apiRules[i].length > 2 && apiRules[i].indexOf('{') > -1 && apiRules[i].indexOf('}') > -1){
|
||||
let params = [];
|
||||
apiRules[i] = apiRules[i].replace(/\{(.+?)\}/g, function(src, match){
|
||||
params.push(match);
|
||||
return '(.+?)';
|
||||
})
|
||||
apiRules[i] = new RegExp(apiRules[i]);
|
||||
if(!apiRules[i].test(apiPaths[i])){
|
||||
return false;
|
||||
}
|
||||
let matchs = apiPaths[i].match(apiRules[i]);
|
||||
params.forEach((item,index)=>{
|
||||
pathRules[item] = matchs[index+1];
|
||||
})
|
||||
}else {
|
||||
if (apiRules[i] !== apiPaths[i]) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
pathRules[apiRules[i].substr(1)] = apiPaths[i]
|
||||
}
|
||||
}
|
||||
return pathRules;
|
||||
|
@ -4,6 +4,7 @@ const yapi = require('../yapi.js');
|
||||
const sha1 = require('sha1');
|
||||
const logModel = require('../models/log.js');
|
||||
const json5 = require('json5');
|
||||
const _ = require('underscore');
|
||||
|
||||
exports.resReturn = (data, num, errmsg) => {
|
||||
num = num || 0;
|
||||
@ -160,12 +161,38 @@ exports.filterRes = (list, rules) => {
|
||||
});
|
||||
};
|
||||
|
||||
exports.handleVarPath = (pathname, params)=>{
|
||||
|
||||
function insertParams(name){
|
||||
if (!_.find(params, { name: name })) {
|
||||
params.push({
|
||||
name: name,
|
||||
desc: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if(!pathname) return;
|
||||
if(pathname.indexOf(':') !== -1){
|
||||
let paths = pathname.split("/"), name, i;
|
||||
for (i = 1; i < paths.length; i++) {
|
||||
if (paths[i] && paths[i][0] === ':') {
|
||||
name = paths[i].substr(1);
|
||||
insertParams(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
pathname.replace(/\{(.+?)\}/g, function(str, match){
|
||||
insertParams(match)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证一个 path 是否合法
|
||||
* path第一位必需为 /, path 只允许由 字母数字-/_:. 组成
|
||||
* path第一位必需为 /, path 只允许由 字母数字-/_:.{}= 组成
|
||||
*/
|
||||
exports.verifyPath = (path) => {
|
||||
if (/^\/[a-zA-Z0-9\-\/_:\.\!]+$/.test(path)) {
|
||||
if (/^\/[a-zA-Z0-9\-\/_:\.\{\}\=]+$/.test(path)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -5,7 +5,8 @@ import {
|
||||
trim,
|
||||
handleParams,
|
||||
verifyPath,
|
||||
sandbox
|
||||
sandbox,
|
||||
handleVarPath
|
||||
} from '../../server/utils/commons.js';
|
||||
|
||||
test('trim', t => {
|
||||
@ -46,4 +47,40 @@ test('sandbox', t=>{
|
||||
t.deepEqual(sandbox({
|
||||
a: 1
|
||||
}, 'a=2'), {a : 2});
|
||||
})
|
||||
|
||||
test('handleVarPath', t=>{
|
||||
let result = [];
|
||||
let pathname = '/a/:id'
|
||||
handleVarPath(pathname, result);
|
||||
|
||||
t.deepEqual(result, [{
|
||||
name: 'id',
|
||||
desc: ''
|
||||
}])
|
||||
})
|
||||
|
||||
test('handleVarPath2', t=>{
|
||||
let result = [];
|
||||
let pathname = '/a/{id}'
|
||||
handleVarPath(pathname, result);
|
||||
|
||||
t.deepEqual(result, [{
|
||||
name: 'id',
|
||||
desc: ''
|
||||
}])
|
||||
})
|
||||
|
||||
test('handleVarPath4', t=>{
|
||||
let result = [];
|
||||
let pathname = '/a/id={id}/tt/:sub/kk'
|
||||
handleVarPath(pathname, result);
|
||||
|
||||
t.deepEqual(result, [{
|
||||
name: 'sub',
|
||||
desc: ''
|
||||
}, {
|
||||
name: 'id',
|
||||
desc: ''
|
||||
}])
|
||||
})
|
@ -20,5 +20,22 @@ test('matchApi', t => {
|
||||
t.truthy(matchApi('/user/a/ttt/b', apiRule_3));
|
||||
t.false(matchApi('/user/a/ttt2/b', apiRule_3))
|
||||
|
||||
const apiRule_4 = '/user/{aaa}/ttt/{bbbb}';
|
||||
t.truthy(matchApi('/user/a/ttt/b', apiRule_4));
|
||||
t.false(matchApi('/user/a/ttt2/b', apiRule_4))
|
||||
|
||||
const apiRule_5 = '/user/{aaa}/ttt/{bbbb}';
|
||||
let r5 = matchApi('/user/a/ttt/b', apiRule_5);
|
||||
t.deepEqual(r5, {
|
||||
aaa: 'a',
|
||||
bbbb: 'b'
|
||||
});
|
||||
|
||||
const apiRule_6 = '/user/a1={aaa}/ttt/b1={bbbb}';
|
||||
let r6 = matchApi('/user/a1=a/ttt/b1=b', apiRule_6);
|
||||
t.deepEqual(r6, {
|
||||
aaa: 'a',
|
||||
bbbb: 'b'
|
||||
});
|
||||
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user