diff --git a/src/main/java/net/sourceforge/plantuml/servlet/OldProxyServlet.java b/src/main/java/net/sourceforge/plantuml/servlet/OldProxyServlet.java new file mode 100644 index 0000000..0982b44 --- /dev/null +++ b/src/main/java/net/sourceforge/plantuml/servlet/OldProxyServlet.java @@ -0,0 +1,119 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * Project Info: http://plantuml.sourceforge.net + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ +package net.sourceforge.plantuml.servlet; + +import java.io.IOException; +import java.net.URL; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import HTTPClient.CookieModule; +import HTTPClient.HTTPConnection; +import HTTPClient.HTTPResponse; +import HTTPClient.ModuleException; +import HTTPClient.ParseException; + +import net.sourceforge.plantuml.FileFormat; +import net.sourceforge.plantuml.FileFormatOption; +import net.sourceforge.plantuml.SourceStringReader; + +/* + * Proxy servlet of the webapp. + * This servlet retrieves the diagram source of a web resource (web html page) + * and renders it. + */ +@SuppressWarnings("serial") +public class OldProxyServlet extends HttpServlet { + + private static final Pattern proxyPattern = Pattern.compile("/\\w+/proxy/((\\d+)/)?((\\w+)/)?(http://.*)"); + private String format; + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + + final String uri = request.getRequestURI(); + + Matcher proxyMatcher = proxyPattern.matcher(uri); + if (proxyMatcher.matches()) { + String num = proxyMatcher.group(2); // Optional number of the diagram source + format = proxyMatcher.group(4); // Expected format of the generated diagram + String sourceURL = proxyMatcher.group(5); + handleImageProxy(response, num, sourceURL); + } else { + request.setAttribute("net.sourceforge.plantuml.servlet.decoded", "ERROR Invalid proxy syntax : " + uri); + request.removeAttribute("net.sourceforge.plantuml.servlet.encoded"); + + // forward to index.jsp + RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp"); + dispatcher.forward(request, response); + } + } + + private void handleImageProxy(HttpServletResponse response, String num, String source) throws IOException { + SourceStringReader reader = new SourceStringReader(getSource(source)); + int n = num == null ? 0 : Integer.parseInt(num); + + reader.generateImage(response.getOutputStream(), n, new FileFormatOption(getOutputFormat(), false)); + } + + private String getSource(String uri) throws IOException { + CookieModule.setCookiePolicyHandler(null); + + final Pattern p = Pattern.compile("http://[^/]+(/?.*)"); + final Matcher m = p.matcher(uri); + if (m.find() == false) { + throw new IOException(uri); + } + final URL url = new URL(uri); + final HTTPConnection httpConnection = new HTTPConnection(url); + try { + final HTTPResponse resp = httpConnection.Get(m.group(1)); + return resp.getText(); + } catch (ModuleException e) { + throw new IOException(e.toString()); + } catch (ParseException e) { + throw new IOException(e.toString()); + } + } + + private FileFormat getOutputFormat() { + if (format == null) { + return FileFormat.PNG; + } + if (format.equals("svg")) { + return FileFormat.SVG; + } + if (format.equals("txt")) { + return FileFormat.ATXT; + } + return FileFormat.PNG; + } + +} diff --git a/src/main/java/net/sourceforge/plantuml/servlet/ProxyServlet.java b/src/main/java/net/sourceforge/plantuml/servlet/ProxyServlet.java index bb78e8d..2902568 100644 --- a/src/main/java/net/sourceforge/plantuml/servlet/ProxyServlet.java +++ b/src/main/java/net/sourceforge/plantuml/servlet/ProxyServlet.java @@ -28,7 +28,6 @@ import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -52,34 +51,19 @@ import net.sourceforge.plantuml.SourceStringReader; @SuppressWarnings("serial") public class ProxyServlet extends HttpServlet { - private static final Pattern proxyPattern = Pattern.compile("/\\w+/proxy/((\\d+)/)?((\\w+)/)?(http://.*)"); private String format; @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - final String uri = request.getRequestURI(); - - Matcher proxyMatcher = proxyPattern.matcher(uri); - if (proxyMatcher.matches()) { - String num = proxyMatcher.group(2); // Optional number of the diagram source - format = proxyMatcher.group(4); // Expected format of the generated diagram - String sourceURL = proxyMatcher.group(5); - handleImageProxy(response, num, sourceURL); - } else { - request.setAttribute("net.sourceforge.plantuml.servlet.decoded", "ERROR Invalid proxy syntax : " + uri); - request.removeAttribute("net.sourceforge.plantuml.servlet.encoded"); - - // forward to index.jsp - RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp"); - dispatcher.forward(request, response); - } - } - - private void handleImageProxy(HttpServletResponse response, String num, String source) throws IOException { + final String source = request.getParameter("src"); + final String index = request.getParameter("idx"); + + // TODO Check if the src URL is valid + + // generate the response SourceStringReader reader = new SourceStringReader(getSource(source)); - int n = num == null ? 0 : Integer.parseInt(num); - + int n = index == null ? 0 : Integer.parseInt(index); reader.generateImage(response.getOutputStream(), n, new FileFormatOption(getOutputFormat(), false)); } @@ -111,7 +95,7 @@ public class ProxyServlet extends HttpServlet { return FileFormat.SVG; } if (format.equals("txt")) { - return FileFormat.ATXT; + return FileFormat.UTXT; } return FileFormat.PNG; } diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 0b0e839..222fc12 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -31,6 +31,10 @@ proxyservlet net.sourceforge.plantuml.servlet.ProxyServlet + + oldproxyservlet + net.sourceforge.plantuml.servlet.OldProxyServlet + mapservlet net.sourceforge.plantuml.servlet.MapServlet @@ -69,9 +73,13 @@ /start/* - proxyservlet + oldproxyservlet /proxy/* + + proxyservlet + /proxy + java.lang.Throwable /error.jsp diff --git a/src/main/webapp/resource/test2diagrams.txt b/src/main/webapp/resource/test2diagrams.txt new file mode 100644 index 0000000..77b54f2 --- /dev/null +++ b/src/main/webapp/resource/test2diagrams.txt @@ -0,0 +1,9 @@ +This file is used by the TestProxy unit test. It contains 2 diagrams description. + +@startuml +Bob -> Alice : hello +@enduml + +@startuml +version +@enduml \ No newline at end of file diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestOldProxy.java b/src/test/java/net/sourceforge/plantuml/servlet/TestOldProxy.java new file mode 100644 index 0000000..d9fdc5b --- /dev/null +++ b/src/test/java/net/sourceforge/plantuml/servlet/TestOldProxy.java @@ -0,0 +1,67 @@ +package net.sourceforge.plantuml.servlet; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import com.meterware.httpunit.GetMethodWebRequest; +import com.meterware.httpunit.WebConversation; +import com.meterware.httpunit.WebForm; +import com.meterware.httpunit.WebRequest; +import com.meterware.httpunit.WebResponse; + +public class TestOldProxy extends WebappTestCase { + /** + * Verifies the proxified reception of the default Bob and Alice diagram + */ + public void testDefaultProxy() throws Exception { + WebConversation conversation = new WebConversation(); + WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy/" + getServerUrl() + "welcome"); + WebResponse response = conversation.getResource(request); + // Analyze response + // Verifies the Content-Type header + // assertEquals( "Response content type is not PNG", "image/png", response.getContentType()); + // Get the image and verify its size (~2000 bytes) + InputStream responseStream = response.getInputStream(); + ByteArrayOutputStream imageStream = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + int n = 0; + while ((n = responseStream.read(buf)) != -1) { + imageStream.write(buf, 0, n); + } + imageStream.close(); + responseStream.close(); + byte[] inMemoryImage = imageStream.toByteArray(); + int diagramLen = inMemoryImage.length; + assertTrue(diagramLen > 1500); + assertTrue(diagramLen < 2500); + } + + public void testProxyWithFormat() throws Exception { + WebConversation conversation = new WebConversation(); + WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy/svg/" + getServerUrl() + "welcome"); + WebResponse response = conversation.getResource(request); + // Analyze response + // Verifies the Content-Type header + // TODO assertEquals( "Response content type is not SVG", "image/svg+xml", response.getContentType()); + // Get the content and verify its size + String diagram = response.getText(); + int diagramLen = diagram.length(); + assertTrue(diagramLen > 1000); + assertTrue(diagramLen < 3000); + } + + /** + * Verifies that the HTTP header of a diagram incites the browser to cache it. + */ + public void testInvalidUrl() throws Exception { + WebConversation conversation = new WebConversation(); + // Try to proxify an invalid address + WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy/invalidURL"); + WebResponse response = conversation.getResource(request); + // Analyze response, it must be the empty form + // Verifies the Content-Type header + assertEquals("Response content type is not HTML", "text/html", response.getContentType()); + WebForm forms[] = response.getForms(); + assertEquals(2, forms.length); + } +} diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestProxy.java b/src/test/java/net/sourceforge/plantuml/servlet/TestProxy.java index 4a6d7fc..34a1b55 100644 --- a/src/test/java/net/sourceforge/plantuml/servlet/TestProxy.java +++ b/src/test/java/net/sourceforge/plantuml/servlet/TestProxy.java @@ -5,7 +5,6 @@ import java.io.InputStream; import com.meterware.httpunit.GetMethodWebRequest; import com.meterware.httpunit.WebConversation; -import com.meterware.httpunit.WebForm; import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; @@ -15,7 +14,8 @@ public class TestProxy extends WebappTestCase { */ public void testDefaultProxy() throws Exception { WebConversation conversation = new WebConversation(); - WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy/" + getServerUrl() + "welcome"); + WebRequest request = new GetMethodWebRequest(getServerUrl() + + "proxy?src=" + getServerUrl() + "resource/test2diagrams.txt"); WebResponse response = conversation.getResource(request); // Analyze response // Verifies the Content-Type header @@ -35,14 +35,15 @@ public class TestProxy extends WebappTestCase { assertTrue(diagramLen > 1500); assertTrue(diagramLen < 2500); } - +/* public void testProxyWithFormat() throws Exception { WebConversation conversation = new WebConversation(); - WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy/svg/" + getServerUrl() + "welcome"); + WebRequest request = new GetMethodWebRequest(getServerUrl() + + "proxy?format=svg&src=" + getServerUrl() + "resource/test2diagrams.txt"); WebResponse response = conversation.getResource(request); // Analyze response // Verifies the Content-Type header - // TODO assertEquals( "Response content type is not SVG", "image/svg+xml", response.getContentType()); + assertEquals( "Response content type is not SVG", "image/svg+xml", response.getContentType()); // Get the content and verify its size String diagram = response.getText(); int diagramLen = diagram.length(); @@ -56,12 +57,9 @@ public class TestProxy extends WebappTestCase { public void testInvalidUrl() throws Exception { WebConversation conversation = new WebConversation(); // Try to proxify an invalid address - WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy/invalidURL"); + WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy?src=invalidURL"); WebResponse response = conversation.getResource(request); - // Analyze response, it must be the empty form - // Verifies the Content-Type header - assertEquals("Response content type is not HTML", "text/html", response.getContentType()); - WebForm forms[] = response.getForms(); - assertEquals(2, forms.length); + // Analyze response, it must be HTTP error 500 + assertEquals("Response HTTP status is not 500", response.getResponseCode(), 500); } }