diff --git a/brouter-core/src/test/java/btools/router/RoutingEngineTest.java b/brouter-core/src/test/java/btools/router/RoutingEngineTest.java index ba2dc90..1f95be4 100644 --- a/brouter-core/src/test/java/btools/router/RoutingEngineTest.java +++ b/brouter-core/src/test/java/btools/router/RoutingEngineTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import java.io.File; import java.net.URL; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; public class RoutingEngineTest { @@ -22,22 +23,36 @@ public class RoutingEngineTest { @Test public void routeCrossingSegmentBorder() { - String msg = calcRoute(8.720897, 50.002515, 8.723658, 49.997510, "testtrack"); + String msg = calcRoute(8.720897, 50.002515, 8.723658, 49.997510, "testtrack", new RoutingContext()); // error message from router? Assert.assertNull("routing failed: " + msg, msg); // if the track didn't change, we expect the first alternative also File a1 = new File(workingDir, "testtrack1.gpx"); - Assert.assertTrue("result content missmatch", a1.exists()); + a1.deleteOnExit(); + Assert.assertTrue("result content mismatch", a1.exists()); } @Test public void routeDestinationPointFarOff() { - String msg = calcRoute(8.720897, 50.002515, 16.723658, 49.997510, "notrack"); + String msg = calcRoute(8.720897, 50.002515, 16.723658, 49.997510, "notrack", new RoutingContext()); Assert.assertTrue(msg, msg != null && msg.contains("not found")); } - private String calcRoute(double flon, double flat, double tlon, double tlat, String trackname) { + @Test + public void overrideParam() { + RoutingContext rctx = new RoutingContext(); + rctx.keyValues = new HashMap<>(); + rctx.keyValues.put("avoid_unsafe", "1.0"); + String msg = calcRoute(8.723037, 50.000491, 8.712737, 50.002899, "paramTrack", rctx); + Assert.assertNull("routing failed: " + msg, msg); + + File trackFile = new File(workingDir, "paramTrack1.gpx"); + trackFile.deleteOnExit(); + Assert.assertTrue("result content mismatch", trackFile.exists()); + } + + private String calcRoute(double flon, double flat, double tlon, double tlat, String trackname, RoutingContext rctx) { String wd = workingDir.getAbsolutePath(); List wplist = new ArrayList<>(); @@ -54,7 +69,6 @@ public class RoutingEngineTest { n.ilat = 90000000 + (int) (tlat * 1000000 + 0.5); wplist.add(n); - RoutingContext rctx = new RoutingContext(); rctx.localFunction = wd + "/../../../../misc/profiles2/trekking.brf"; RoutingEngine re = new RoutingEngine( diff --git a/brouter-core/src/test/resources/paramTrack0.gpx b/brouter-core/src/test/resources/paramTrack0.gpx new file mode 100644 index 0000000..f3de18c --- /dev/null +++ b/brouter-core/src/test/resources/paramTrack0.gpx @@ -0,0 +1,76 @@ + + + + + brouter_trekking_0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/brouter-server/build.gradle b/brouter-server/build.gradle index 2e377ab..c52d524 100644 --- a/brouter-server/build.gradle +++ b/brouter-server/build.gradle @@ -70,8 +70,6 @@ distributions { } dependencies { - testImplementation 'junit:junit:4.13.1' - implementation project(':brouter-codec') implementation project(':brouter-core') implementation project(':brouter-expressions') @@ -79,4 +77,6 @@ dependencies { implementation project(':brouter-mapaccess') implementation project(':brouter-util') + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.json:json:20180813' } diff --git a/brouter-server/src/main/java/btools/server/RouteServer.java b/brouter-server/src/main/java/btools/server/RouteServer.java index 62c74e5..24abb13 100644 --- a/brouter-server/src/main/java/btools/server/RouteServer.java +++ b/brouter-server/src/main/java/btools/server/RouteServer.java @@ -81,7 +81,6 @@ public class RouteServer extends Thread implements Comparable { String agent = null; String encodings = null; String xff = null; // X-Forwarded-For - String referer = null; // more headers until first empty line for (; ; ) { @@ -108,12 +107,6 @@ public class RouteServer extends Thread implements Comparable { if (line.startsWith("x-forwarded-for: ")) { xff = line.substring("x-forwarded-for: ".length()); } - if (line.startsWith("Referer: ")) { - referer = line.substring("Referer: ".length()); - } - if (line.startsWith("Referrer: ")) { - referer = line.substring("Referrer: ".length()); - } } InetAddress ip = clientSocket.getInetAddress(); @@ -139,15 +132,6 @@ public class RouteServer extends Thread implements Comparable { } } - if (referer != null && referer.indexOf("brouter.de/brouter-web") >= 0) { - if (getline.indexOf("%7C") >= 0 && getline.indexOf("%2C") >= 0) { - writeHttpHeader(bw, HTTP_STATUS_FORBIDDEN); - bw.write("Spam? please stop"); - bw.flush(); - return; - } - } - if (getline.startsWith("GET /favicon.ico")) { writeHttpHeader(bw, HTTP_STATUS_NOT_FOUND); bw.flush(); diff --git a/brouter-server/src/main/java/btools/server/request/RequestHandler.java b/brouter-server/src/main/java/btools/server/request/RequestHandler.java index fb69d30..5364c5b 100644 --- a/brouter-server/src/main/java/btools/server/request/RequestHandler.java +++ b/brouter-server/src/main/java/btools/server/request/RequestHandler.java @@ -1,7 +1,7 @@ package btools.server.request; -import java.util.HashMap; import java.util.List; +import java.util.Map; import btools.router.OsmNodeNamed; import btools.router.OsmTrack; @@ -10,9 +10,9 @@ import btools.server.ServiceContext; public abstract class RequestHandler { protected ServiceContext serviceContext; - protected HashMap params; + protected Map params; - public RequestHandler(ServiceContext serviceContext, HashMap params) { + public RequestHandler(ServiceContext serviceContext, Map params) { this.serviceContext = serviceContext; this.params = params; } diff --git a/brouter-server/src/test/java/btools/server/RequestHandlerTest.java b/brouter-server/src/test/java/btools/server/RequestHandlerTest.java new file mode 100644 index 0000000..2d5f698 --- /dev/null +++ b/brouter-server/src/test/java/btools/server/RequestHandlerTest.java @@ -0,0 +1,27 @@ +package btools.server; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.HashMap; + +import btools.router.RoutingContext; +import btools.server.request.ServerHandler; + +public class RequestHandlerTest { + @Test + @Ignore("Parameters are currently handled by RouteServer, not RequestHandler") + public void parseParameters() { + HashMap params = new HashMap<>(); + params.put("lonlats", "8.799297,49.565883|8.811764,49.563606"); + params.put("profile", "trekking"); + params.put("alternativeidx", "0"); + params.put("profile:test", "bar"); + ServerHandler serverHandler = new ServerHandler(null, params); + RoutingContext routingContext = serverHandler.readRoutingContext(); + + Assert.assertEquals("trekking", routingContext.localFunction); + Assert.assertEquals("bar", routingContext.keyValues.get("test")); + } +} diff --git a/brouter-server/src/test/java/btools/server/RouteServerTest.java b/brouter-server/src/test/java/btools/server/RouteServerTest.java new file mode 100644 index 0000000..e5d3521 --- /dev/null +++ b/brouter-server/src/test/java/btools/server/RouteServerTest.java @@ -0,0 +1,169 @@ +package btools.server; + + +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class RouteServerTest { + private static final String host = "localhost"; + private static final String port = "17777"; + private static final String baseUrl = "http://" + host + ":" + port + "/"; + + @ClassRule + public static TemporaryFolder profileDir = new TemporaryFolder(); + + @BeforeClass + public static void setupServer() throws IOException, InterruptedException { + File workingDir = new File(".").getCanonicalFile(); + File segmentDir = new File(workingDir, "../brouter-map-creator/build/resources/test/tmp/segments"); + File profileSourceDir = new File(workingDir, "../misc/profiles2"); + // Copy required files to temporary dir because profile upload will create files + Files.copy(Paths.get(profileSourceDir.getAbsolutePath(), "lookups.dat"), Paths.get(profileDir.getRoot().getAbsolutePath(), "lookups.dat")); + Files.copy(Paths.get(profileSourceDir.getAbsolutePath(), "trekking.brf"), Paths.get(profileDir.getRoot().getAbsolutePath(), "trekking.brf")); + String customProfileDir = "custom"; + + Runnable runnable = () -> { + try { + RouteServer.main(new String[]{segmentDir.getAbsolutePath(), profileDir.getRoot().getAbsolutePath(), customProfileDir, port, "1"}); + } catch (Exception e) { + e.printStackTrace(); + } + }; + + Thread thread = new Thread(runnable); + thread.start(); + + // Busy-wait for server startup + URL requestUrl = new URL(baseUrl); + HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); + for (int i = 20; i >= 0; i--) { + try { + httpConnection.setConnectTimeout(1000); + httpConnection.connect(); + break; + } catch (ConnectException e) { + if (i == 0) { + throw e; + } + Thread.sleep(100); + } + } + } + + @Test + public void defaultRouteTrekking() throws IOException { + URL requestUrl = new URL(baseUrl + "brouter?lonlats=8.723037,50.000491|8.712737,50.002899&nogos=&profile=trekking&alternativeidx=0&format=geojson"); + + HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); + httpConnection.connect(); + + Assert.assertEquals(HttpURLConnection.HTTP_OK, httpConnection.getResponseCode()); + + InputStream inputStream = httpConnection.getInputStream(); + JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8)); + Assert.assertEquals("1204", geoJson.query("/features/0/properties/track-length")); + } + + @Test + public void overrideParameter() throws IOException { + URL requestUrl = new URL(baseUrl + "brouter?lonlats=8.723037,50.000491|8.712737,50.002899&nogos=&profile=trekking&alternativeidx=0&format=geojson&profile:avoid_unsafe=1"); + HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); + httpConnection.connect(); + + Assert.assertEquals(HttpURLConnection.HTTP_OK, httpConnection.getResponseCode()); + + InputStream inputStream = httpConnection.getInputStream(); + JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8)); + Assert.assertEquals("1902", geoJson.query("/features/0/properties/track-length")); + } + + @Test + public void uploadValidProfile() throws IOException { + URL requestUrl = new URL(baseUrl + "brouter/profile"); + HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); + + httpConnection.setRequestMethod("POST"); + httpConnection.setDoOutput(true); + String dummyProfile = "---context:global # following code refers to global config\n" + + "\n" + + "# this prevents suppression of unused tags, so they are visibly in the data tab\n" + + "assign processUnusedTags = true\n" + + "assign validForFoot = true\n" + + "\n" + + "---context:way # following code refers to way-tags\n" + + "\n" + + "assign costfactor\n" + + " switch and highway= not route=ferry 100000 1\n" + + "\n" + + "---context:node # following code refers to node tags\n" + + "assign initialcost = 0\n"; + try (OutputStream outputStream = httpConnection.getOutputStream()) { + outputStream.write(dummyProfile.getBytes(StandardCharsets.UTF_8)); + } + + Assert.assertEquals(HttpURLConnection.HTTP_OK, httpConnection.getResponseCode()); + InputStream inputStream = httpConnection.getInputStream(); + String response = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + JSONObject jsonResponse = new JSONObject(response); + Assert.assertTrue(jsonResponse.query("/profileid").toString().startsWith("custom_")); + Assert.assertFalse(jsonResponse.has("error")); + } + + @Test + public void uploadInvalidProfile() throws IOException { + URL requestUrl = new URL(baseUrl + "brouter/profile"); + HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); + + httpConnection.setRequestMethod("POST"); + httpConnection.setDoOutput(true); + String invalidProfile = ""; + try (OutputStream outputStream = httpConnection.getOutputStream()) { + outputStream.write(invalidProfile.getBytes(StandardCharsets.UTF_8)); + } + + // It would be better if RouteServer would return "400 Bad Request" + Assert.assertEquals(HttpURLConnection.HTTP_OK, httpConnection.getResponseCode()); + InputStream inputStream = httpConnection.getInputStream(); + String response = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + JSONObject jsonResponse = new JSONObject(response); + // Returns profileid, but profile isn't valid + Assert.assertTrue(jsonResponse.query("/profileid").toString().startsWith("custom_")); + Assert.assertTrue(jsonResponse.has("error")); + } + + @Test + public void robots() throws IOException { + URL requestUrl = new URL(baseUrl + "robots.txt"); + HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); + httpConnection.connect(); + + Assert.assertEquals(HttpURLConnection.HTTP_OK, httpConnection.getResponseCode()); + + String content = new String(httpConnection.getInputStream().readAllBytes(), StandardCharsets.UTF_8); + Assert.assertTrue(content.contains("Disallow: /")); + } + + @Test + public void invalidUrl() throws IOException { + URL requestUrl = new URL(baseUrl + "invalid"); + HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); + httpConnection.connect(); + + Assert.assertEquals(HttpURLConnection.HTTP_NOT_FOUND, httpConnection.getResponseCode()); + } +}