headers = servletRequest.getHeaders(headerName);
- while (headers.hasMoreElements()) {//sometimes more than one value
+ while (headers.hasMoreElements()) {
String headerValue = headers.nextElement();
- // In case the proxy host is running multiple virtual servers,
- // rewrite the Host header to ensure that we get content from
- // the correct virtual server
if (!doPreserveHost && headerName.equalsIgnoreCase(HttpHeaders.HOST)) {
- HttpHost host = getTargetHost(servletRequest);
+ HttpHost host = targetHost;
headerValue = host.getHostName();
- if (host.getPort() != -1)
- headerValue += ":"+host.getPort();
+ if (host.getPort() != -1){
+ headerValue += ":"+host.getPort();
+ }
} else if (!doPreserveCookies && headerName.equalsIgnoreCase(org.apache.http.cookie.SM.COOKIE)) {
headerValue = getRealCookie(headerValue);
}
@@ -438,7 +270,6 @@ public class ProxyServlet extends HttpServlet {
}
}
- /** Copy proxied response headers back to the servlet client. */
protected void copyResponseHeaders(HttpResponse proxyResponse, HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {
for (Header header : proxyResponse.getAllHeaders()) {
@@ -446,58 +277,43 @@ public class ProxyServlet extends HttpServlet {
}
}
- /** Copy a proxied response header back to the servlet client.
- * This is easily overwritten to filter out certain headers if desired.
- */
protected void copyResponseHeader(HttpServletRequest servletRequest,
HttpServletResponse servletResponse, Header header) {
String headerName = header.getName();
- if (hopByHopHeaders.containsHeader(headerName))
- return;
+ if (hopByHopHeaders.containsHeader(headerName)){
+ return;
+ }
String headerValue = header.getValue();
if (headerName.equalsIgnoreCase(org.apache.http.cookie.SM.SET_COOKIE) ||
headerName.equalsIgnoreCase(org.apache.http.cookie.SM.SET_COOKIE2)) {
copyProxyCookie(servletRequest, servletResponse, headerValue);
} else if (headerName.equalsIgnoreCase(HttpHeaders.LOCATION)) {
- // LOCATION Header may have to be rewritten.
servletResponse.addHeader(headerName, rewriteUrlFromResponse(servletRequest, headerValue));
} else {
servletResponse.addHeader(headerName, headerValue);
}
}
- /**
- * Copy cookie from the proxy to the servlet client.
- * Replaces cookie path to local path and renames cookie to avoid collisions.
- */
protected void copyProxyCookie(HttpServletRequest servletRequest,
HttpServletResponse servletResponse, String headerValue) {
- //build path for resulting cookie
- String path = servletRequest.getContextPath(); // path starts with / or is empty string
- path += servletRequest.getServletPath(); // servlet path starts with / or is empty string
+ String path = servletRequest.getContextPath();
+ path += servletRequest.getServletPath();
if(path.isEmpty()){
path = "/";
}
for (HttpCookie cookie : HttpCookie.parse(headerValue)) {
- //set cookie name prefixed w/ a proxy value so it won't collide w/ other cookies
String proxyCookieName = doPreserveCookies ? cookie.getName() : getCookieNamePrefix(cookie.getName()) + cookie.getName();
Cookie servletCookie = new Cookie(proxyCookieName, cookie.getValue());
servletCookie.setComment(cookie.getComment());
servletCookie.setMaxAge((int) cookie.getMaxAge());
- servletCookie.setPath(path); //set to the path of the proxy servlet
- // don't set cookie domain
+ servletCookie.setPath(path);
servletCookie.setSecure(cookie.getSecure());
servletCookie.setVersion(cookie.getVersion());
servletResponse.addCookie(servletCookie);
}
}
- /**
- * Take any client cookies that were originally from the proxy and prepare them to send to the
- * proxy. This relies on cookie headers being set correctly according to RFC 6265 Sec 5.4.
- * This also blocks any local cookies from being sent to the proxy.
- */
protected String getRealCookie(String cookieValue) {
StringBuilder escapedCookie = new StringBuilder();
String cookies[] = cookieValue.split("[;,]");
@@ -517,14 +333,11 @@ public class ProxyServlet extends HttpServlet {
return escapedCookie.toString();
}
- /** The string prefixing rewritten cookies. */
protected String getCookieNamePrefix(String name) {
return "!Proxy!" + getServletConfig().getServletName();
}
- /** Copy response body data (the entity) from the proxy to the servlet client. */
- protected void copyResponseEntity(HttpResponse proxyResponse, HttpServletResponse servletResponse,
- HttpRequest proxyRequest, HttpServletRequest servletRequest)
+ protected void copyResponseEntity(HttpResponse proxyResponse, HttpServletResponse servletResponse)
throws IOException {
HttpEntity entity = proxyResponse.getEntity();
if (entity != null) {
@@ -533,81 +346,32 @@ public class ProxyServlet extends HttpServlet {
}
}
- /**
- * Reads the request URI from {@code servletRequest} and rewrites it, considering targetUri.
- * It's used to make the new request.
- */
- protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
- StringBuilder uri = new StringBuilder(500);
- uri.append(getTargetUri(servletRequest));
- // Handle the path given to the servlet
+ protected String getTargetUri(HttpServletRequest servletRequest) {
String pathInfo = servletRequest.getPathInfo();
- if (pathInfo != null) {//ex: /my/path.html
- // getPathInfo() returns decoded string, so we need encodeUriQuery to encode "%" characters
- uri.append(encodeUriQuery(pathInfo, true));
- }
- // Handle the query string & fragment
- String queryString = servletRequest.getQueryString();//ex:(following '?'): name=value&foo=bar#fragment
- String fragment = null;
- //split off fragment from queryString, updating queryString if found
- if (queryString != null) {
- int fragIdx = queryString.indexOf('#');
- if (fragIdx >= 0) {
- fragment = queryString.substring(fragIdx + 1);
- queryString = queryString.substring(0,fragIdx);
+ targetUri = pathInfo.split("/")[1];
+ String host = targetUri.split(":")[0];
+ String port = targetUri.split(":")[1];
+ try {
+ targetUriObj = new URI(targetUri);
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e.getMessage(),e);
}
- }
-
- queryString = rewriteQueryStringFromRequest(servletRequest, queryString);
- if (queryString != null && queryString.length() > 0) {
- uri.append('?');
- // queryString is not decoded, so we need encodeUriQuery not to encode "%" characters, to avoid double-encoding
- uri.append(encodeUriQuery(queryString, false));
- }
-
- if (doSendUrlFragment && fragment != null) {
- uri.append('#');
- // fragment is not decoded, so we need encodeUriQuery not to encode "%" characters, to avoid double-encoding
- uri.append(encodeUriQuery(fragment, false));
- }
- return uri.toString();
+ targetHost = new HttpHost(host, Integer.valueOf(port));
+ return "http:/" + pathInfo;
}
- protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
- return queryString;
- }
- /**
- * For a redirect response from the target server, this translates {@code theUrl} to redirect to
- * and translates it to one the original client can use.
- */
protected String rewriteUrlFromResponse(HttpServletRequest servletRequest, String theUrl) {
- //TODO document example paths
- final String targetUri = getTargetUri(servletRequest);
if (theUrl.startsWith(targetUri)) {
- /*-
- * The URL points back to the back-end server.
- * Instead of returning it verbatim we replace the target path with our
- * source path in a way that should instruct the original client to
- * request the URL pointed through this Proxy.
- * We do this by taking the current request and rewriting the path part
- * using this servlet's absolute path and the path from the returned URL
- * after the base target URL.
- */
- StringBuffer curUrl = servletRequest.getRequestURL();//no query
+ StringBuffer curUrl = servletRequest.getRequestURL();
int pos;
- // Skip the protocol part
if ((pos = curUrl.indexOf("://"))>=0) {
- // Skip the authority part
- // + 3 to skip the separator between protocol and authority
if ((pos = curUrl.indexOf("/", pos + 3)) >=0) {
- // Trim everything after the authority part.
curUrl.setLength(pos);
}
}
- // Context path starts with a / if it is not blank
curUrl.append(servletRequest.getContextPath());
- // Servlet path starts with a / if it is not blank
curUrl.append(servletRequest.getServletPath());
curUrl.append(theUrl, targetUri.length(), theUrl.length());
return curUrl.toString();
@@ -615,66 +379,4 @@ public class ProxyServlet extends HttpServlet {
return theUrl;
}
- /** The target URI as configured. Not null. */
- public String getTargetUri() { return targetUri; }
-
- /**
- * Encodes characters in the query or fragment part of the URI.
- *
- * Unfortunately, an incoming URI sometimes has characters disallowed by the spec. HttpClient
- * insists that the outgoing proxied request has a valid URI because it uses Java's {@link URI}.
- * To be more forgiving, we must escape the problematic characters. See the URI class for the
- * spec.
- *
- * @param in example: name=value&foo=bar#fragment
- * @param encodePercent determine whether percent characters need to be encoded
- */
- protected static CharSequence encodeUriQuery(CharSequence in, boolean encodePercent) {
- //Note that I can't simply use URI.java to encode because it will escape pre-existing escaped things.
- StringBuilder outBuf = null;
- Formatter formatter = null;
- for(int i = 0; i < in.length(); i++) {
- char c = in.charAt(i);
- boolean escape = true;
- if (c < 128) {
- if (asciiQueryChars.get((int)c) && !(encodePercent && c == '%')) {
- escape = false;
- }
- } else if (!Character.isISOControl(c) && !Character.isSpaceChar(c)) {//not-ascii
- escape = false;
- }
- if (!escape) {
- if (outBuf != null)
- outBuf.append(c);
- } else {
- //escape
- if (outBuf == null) {
- outBuf = new StringBuilder(in.length() + 5*3);
- outBuf.append(in,0,i);
- formatter = new Formatter(outBuf);
- }
- //leading %, 0 padded, width 2, capital hex
- formatter.format("%%%02X",(int)c);//TODO
- }
- }
- return outBuf != null ? outBuf : in;
- }
-
- protected static final BitSet asciiQueryChars;
- static {
- char[] c_unreserved = "_-!.~'()*".toCharArray();//plus alphanum
- char[] c_punct = ",;:$&+=".toCharArray();
- char[] c_reserved = "?/[]@".toCharArray();//plus punct
-
- asciiQueryChars = new BitSet(128);
- for(char c = 'a'; c <= 'z'; c++) asciiQueryChars.set((int)c);
- for(char c = 'A'; c <= 'Z'; c++) asciiQueryChars.set((int)c);
- for(char c = '0'; c <= '9'; c++) asciiQueryChars.set((int)c);
- for(char c : c_unreserved) asciiQueryChars.set((int)c);
- for(char c : c_punct) asciiQueryChars.set((int)c);
- for(char c : c_reserved) asciiQueryChars.set((int)c);
-
- asciiQueryChars.set((int)'%');//leave existing percent escapes in place
- }
-
}
\ No newline at end of file
diff --git a/backend/src/main/java/io/metersphere/service/FunctionalReportService.java b/backend/src/main/java/io/metersphere/service/FunctionalReportService.java
index 7b8211fb8a..a24b20f5c2 100644
--- a/backend/src/main/java/io/metersphere/service/FunctionalReportService.java
+++ b/backend/src/main/java/io/metersphere/service/FunctionalReportService.java
@@ -1,5 +1,8 @@
package io.metersphere.service;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import io.metersphere.base.domain.FucTestLog;
import io.metersphere.base.domain.FucTestReport;
import io.metersphere.base.domain.FucTestReportExample;
import io.metersphere.base.mapper.FucTestReportMapper;
@@ -20,6 +23,8 @@ public class FunctionalReportService {
private FucTestReportMapper fucTestReportMapper;
@Resource
private ExtFunctionalTestReportMapper extFunctionalTestReportMapper;
+ @Resource
+ private ZaleniumService zaleniumService;
public List getRecentReportList(ReportRequest request) {
FucTestReportExample example = new FucTestReportExample();
@@ -38,4 +43,12 @@ public class FunctionalReportService {
public FunctionalReportDTO getReportTestAndProInfo(String reportId) {
return extFunctionalTestReportMapper.getReportTestAndProInfo(reportId);
}
+
+ public FucTestLog getTestLog(String reportId) {
+ FucTestReport fucTestReport = fucTestReportMapper.selectByPrimaryKey(reportId);
+ String content = fucTestReport.getContent();
+ String endpoint = "http://localhost:4444";
+ FucTestLog fucTestLogs = JSON.parseObject(content, FucTestLog.class);
+ return zaleniumService.getFucTestLog(endpoint, fucTestLogs);
+ }
}
diff --git a/backend/src/main/java/io/metersphere/service/ZaleniumService.java b/backend/src/main/java/io/metersphere/service/ZaleniumService.java
index 7e5b937bfe..3e8b069fe7 100644
--- a/backend/src/main/java/io/metersphere/service/ZaleniumService.java
+++ b/backend/src/main/java/io/metersphere/service/ZaleniumService.java
@@ -1,4 +1,93 @@
package io.metersphere.service;
+import com.alibaba.fastjson.JSONObject;
+import io.metersphere.base.domain.*;
+import io.metersphere.base.mapper.FucTestMapper;
+import io.metersphere.base.mapper.FucTestReportMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Service
public class ZaleniumService {
+
+ @Resource
+ RestTemplate restTemplate;
+
+ @Resource
+ FucTestReportMapper fucTestReportMapper;
+
+ @Resource
+ FucTestMapper fucTestMapper;
+
+ public void syncTestResult(){
+
+ List zaleniumTests = getZaleniumTest();
+
+ List fucTestIds = zaleniumTests.stream().map(test -> test.getTestName())
+ .collect(Collectors.toList());
+
+ FucTestExample fucTestExample = new FucTestExample();
+ fucTestExample.createCriteria().andIdIn(fucTestIds);
+ List fucTests = fucTestMapper.selectByExample(fucTestExample);
+
+ List reportIds = fucTestReportMapper.selectByExample(new FucTestReportExample()).stream().map(report -> report.getId()).collect(Collectors.toList());
+
+ Map fucTestMaps = fucTests.stream()
+ .collect(Collectors.toMap(FucTest::getId, Function.identity()));
+
+ zaleniumTests.forEach(item -> {
+ if(!reportIds.contains(item.getTestName())){
+ saveFucTestReport(item, fucTestMaps.get(item.getTestName()));
+ }
+ });
+ }
+
+ private void saveFucTestReport(ZaleniumTest item, FucTest fucTest) {
+ FucTestReport fucTestReport = new FucTestReport();
+ fucTestReport.setCreateTime(System.currentTimeMillis());
+ fucTestReport.setUpdateTime(System.currentTimeMillis());
+ fucTestReport.setTestId(item.getTestName());
+ fucTestReport.setStatus("1");
+ fucTestReport.setId(item.getTestName());
+ JSONObject content = new JSONObject();
+ content.put("videoUrl", "dashboard/" + item.getFileName());
+ content.put("seleniumLog", "dashboard/logs/" + item.getTestNameNoExtension() + "/selenium-multinode-stderr.log");
+ content.put("browserDriverLog", "dashboard/" + item.getBrowserDriverLogFileName());
+ fucTestReport.setContent(content.toJSONString());
+ if(fucTest != null){
+ fucTestReport.setDescription(fucTest.getDescription());
+ fucTestReport.setName(fucTest.getName());
+ } else {
+ fucTestReport.setDescription("ZaleniumTest");
+ fucTestReport.setName(item.getTestName());
+ }
+ fucTestReportMapper.insert(fucTestReport);
+ }
+
+ private List getZaleniumTest() {
+ List tests = new ArrayList<>();
+ String url = "http://localhost:4444/dashboard/information?lastDateAddedToDashboard=0";
+ tests.addAll(Arrays.asList(restTemplate.getForObject(url, ZaleniumTest[].class)));
+ return tests;
+ }
+
+ public FucTestLog getFucTestLog(String endpoint, FucTestLog logPaths) {
+ FucTestLog testLog = new FucTestLog();
+ testLog.setSeleniumLog(getZaleniumTestLog(endpoint, logPaths.getSeleniumLog()));
+ testLog.setBrowserDriverLog(getZaleniumTestLog(endpoint, logPaths.getBrowserDriverLog()));
+ return testLog;
+ }
+
+ private String getZaleniumTestLog(String endpoint, String logPath) {
+ return restTemplate.getForObject(endpoint + "/" + logPath, String.class);
+ }
+
}
diff --git a/backend/src/test/java/io/metersphere/ZaleniumTest.java b/backend/src/test/java/io/metersphere/ZaleniumTest.java
index 5751d8a9ed..7b6031c2c7 100644
--- a/backend/src/test/java/io/metersphere/ZaleniumTest.java
+++ b/backend/src/test/java/io/metersphere/ZaleniumTest.java
@@ -1,4 +1,23 @@
package io.metersphere;
+import io.metersphere.service.ZaleniumService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import javax.annotation.Resource;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ZaleniumTest {
+
+ @Resource
+ ZaleniumService zaleniumService;
+
+ @Test
+ public void sysnZaleniumTest(){
+ zaleniumService.syncTestResult();
+ }
+
}