沙箱环境支持下载

1.x
tanghc 6 years ago
parent 000bc715a5
commit a06974504a
  1. 72
      sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/HttpTool.java
  2. 20
      sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/DownloadController.java
  3. 20
      sop-test/src/main/java/com/gitee/sop/test/HttpTool.java
  4. 30
      sop-website/website-front/pages/sandbox/sandbox.js
  5. 4
      sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/DocItem.java
  6. 28
      sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java
  7. 1
      sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/SwaggerDocParser.java

@ -13,6 +13,7 @@ import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.RequestBody; import okhttp3.RequestBody;
import okhttp3.Response; import okhttp3.Response;
import okhttp3.ResponseBody;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -51,14 +52,17 @@ public class HttpTool {
protected void initHttpClient(HttpToolConfig httpToolConfig) { protected void initHttpClient(HttpToolConfig httpToolConfig) {
httpClient = new OkHttpClient.Builder() httpClient = new OkHttpClient.Builder()
.connectTimeout(httpToolConfig.connectTimeoutSeconds, TimeUnit.SECONDS) // 设置链接超时时间,默认10秒 // 设置链接超时时间,默认10秒
.connectTimeout(httpToolConfig.connectTimeoutSeconds, TimeUnit.SECONDS)
.readTimeout(httpToolConfig.readTimeoutSeconds, TimeUnit.SECONDS) .readTimeout(httpToolConfig.readTimeoutSeconds, TimeUnit.SECONDS)
.writeTimeout(httpToolConfig.writeTimeoutSeconds, TimeUnit.SECONDS) .writeTimeout(httpToolConfig.writeTimeoutSeconds, TimeUnit.SECONDS)
.cookieJar(new CookieJar() { .cookieJar(new CookieJar() {
@Override
public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) { public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
cookieStore.put(httpUrl.host(), list); cookieStore.put(httpUrl.host(), list);
} }
@Override
public List<Cookie> loadForRequest(HttpUrl httpUrl) { public List<Cookie> loadForRequest(HttpUrl httpUrl) {
List<Cookie> cookies = cookieStore.get(httpUrl.host()); List<Cookie> cookies = cookieStore.get(httpUrl.host());
return cookies != null ? cookies : new ArrayList<Cookie>(); return cookies != null ? cookies : new ArrayList<Cookie>();
@ -204,22 +208,24 @@ public class HttpTool {
* @return * @return
* @throws IOException * @throws IOException
*/ */
public String requestFile(String url, Map<String, String> form, Map<String, String> header, List<UploadFile> files) public String requestFile(String url, Map<String, ?> form, Map<String, String> header, List<UploadFile> files)
throws IOException { throws IOException {
// 创建MultipartBody.Builder,用于添加请求的数据 // 创建MultipartBody.Builder,用于添加请求的数据
MultipartBody.Builder bodyBuilder = new MultipartBody.Builder(); MultipartBody.Builder bodyBuilder = new MultipartBody.Builder();
bodyBuilder.setType(MultipartBody.FORM); bodyBuilder.setType(MultipartBody.FORM);
for (UploadFile uploadFile : files) { for (UploadFile uploadFile : files) {
bodyBuilder.addFormDataPart(uploadFile.getName(), // 请求的名字 // 请求的名字
uploadFile.getFileName(), // 文件的文字,服务器端用来解析的 bodyBuilder.addFormDataPart(uploadFile.getName(),
RequestBody.create(null, uploadFile.getFileData()) // 创建RequestBody,把上传的文件放入 // 文件的文字,服务器端用来解析的
uploadFile.getFileName(),
// 创建RequestBody,把上传的文件放入
RequestBody.create(null, uploadFile.getFileData())
); );
} }
Set<Map.Entry<String, String>> entrySet = form.entrySet(); for (Map.Entry<String, ?> entry : form.entrySet()) {
for (Map.Entry<String, String> entry : entrySet) { bodyBuilder.addFormDataPart(entry.getKey(), String.valueOf(entry.getValue()));
bodyBuilder.addFormDataPart(entry.getKey(), entry.getValue());
} }
RequestBody requestBody = bodyBuilder.build(); RequestBody requestBody = bodyBuilder.build();
@ -238,6 +244,51 @@ public class HttpTool {
} }
} }
/**
* 请求数据
*
* @param url 请求url
* @param form 请求数据
* @param header header
* @return 返回Response
* @throws IOException
*/
public Response requestForResponse(String url, Map<String, ?> form, Map<String, String> header, HTTPMethod method) throws IOException {
Request.Builder requestBuilder = buildRequestBuilder(url, form, method);
// 添加header
addHeader(requestBuilder, header);
Request request = requestBuilder.build();
return httpClient
.newCall(request)
.execute();
}
/**
* 下载文件
*
* @param url 请求url
* @param form 请求数据
* @param header header
* @return 返回文件流
* @throws IOException
*/
public InputStream downloadFile(String url, Map<String, ?> form, Map<String, String> header) throws IOException {
Request.Builder requestBuilder = buildRequestBuilder(url, form, HTTPMethod.GET);
// 添加header
addHeader(requestBuilder, header);
Request request = requestBuilder.build();
Response response = httpClient
.newCall(request)
.execute();
if (response.isSuccessful()) {
ResponseBody body = response.body();
return body == null ? null : body.byteStream();
}
return null;
}
private void addHeader(Request.Builder builder, Map<String, String> header) { private void addHeader(Request.Builder builder, Map<String, String> header) {
if (header != null) { if (header != null) {
Set<Map.Entry<String, String>> entrySet = header.entrySet(); Set<Map.Entry<String, String>> entrySet = header.entrySet();
@ -256,10 +307,15 @@ public class HttpTool {
} }
public enum HTTPMethod { public enum HTTPMethod {
/** http GET */
GET, GET,
/** http POST */
POST, POST,
/** http PUT */
PUT, PUT,
/** http HEAD */
HEAD, HEAD,
/** http DELETE */
DELETE; DELETE;
private HTTPMethod() { private HTTPMethod() {

@ -2,15 +2,15 @@ package com.gitee.sop.storyweb.controller;
import com.gitee.sop.servercommon.annotation.ApiMapping; import com.gitee.sop.servercommon.annotation.ApiMapping;
import com.gitee.sop.storyweb.controller.param.StoryParam; import com.gitee.sop.storyweb.controller.param.StoryParam;
import org.apache.commons.io.FileUtils; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import java.io.File;
import java.io.IOException; import java.io.IOException;
/** /**
@ -18,20 +18,24 @@ import java.io.IOException;
* *
* @author tanghc * @author tanghc
*/ */
@Api(tags = "文件下载")
@Controller @Controller
public class DownloadController { public class DownloadController {
@ApiMapping(value = "story.download") @ApiOperation(value = "文件下载", notes = "演示文件下载")
public ResponseEntity<byte[]> export(StoryParam param) throws IOException { @ApiMapping(value = "story.download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE/* 这个一定要加,不然沙箱文档不起作用 */)
public ResponseEntity<byte[]> download(StoryParam param) throws IOException {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
// 假设下载classpath下的application.properties文件 // 假设下载classpath下的application.properties文件
ClassPathResource resource = new ClassPathResource("/application.properties"); ClassPathResource resource = new ClassPathResource("/application.properties");
File file = resource.getFile();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", file.getName()); headers.setContentDispositionFormData("attachment", resource.getFilename());
return new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK); return ResponseEntity
.ok()
.headers(headers)
.body(IOUtils.toByteArray(resource.getInputStream()));
} }
} }

@ -244,6 +244,26 @@ public class HttpTool {
} }
} }
/**
* 请求数据
*
* @param url 请求url
* @param form 请求数据
* @param header header
* @return 返回Response
* @throws IOException
*/
public Response requestForResponse(String url, Map<String, ?> form, Map<String, String> header, HTTPMethod method) throws IOException {
Request.Builder requestBuilder = buildRequestBuilder(url, form, method);
// 添加header
addHeader(requestBuilder, header);
Request request = requestBuilder.build();
return httpClient
.newCall(request)
.execute();
}
/** /**
* 下载文件 * 下载文件
* *

@ -138,6 +138,12 @@ function doTest() {
} }
}); });
data.bizContent = JSON.stringify(bizContent); data.bizContent = JSON.stringify(bizContent);
if (isDownloadRequest(currentItem)) {
data.isDownloadRequest = true;
downloadFile(data);
// window.open()
return;
}
// 确定文件数量,并且知道参数名称 // 确定文件数量,并且知道参数名称
if (uploadFileObjects.length > 0) { if (uploadFileObjects.length > 0) {
var formData = new FormData(); var formData = new FormData();
@ -151,6 +157,20 @@ function doTest() {
} }
} }
function isDownloadRequest(currentItem) {
var produces = currentItem.produces;
if (!produces) {
return false;
}
for (var i = 0; i < produces.length; i++) {
var produce = produces[i];
if (produce.indexOf('application/octet-stream') > -1) {
return true;
}
}
return false;
}
function putVal(obj, input) { function putVal(obj, input) {
if (input.type == 'text') { if (input.type == 'text') {
obj[input.name] = input.value; obj[input.name] = input.value;
@ -204,6 +224,16 @@ function postFile(data, formData) {
}); });
} }
function downloadFile(data) {
$('.dl-form').remove();
var url = SopConfig.url + '/sandbox/test';
var form = $('<form class="dl-form"></form>').attr("action", url).attr("method", "get");
for(var key in data) {
form.append($("<input>").attr("type", "hidden").attr("name", key).attr("value", data[key]));
}
form.appendTo('body').submit();
}
function successHandler(resp) { function successHandler(resp) {
setReqInfo(resp); setReqInfo(resp);
showRespnfo(resp.apiResult); showRespnfo(resp.apiResult);

@ -20,6 +20,10 @@ public class DocItem {
/** http method列表 */ /** http method列表 */
private Collection<String> httpMethodList; private Collection<String> httpMethodList;
private Collection<String> produces;
List<DocParameter> requestParameters; List<DocParameter> requestParameters;
List<DocParameter> responseParameters; List<DocParameter> responseParameters;

@ -1,12 +1,16 @@
package com.gitee.sop.websiteserver.controller; package com.gitee.sop.websiteserver.controller;
import com.gitee.sop.registryapi.bean.HttpTool; import com.gitee.sop.registryapi.bean.HttpTool;
import com.gitee.sop.registryapi.bean.HttpTool.*; import com.gitee.sop.registryapi.bean.HttpTool.HTTPMethod;
import com.gitee.sop.registryapi.bean.HttpTool.UploadFile;
import com.gitee.sop.websiteserver.sign.AlipayApiException; import com.gitee.sop.websiteserver.sign.AlipayApiException;
import com.gitee.sop.websiteserver.sign.AlipaySignature; import com.gitee.sop.websiteserver.sign.AlipaySignature;
import com.gitee.sop.websiteserver.util.UploadUtil; import com.gitee.sop.websiteserver.util.UploadUtil;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import okhttp3.Headers;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair; import org.apache.http.NameValuePair;
@ -26,6 +30,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Collection; import java.util.Collection;
@ -60,7 +65,10 @@ public class SandboxController {
, @RequestParam String version , @RequestParam String version
, @RequestParam String bizContent , @RequestParam String bizContent
, @RequestParam(defaultValue = "get") String httpMethod , @RequestParam(defaultValue = "get") String httpMethod
, HttpServletRequest request) throws AlipayApiException { , @RequestParam(defaultValue = "false") boolean isDownloadRequest
, HttpServletRequest request
, HttpServletResponse response
) throws AlipayApiException {
Assert.isTrue(StringUtils.isNotBlank(appId), "AppId不能为空"); Assert.isTrue(StringUtils.isNotBlank(appId), "AppId不能为空");
Assert.isTrue(StringUtils.isNotBlank(privateKey), "PrivateKey不能为空"); Assert.isTrue(StringUtils.isNotBlank(privateKey), "PrivateKey不能为空");
@ -111,7 +119,21 @@ public class SandboxController {
try { try {
String responseData; String responseData;
if (!CollectionUtils.isEmpty(files)) { if (isDownloadRequest) {
Response resp = httpTool.requestForResponse(url, params, Collections.emptyMap(), HTTPMethod.GET);
Headers respHeaders = resp.headers();
ResponseBody body = resp.body();
if (body == null) {
return null;
}
respHeaders
.names()
.forEach(name -> response.setHeader(name, respHeaders.get(name)));
IOUtils.copy(body.byteStream(), response.getOutputStream());
response.flushBuffer();
return null;
} else if (!CollectionUtils.isEmpty(files)) {
responseData = httpTool.requestFile(url, params, Collections.emptyMap(), files); responseData = httpTool.requestFile(url, params, Collections.emptyMap(), files);
} else { } else {
responseData = httpTool.request(url, params, Collections.emptyMap(), HTTPMethod.fromValue(httpMethod)); responseData = httpTool.request(url, params, Collections.emptyMap(), HTTPMethod.fromValue(httpMethod));

@ -92,6 +92,7 @@ public class SwaggerDocParser implements DocParser {
docItem.setSummary(docInfo.getString("summary")); docItem.setSummary(docInfo.getString("summary"));
docItem.setDescription(docInfo.getString("description")); docItem.setDescription(docInfo.getString("description"));
docItem.setMultiple(docInfo.getString("multiple") != null); docItem.setMultiple(docInfo.getString("multiple") != null);
docItem.setProduces(docInfo.getJSONArray("produces").toJavaList(String.class));
String moduleName = this.buildModuleName(docInfo, docRoot); String moduleName = this.buildModuleName(docInfo, docRoot);
docItem.setModule(moduleName); docItem.setModule(moduleName);
List<DocParameter> docParameterList = this.buildRequestParameterList(docInfo, docRoot); List<DocParameter> docParameterList = this.buildRequestParameterList(docInfo, docRoot);

Loading…
Cancel
Save