Commit 5d01d643 by inrgihc

支持requestBody入参

parent 2852b697
...@@ -69,19 +69,13 @@ ...@@ -69,19 +69,13 @@
- (1) 接口响应出参列表及说明文档 - (1) 接口响应出参列表及说明文档
> 通过人工配制或接口调试,以构建接口出参及其说明文档。 > 通过人工配制或接口调试,以构建接口出参及其说明文档。
- (2) 支持更广泛的入参格式(如JSON入参/文件入参等) - (2) 支持接口的缓存配置功能
> 支持POST/PUT等JSON格式的接口入参。
- (3) 支持接口的缓存配置功能
> 基于分布式缓存等构建支持接口的缓存配置功能。 > 基于分布式缓存等构建支持接口的缓存配置功能。
- (4) SQL结果集的出参格式转换 - (3) SQL结果集的出参格式转换
> SQL查询结果集到接口出参相应的格式转换。 > SQL查询结果集到接口出参相应的格式转换。
- (5) 接口入参的校验 - (4) 前端界面中拓扑结构美化
> 支持接口入参的类型、是否可空等的校验功能。
- (6) 前端界面中拓扑结构美化
> 美化签到界面的拓扑结构图的展示。 > 美化签到界面的拓扑结构图的展示。
## 二、编译打包 ## 二、编译打包
......
...@@ -50,6 +50,13 @@ eureka: ...@@ -50,6 +50,13 @@ eureka:
service-url: service-url:
defaultZone: http://${MANAGER_HOST}:${MANAGER_PORT}/eureka/ defaultZone: http://${MANAGER_HOST}:${MANAGER_PORT}/eureka/
springfox:
documentation:
enabled: true
auto-startup: false
swagger-ui:
enabled: false
datasource: datasource:
driver: driver:
base-path: ${APP_DRIVERS_PATH} base-path: ${APP_DRIVERS_PATH}
...@@ -22,6 +22,12 @@ public abstract class Constants { ...@@ -22,6 +22,12 @@ public abstract class Constants {
public static final String SYS_PARAM_KEY_API_DOC_OPEN = "apiDocOpen"; public static final String SYS_PARAM_KEY_API_DOC_OPEN = "apiDocOpen";
public static final String SYS_PARAM_KEY_SWAGGER_INFO_TITLE = "apiDocInfoTitle";
public static final String SYS_PARAM_KEY_SWAGGER_INFO_VERSION = "apiDocInfoVersion";
public static final String SYS_PARAM_KEY_SWAGGER_INFO_DESCRIPTION = "apiDocInfoDescription";
public static final String getResourceName(String method, String path) { public static final String getResourceName(String method, String path) {
return String.format("/%s/%s[%s]", Constants.API_PATH_PREFIX, path, method); return String.format("/%s/%s[%s]", Constants.API_PATH_PREFIX, path, method);
} }
......
package com.gitee.sqlrest.common.enums; package com.gitee.sqlrest.common.enums;
public enum HttpMethodEnum { public enum HttpMethodEnum {
GET, HEAD, PUT, POST, DELETE, GET(false), HEAD(false), PUT(true), POST(true), DELETE(true),
; ;
private boolean hasBody;
HttpMethodEnum(boolean hasBody) {
this.hasBody = hasBody;
}
public boolean isHasBody() {
return hasBody;
}
public static boolean exists(String method) { public static boolean exists(String method) {
for (HttpMethodEnum methodEnum : values()) { for (HttpMethodEnum methodEnum : values()) {
if (methodEnum.name().equals(method)) { if (methodEnum.name().equals(method)) {
......
package com.gitee.sqlrest.common.enums; package com.gitee.sqlrest.common.enums;
public enum ParamLocationEnum { public enum ParamLocationEnum {
REQUEST_HEADER("请求头"), REQUEST_HEADER("header", "请求头"),
REQUEST_BODY("请求体"), REQUEST_FORM("query", "表单数据"),
FORM_DATA("表单数据"), REQUEST_BODY("body", "请求体"),
; ;
private String name; private String name;
private String in;
ParamLocationEnum(String name) { ParamLocationEnum(String in, String name) {
this.name = name; this.name = name;
this.in = in;
} }
public String getName() { public String getName() {
return name; return name;
} }
public String getIn() {
return in;
}
public boolean isParameter() {
return this == REQUEST_FORM || this == REQUEST_HEADER;
}
public boolean isHeader() {
return this == REQUEST_HEADER;
}
public boolean isRequestBody() {
return this == REQUEST_BODY;
}
} }
...@@ -19,6 +19,7 @@ import com.google.common.base.Charsets; ...@@ -19,6 +19,7 @@ import com.google.common.base.Charsets;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
...@@ -26,11 +27,11 @@ import java.util.Iterator; ...@@ -26,11 +27,11 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -51,7 +52,11 @@ public class ApiExecuteService { ...@@ -51,7 +52,11 @@ public class ApiExecuteService {
log.warn("Error for handle api[id={}],information:{}", config.getId(), message); log.warn("Error for handle api[id={}],information:{}", config.getId(), message);
return ResultEntity.failed(ResponseErrorCode.ERROR_RESOURCE_NOT_EXISTS, message); return ResultEntity.failed(ResponseErrorCode.ERROR_RESOURCE_NOT_EXISTS, message);
} }
Map<String, Object> paramValues = obtainParameterValues(request, config.getParams()); List<ItemParam> invalidArgs = new ArrayList<>();
Map<String, Object> paramValues = obtainParameterValues(request, config.getParams(), invalidArgs);
if (invalidArgs.size() > 0) {
return ResultEntity.failed(ResponseErrorCode.ERROR_INVALID_ARGUMENT, convertInvalidArgs(invalidArgs));
}
File driverPath = driverLoadService.getVersionDriverFile(dsEntity.getType(), dsEntity.getVersion()); File driverPath = driverLoadService.getVersionDriverFile(dsEntity.getType(), dsEntity.getVersion());
HikariDataSource dataSource = DataSourceUtils.getHikariDataSource(dsEntity, driverPath.getAbsolutePath()); HikariDataSource dataSource = DataSourceUtils.getHikariDataSource(dsEntity, driverPath.getAbsolutePath());
Object result = ApiExecutorEngineFactory Object result = ApiExecutorEngineFactory
...@@ -63,37 +68,79 @@ public class ApiExecuteService { ...@@ -63,37 +68,79 @@ public class ApiExecuteService {
} }
} }
private Map<String, Object> obtainParameterValues(HttpServletRequest request, List<ItemParam> params) { private String convertInvalidArgs(List<ItemParam> invalidArgs) {
return "无效参数," + invalidArgs.stream().map(
p -> p.getIsArray() ? "数组" : "" + "参数'" + p.getName() + "'位于" + p.getLocation().getIn()
).collect(Collectors.joining(";"));
}
private Map<String, Object> obtainParameterValues(HttpServletRequest request, List<ItemParam> params,
List<ItemParam> invalidArgs) {
if (CollectionUtils.isEmpty(params)) {
return Collections.emptyMap();
}
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
if (null != params && params.size() > 0) { Map<String, Object> bodyMap = getRequestBodyMap(request);
Map<String, Object> bodyMap = getRequestBodyMap(request); for (ItemParam param : params) {
for (ItemParam param : params) { String name = param.getName();
String name = param.getName(); ParamTypeEnum type = param.getType();
ParamTypeEnum type = param.getType(); ParamLocationEnum location = param.getLocation();
ParamLocationEnum location = param.getLocation(); Boolean isArray = param.getIsArray();
String defaultValue = param.getDefaultValue(); Boolean required = param.getRequired();
if (location == ParamLocationEnum.REQUEST_HEADER) { String defaultValue = param.getDefaultValue();
map.put(name, request.getHeader(name)); if (location == ParamLocationEnum.REQUEST_HEADER) {
} else if (location == ParamLocationEnum.REQUEST_BODY) { List<Object> hv = Collections.list(request.getHeaders(name))
map.put(name, bodyMap.get(name)); .stream().map(v -> type.getConverter().apply(v))
.collect(Collectors.toList());
if (isArray) {
if (CollectionUtils.isEmpty(hv)) {
invalidArgs.add(param);
} else {
map.put(name, hv);
}
} else { } else {
boolean isArray = Optional.ofNullable(param.getIsArray()).orElse(false); if (CollectionUtils.isEmpty(hv)) {
Boolean required = Optional.ofNullable(param.getRequired()).orElse(false); if (required) {
if (isArray) { invalidArgs.add(param);
String[] values = request.getParameterValues(name);
if (null != values && values.length > 0) {
List list = Arrays.asList(values).stream()
.map(v -> type.getConverter().apply(v))
.collect(Collectors.toList());
map.put(name, list);
} else { } else {
map.put(name, null); map.put(name, type.getConverter().apply(defaultValue));
} }
} else { } else {
String value = request.getParameter(name); map.put(name, hv.get(0));
if (!required && null == value) { }
value = defaultValue; }
} else if (location == ParamLocationEnum.REQUEST_BODY) {
Object paramValue = bodyMap.get(name);
if (null == paramValue) {
if (required) {
invalidArgs.add(param);
} else {
map.put(name, type.getConverter().apply(defaultValue));
}
} else {
map.put(name, paramValue);
}
} else {
if (isArray) {
String[] values = request.getParameterValues(name);
if (null != values && values.length > 0) {
List list = Arrays.asList(values).stream()
.map(v -> type.getConverter().apply(v))
.collect(Collectors.toList());
map.put(name, list);
} else {
invalidArgs.add(param);
}
} else {
String value = request.getParameter(name);
if (null == value) {
if (required) {
invalidArgs.add(param);
} else {
map.put(name, type.getConverter().apply(defaultValue));
} }
} else {
map.put(name, type.getConverter().apply(value)); map.put(name, type.getConverter().apply(value));
} }
} }
...@@ -103,6 +150,10 @@ public class ApiExecuteService { ...@@ -103,6 +150,10 @@ public class ApiExecuteService {
} }
public Map<String, Object> getRequestBodyMap(HttpServletRequest request) { public Map<String, Object> getRequestBodyMap(HttpServletRequest request) {
if (null == request.getContentType() || !request.getContentType().contains("application/json")) {
return Collections.emptyMap();
}
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
try { try {
String jsonString = IoUtil.read(request.getInputStream(), Charsets.UTF_8); String jsonString = IoUtil.read(request.getInputStream(), Charsets.UTF_8);
......
...@@ -8,6 +8,7 @@ import com.gitee.sqlrest.common.dto.ResultEntity; ...@@ -8,6 +8,7 @@ import com.gitee.sqlrest.common.dto.ResultEntity;
import com.gitee.sqlrest.common.enums.DataTypeFormatEnum; import com.gitee.sqlrest.common.enums.DataTypeFormatEnum;
import com.gitee.sqlrest.common.enums.NamingStrategyEnum; import com.gitee.sqlrest.common.enums.NamingStrategyEnum;
import com.gitee.sqlrest.common.enums.OnOffEnum; import com.gitee.sqlrest.common.enums.OnOffEnum;
import com.gitee.sqlrest.common.enums.ParamLocationEnum;
import com.gitee.sqlrest.common.enums.ParamTypeEnum; import com.gitee.sqlrest.common.enums.ParamTypeEnum;
import com.gitee.sqlrest.common.exception.CommonException; import com.gitee.sqlrest.common.exception.CommonException;
import com.gitee.sqlrest.common.exception.ResponseErrorCode; import com.gitee.sqlrest.common.exception.ResponseErrorCode;
...@@ -18,7 +19,6 @@ import com.gitee.sqlrest.core.dto.ApiAssignmentSaveRequest; ...@@ -18,7 +19,6 @@ import com.gitee.sqlrest.core.dto.ApiAssignmentSaveRequest;
import com.gitee.sqlrest.core.dto.ApiDebugExecuteRequest; import com.gitee.sqlrest.core.dto.ApiDebugExecuteRequest;
import com.gitee.sqlrest.core.dto.AssignmentSearchRequest; import com.gitee.sqlrest.core.dto.AssignmentSearchRequest;
import com.gitee.sqlrest.core.dto.DataTypeFormatMapValue; import com.gitee.sqlrest.core.dto.DataTypeFormatMapValue;
import com.gitee.sqlrest.core.dto.NameValueRemarkResponse;
import com.gitee.sqlrest.core.dto.ScriptEditorCompletion; import com.gitee.sqlrest.core.dto.ScriptEditorCompletion;
import com.gitee.sqlrest.core.dto.SqlParamParseResponse; import com.gitee.sqlrest.core.dto.SqlParamParseResponse;
import com.gitee.sqlrest.core.exec.ApiExecuteService; import com.gitee.sqlrest.core.exec.ApiExecuteService;
...@@ -42,8 +42,6 @@ import java.io.File; ...@@ -42,8 +42,6 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -56,7 +54,6 @@ import javax.annotation.Resource; ...@@ -56,7 +54,6 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -140,7 +137,7 @@ public class ApiAssignmentService { ...@@ -140,7 +137,7 @@ public class ApiAssignmentService {
String paramName = entry.getKey(); String paramName = entry.getKey();
List<ParamValue> value = entry.getValue(); List<ParamValue> value = entry.getValue();
ParamTypeEnum type = value.get(0).getType(); ParamTypeEnum type = value.get(0).getType();
if (value.size() > 1) { if (value.get(0).getIsArray()) {
List<Object> values = value.stream().map(ParamValue::getValue) List<Object> values = value.stream().map(ParamValue::getValue)
.map(s -> type.getConverter().apply(s)) .map(s -> type.getConverter().apply(s))
.collect(Collectors.toList()); .collect(Collectors.toList());
...@@ -183,6 +180,28 @@ public class ApiAssignmentService { ...@@ -183,6 +180,28 @@ public class ApiAssignmentService {
String message = String.format("path=[%s]%s", request.getMethod().name(), request.getPath()); String message = String.format("path=[%s]%s", request.getMethod().name(), request.getPath());
throw new CommonException(ResponseErrorCode.ERROR_RESOURCE_ALREADY_EXISTS, message); throw new CommonException(ResponseErrorCode.ERROR_RESOURCE_ALREADY_EXISTS, message);
} }
if (!CollectionUtils.isEmpty(request.getParams())) {
if (!request.getMethod().isHasBody()) {
if (request.getParams().stream().anyMatch(i -> ParamLocationEnum.REQUEST_BODY == i.getLocation())) {
throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT,
"Request with GET/HEAD method cannot have body.");
}
} else {
if ("application/json".equals(request.getContentType())) {
if (request.getParams().stream().filter(i -> ParamLocationEnum.REQUEST_HEADER != i.getLocation())
.anyMatch(i -> ParamLocationEnum.REQUEST_BODY != i.getLocation())) {
throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT,
"Request with 'application/json' content-type must use body parameter.");
}
} else {
if (request.getParams().stream().filter(i -> ParamLocationEnum.REQUEST_HEADER != i.getLocation())
.anyMatch(i -> ParamLocationEnum.REQUEST_FORM != i.getLocation())) {
throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT,
"Request with '" + request.getContentType() + "' content-type must use form parameter.");
}
}
}
}
if (CollectionUtils.isEmpty(request.getContextList())) { if (CollectionUtils.isEmpty(request.getContextList())) {
throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT, "contextList"); throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT, "contextList");
} }
...@@ -222,6 +241,12 @@ public class ApiAssignmentService { ...@@ -222,6 +241,12 @@ public class ApiAssignmentService {
if (null == exists) { if (null == exists) {
throw new CommonException(ResponseErrorCode.ERROR_RESOURCE_NOT_EXISTS, "id=" + request.getId()); throw new CommonException(ResponseErrorCode.ERROR_RESOURCE_NOT_EXISTS, "id=" + request.getId());
} }
if (exists.getMethod() != request.getMethod()) {
throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT, "can't update method");
}
if (!StringUtils.equals(exists.getPath(), request.getPath())) {
throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT, "can't update path");
}
if (exists.getStatus()) { if (exists.getStatus()) {
throw new CommonException(ResponseErrorCode.ERROR_EDIT_ALREADY_PUBLISHED, "id=" + request.getId()); throw new CommonException(ResponseErrorCode.ERROR_EDIT_ALREADY_PUBLISHED, "id=" + request.getId());
} }
...@@ -231,7 +256,28 @@ public class ApiAssignmentService { ...@@ -231,7 +256,28 @@ public class ApiAssignmentService {
if (CollectionUtils.isEmpty(request.getContextList())) { if (CollectionUtils.isEmpty(request.getContextList())) {
throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT, "sqlTextList"); throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT, "sqlTextList");
} }
if (!CollectionUtils.isEmpty(request.getParams())) {
if (!request.getMethod().isHasBody()) {
if (request.getParams().stream().anyMatch(i -> ParamLocationEnum.REQUEST_BODY == i.getLocation())) {
throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT,
"Request with GET/HEAD method cannot have body.");
}
} else {
if ("application/json".equals(request.getContentType())) {
if (request.getParams().stream().filter(i -> ParamLocationEnum.REQUEST_HEADER != i.getLocation())
.anyMatch(i -> ParamLocationEnum.REQUEST_BODY != i.getLocation())) {
throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT,
"Request with 'application/json' content-type must use body parameter.");
}
} else {
if (request.getParams().stream().filter(i -> ParamLocationEnum.REQUEST_HEADER != i.getLocation())
.anyMatch(i -> ParamLocationEnum.REQUEST_FORM != i.getLocation())) {
throw new CommonException(ResponseErrorCode.ERROR_INVALID_ARGUMENT,
"Request with '" + request.getContentType() + "' content-type must use form parameter.");
}
}
}
}
if (null == request.getNamingStrategy()) { if (null == request.getNamingStrategy()) {
request.setNamingStrategy(NamingStrategyEnum.CAMEL_CASE); request.setNamingStrategy(NamingStrategyEnum.CAMEL_CASE);
} }
......
...@@ -64,9 +64,13 @@ public class ClientTokenService { ...@@ -64,9 +64,13 @@ public class ClientTokenService {
public AccessToken generateToken(String clientId, String clientSecret) { public AccessToken generateToken(String clientId, String clientSecret) {
AppClientEntity appClient = appClientDao.getByAppKey(clientId); AppClientEntity appClient = appClientDao.getByAppKey(clientId);
if (null == appClient || !StringUtils.equals(appClient.getAppSecret(), clientSecret)) { if (null == appClient) {
return null; throw new CommonException(ResponseErrorCode.ERROR_CLIENT_FORBIDDEN, "clientId invalid");
}
if (!StringUtils.equals(appClient.getAppSecret(), clientSecret)) {
throw new CommonException(ResponseErrorCode.ERROR_CLIENT_FORBIDDEN, "secret invalid");
} }
String token = TokenUtils.generateValue(); String token = TokenUtils.generateValue();
AccessToken clientToken = AccessToken.builder() AccessToken clientToken = AccessToken.builder()
.realName(appClient.getName()) .realName(appClient.getName())
......
package com.gitee.sqlrest.executor.controller; package com.gitee.sqlrest.executor.controller;
import com.gitee.sqlrest.common.consts.Constants; import com.gitee.sqlrest.common.consts.Constants;
import com.gitee.sqlrest.core.dto.SwaggerEntity;
import com.gitee.sqlrest.core.servlet.ApiSwaggerService; import com.gitee.sqlrest.core.servlet.ApiSwaggerService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.v3.oas.models.OpenAPI;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.spring.web.json.Json;
import springfox.documentation.spring.web.json.JsonSerializer;
@Api(tags = {"Swagger接口文档"}) @Api(tags = {"Swagger接口文档"})
@RestController @RestController
...@@ -18,9 +22,12 @@ public class ApiSwaggerController { ...@@ -18,9 +22,12 @@ public class ApiSwaggerController {
@Resource @Resource
private ApiSwaggerService apiSwaggerService; private ApiSwaggerService apiSwaggerService;
@Resource
private JsonSerializer jsonSerializer;
@GetMapping(value = "/swagger.json", produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(value = "/swagger.json", produces = MediaType.APPLICATION_JSON_VALUE)
public SwaggerEntity getSwaggerJson(HttpServletRequest request) { public ResponseEntity<Json> getSwaggerJson(HttpServletRequest request) {
return apiSwaggerService.getSwaggerJson(request); OpenAPI oas = apiSwaggerService.getSwaggerJson(request);
return new ResponseEntity(this.jsonSerializer.toJson(oas), HttpStatus.OK);
} }
} }
package com.gitee.sqlrest.executor.controller; package com.gitee.sqlrest.executor.controller;
import com.gitee.sqlrest.common.dto.AccessToken; import com.gitee.sqlrest.common.dto.AccessToken;
import com.gitee.sqlrest.common.dto.ResultEntity;
import com.gitee.sqlrest.common.exception.ResponseErrorCode;
import com.gitee.sqlrest.core.servlet.ClientTokenService; import com.gitee.sqlrest.core.servlet.ClientTokenService;
import java.util.Map;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
...@@ -18,11 +18,7 @@ public class ClientTokenController { ...@@ -18,11 +18,7 @@ public class ClientTokenController {
private ClientTokenService clientTokenService; private ClientTokenService clientTokenService;
@PostMapping(value = "/generate", produces = MediaType.APPLICATION_JSON_VALUE) @PostMapping(value = "/generate", produces = MediaType.APPLICATION_JSON_VALUE)
public ResultEntity<AccessToken> generateToken(String clientId, String secret) { public AccessToken generateToken(@RequestBody Map<String, String> body) {
AccessToken token = clientTokenService.generateToken(clientId, secret); return clientTokenService.generateToken(body.get("clientId"), body.get("secret"));
if (null == token) {
return ResultEntity.failed(ResponseErrorCode.ERROR_RESOURCE_NOT_EXISTS);
}
return ResultEntity.success(token);
} }
} }
...@@ -65,7 +65,9 @@ public class SentinelFlowControlManager implements FlowControlManger { ...@@ -65,7 +65,9 @@ public class SentinelFlowControlManager implements FlowControlManger {
} }
if (rules.size() > 0) { if (rules.size() > 0) {
FlowRuleManager.loadRules(rules); FlowRuleManager.loadRules(rules);
log.info("Success refresh flow rules count: {}", rules.size()); if (log.isDebugEnabled()) {
log.debug("Success refresh flow rules count: {}", rules.size());
}
} }
} }
......
...@@ -50,6 +50,14 @@ eureka: ...@@ -50,6 +50,14 @@ eureka:
service-url: service-url:
defaultZone: http://${MANAGER_HOST}:${MANAGER_PORT}/eureka/ defaultZone: http://${MANAGER_HOST}:${MANAGER_PORT}/eureka/
springfox:
documentation:
enabled: true
auto-startup: false
swagger-ui:
enabled: false
datasource: datasource:
driver: driver:
base-path: ${APP_DRIVERS_PATH} base-path: ${APP_DRIVERS_PATH}
\ No newline at end of file
...@@ -154,6 +154,20 @@ ...@@ -154,6 +154,20 @@
:disabled="isOnlyShowDetail"> </el-input> :disabled="isOnlyShowDetail"> </el-input>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="参数位置"
min-width="25%">
<template slot-scope="scope">
<el-select v-model="scope.row.location"
:disabled="isOnlyShowDetail">
<el-option label='header'
value='REQUEST_HEADER'></el-option>
<el-option label='body'
value='REQUEST_BODY'></el-option>
<el-option label='query'
value='REQUEST_FORM'></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="参数类型" <el-table-column label="参数类型"
min-width="25%"> min-width="25%">
<template slot-scope="scope"> <template slot-scope="scope">
...@@ -568,7 +582,7 @@ export default { ...@@ -568,7 +582,7 @@ export default {
groupList: [], groupList: [],
moduleList: [], moduleList: [],
connectionList: [], connectionList: [],
contentTypes: ['application/x-www-form-urlencoded'], contentTypes: ['application/x-www-form-urlencoded', 'application/json'],
showTree: true, showTree: true,
createParam: { createParam: {
id: null, id: null,
...@@ -579,7 +593,7 @@ export default { ...@@ -579,7 +593,7 @@ export default {
module: null, module: null,
method: null, method: null,
path: null, path: null,
contentType: 'application/x-www-form-urlencoded', contentType: null,
engine: 'SQL', engine: 'SQL',
sqls: [], sqls: [],
script: '', script: '',
...@@ -1044,7 +1058,7 @@ export default { ...@@ -1044,7 +1058,7 @@ export default {
this.inputParams.push( this.inputParams.push(
{ {
name: item.name, name: item.name,
location: 'FORM_DATA', location: 'REQUEST_FORM',
type: "STRING", type: "STRING",
isArray: item.isArray, isArray: item.isArray,
required: true, required: true,
...@@ -1070,7 +1084,7 @@ export default { ...@@ -1070,7 +1084,7 @@ export default {
this.inputParams.push( this.inputParams.push(
{ {
name: "", name: "",
location: 'FORM_DATA', location: 'REQUEST_FORM',
type: "STRING", type: "STRING",
isArray: false, isArray: false,
required: true, required: true,
...@@ -1087,7 +1101,7 @@ export default { ...@@ -1087,7 +1101,7 @@ export default {
{ {
name: "apiPageNum", name: "apiPageNum",
type: "LONG", type: "LONG",
location: 'FORM_DATA', location: 'REQUEST_FORM',
isArray: false, isArray: false,
required: true, required: true,
defaultValue: "1", defaultValue: "1",
...@@ -1101,7 +1115,7 @@ export default { ...@@ -1101,7 +1115,7 @@ export default {
{ {
name: "apiPageSize", name: "apiPageSize",
type: "LONG", type: "LONG",
location: 'FORM_DATA', location: 'REQUEST_FORM',
isArray: false, isArray: false,
required: true, required: true,
defaultValue: "10", defaultValue: "10",
......
...@@ -62,6 +62,8 @@ CREATE TABLE `SQLREST_API_ASSIGNMENT` ...@@ -62,6 +62,8 @@ CREATE TABLE `SQLREST_API_ASSIGNMENT`
`status` tinyint(1) not null default 0 comment '是否发布', `status` tinyint(1) not null default 0 comment '是否发布',
`open` tinyint(1) not null default 0 comment '是否公开', `open` tinyint(1) not null default 0 comment '是否公开',
`engine` varchar(16) not null default 'SQL' comment '执行引擎', `engine` varchar(16) not null default 'SQL' comment '执行引擎',
`response_format` tinytext default null comment '响应格式配置',
`naming_strategy` varchar(16) not null default 'NONE' comment '响应命名策略',
`flow_status` tinyint(1) not null default 0 comment '是否开启流量控制', `flow_status` tinyint(1) not null default 0 comment '是否开启流量控制',
`flow_grade` bigint(20) unsigned default null comment '流控类型', `flow_grade` bigint(20) unsigned default null comment '流控类型',
`flow_count` bigint(20) unsigned default null comment '流控阈值', `flow_count` bigint(20) unsigned default null comment '流控阈值',
......
...@@ -16,6 +16,10 @@ VALUES ('1', '测试', '测试使用', 'test', 'test', 'FOR_EVER', '-1', md5(uui ...@@ -16,6 +16,10 @@ VALUES ('1', '测试', '测试使用', 'test', 'test', 'FOR_EVER', '-1', md5(uui
INSERT INTO `SQLREST_CLIENT_GROUP` (`id`, `client_id`, `group_id`) INSERT INTO `SQLREST_CLIENT_GROUP` (`id`, `client_id`, `group_id`)
VALUES ('1', '1', '1'); VALUES ('1', '1', '1');
INSERT INTO `SQLREST_SYSTEM_PARAM` (`param_key`, `param_type`, `param_value`) VALUES ('apiDocOpen', 'BOOLEAN', 'true');
INSERT INTO `SQLREST_SYSTEM_PARAM` (`param_key`, `param_type`, `param_value`) VALUES ('apiDocInfoTitle', 'STRING', '在线接口文档');
INSERT INTO `SQLREST_SYSTEM_PARAM` (`param_key`, `param_type`, `param_value`) VALUES ('apiDocInfoVersion', 'STRING', '1.0');
INSERT INTO `SQLREST_SYSTEM_PARAM` (`param_key`, `param_type`, `param_value`) VALUES ('apiDocInfoDescription', 'STRING', 'Swagger在线接口文档');
ALTER TABLE `SQLREST_API_ASSIGNMENT`
ADD COLUMN `response_format` tinytext NULL comment '响应格式配置' AFTER `engine`,
ADD COLUMN `naming_strategy` varchar(16) NOT NULL DEFAULT 'NONE' comment '命名策略' AFTER `response_format` ;
UPDATE SQLREST_API_ASSIGNMENT set response_format = '{"LOCAL_DATE":"yyyy-MM-dd","DATE":"yyyy-MM-dd","TIMESTAMP":"yyyy-MM-dd HH:mm","LOCAL_DATE_TIME":"yyyy-MM-dd HH:mm","TIME":"HH:mm:ss","BIG_DECIMAL":"6"}' where response_format is null;
INSERT INTO `SQLREST_SYSTEM_PARAM` (`param_key`, `param_type`, `param_value`) VALUES ('apiDocOpen', 'BOOLEAN', 'true');
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>SQLREST工具</title><link href=/static/css/app.5c8fbd832dc67e072771290ff1dfeb72.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.4cf28694c2d9979f6f9e.js></script><script type=text/javascript src=/static/js/vendor.b8089f9fd73f8896df25.js></script><script type=text/javascript src=/static/js/app.f6411b5ec606284ab8a0.js></script></body></html> <!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>SQLREST工具</title><link href=/static/css/app.7e1ab6e082220ffa6c8de7c8d41c355c.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.2d58d9aaeea67d24a4fa.js></script><script type=text/javascript src=/static/js/vendor.b8089f9fd73f8896df25.js></script><script type=text/javascript src=/static/js/app.f6411b5ec606284ab8a0.js></script></body></html>
\ No newline at end of file \ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,o,a){for(var d,f,i,u=0,b=[];u<r.length;u++)f=r[u],t[f]&&b.push(t[f][0]),t[f]=0;for(d in o)Object.prototype.hasOwnProperty.call(o,d)&&(e[d]=o[d]);for(n&&n(r,o,a);b.length;)b.shift()();if(a)for(u=0;u<a.length;u++)i=c(c.s=a[u]);return i};var r={},t={22:0};function c(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,c),t.l=!0,t.exports}c.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,c){n=t[e]=[r,c]});n[2]=r;var o=document.getElementsByTagName("head")[0],a=document.createElement("script");a.type="text/javascript",a.charset="utf-8",a.async=!0,a.timeout=12e4,c.nc&&a.setAttribute("nonce",c.nc),a.src=c.p+"static/js/"+e+"."+{0:"04668914d5dbd2646823",1:"b17200cccd46e216dcb3",2:"140338f6a5528feea1a3",3:"8d7b8f0b413a10853aad",4:"0fbd7bc32b56153939ab",5:"f69840e8bd74f4d4e92b",6:"8f85de06573e2a5f9562",7:"7ea6008d16a44e79a428",8:"7483ee6d3a25506eb489",9:"1f165c58c9933d0da8a7",10:"cdd03027e5c73f31170c",11:"cdde61370dec5108c322",12:"57d1188c7336fe654844",13:"cdc0bd22251263ac4669",14:"42cdbd66a7803b30c641",15:"3b3f0c03ff4fed9903cc",16:"4de955682c1f7710c7ea",17:"819547b2361d544d3b8b",18:"5e7f065a8d031847e833",19:"3936346cb7e30aa279e2"}[e]+".js";var d=setTimeout(f,12e4);function f(){a.onerror=a.onload=null,clearTimeout(d);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return a.onerror=a.onload=f,o.appendChild(a),r},c.m=e,c.c=r,c.d=function(e,n,r){c.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},c.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return c.d(n,"a",n),n},c.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},c.p="/",c.oe=function(e){throw console.error(e),e}}([]); !function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,o,a){for(var f,d,i,u=0,b=[];u<r.length;u++)d=r[u],t[d]&&b.push(t[d][0]),t[d]=0;for(f in o)Object.prototype.hasOwnProperty.call(o,f)&&(e[f]=o[f]);for(n&&n(r,o,a);b.length;)b.shift()();if(a)for(u=0;u<a.length;u++)i=c(c.s=a[u]);return i};var r={},t={22:0};function c(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,c),t.l=!0,t.exports}c.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,c){n=t[e]=[r,c]});n[2]=r;var o=document.getElementsByTagName("head")[0],a=document.createElement("script");a.type="text/javascript",a.charset="utf-8",a.async=!0,a.timeout=12e4,c.nc&&a.setAttribute("nonce",c.nc),a.src=c.p+"static/js/"+e+"."+{0:"c6b968f702956d23cafc",1:"b17200cccd46e216dcb3",2:"140338f6a5528feea1a3",3:"8d7b8f0b413a10853aad",4:"0fbd7bc32b56153939ab",5:"f69840e8bd74f4d4e92b",6:"8f85de06573e2a5f9562",7:"7ea6008d16a44e79a428",8:"7483ee6d3a25506eb489",9:"1f165c58c9933d0da8a7",10:"cdd03027e5c73f31170c",11:"cdde61370dec5108c322",12:"57d1188c7336fe654844",13:"cdc0bd22251263ac4669",14:"42cdbd66a7803b30c641",15:"3b3f0c03ff4fed9903cc",16:"4de955682c1f7710c7ea",17:"819547b2361d544d3b8b",18:"5e7f065a8d031847e833",19:"3936346cb7e30aa279e2"}[e]+".js";var f=setTimeout(d,12e4);function d(){a.onerror=a.onload=null,clearTimeout(f);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return a.onerror=a.onload=d,o.appendChild(a),r},c.m=e,c.c=r,c.d=function(e,n,r){c.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},c.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return c.d(n,"a",n),n},c.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},c.p="/",c.oe=function(e){throw console.error(e),e}}([]);
//# sourceMappingURL=manifest.4cf28694c2d9979f6f9e.js.map //# sourceMappingURL=manifest.2d58d9aaeea67d24a4fa.js.map
\ No newline at end of file \ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment