PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/atlassian-pretty-urls-plugin/src/test/java/com/atlassian/prettyurls/internal/route/UrlRouterImplTest.java

https://bitbucket.org/atlassian/atlassian-pretty-urls
Java | 392 lines | 289 code | 94 blank | 9 comment | 8 complexity | dcc724d43a09e9583e21dfeed98708fd MD5 | raw file
  1. package com.atlassian.prettyurls.internal.route;
  2. import com.atlassian.plugin.servlet.filter.FilterLocation;
  3. import com.atlassian.prettyurls.api.route.DefaultUrlRouteRuleSetKey;
  4. import com.atlassian.prettyurls.api.route.RoutePredicates;
  5. import com.atlassian.prettyurls.api.route.UrlRouteRuleSet;
  6. import com.atlassian.prettyurls.mocks.MockHttpServletRequest;
  7. import com.google.common.collect.Lists;
  8. import com.google.common.collect.Sets;
  9. import com.sun.jersey.api.uri.UriTemplate;
  10. import org.apache.http.NameValuePair;
  11. import org.apache.http.client.utils.URLEncodedUtils;
  12. import org.junit.Before;
  13. import org.junit.Test;
  14. import javax.ws.rs.core.UriBuilder;
  15. import java.net.URI;
  16. import java.util.Collections;
  17. import java.util.Comparator;
  18. import java.util.List;
  19. import java.util.Set;
  20. import static com.atlassian.plugin.servlet.filter.FilterLocation.BEFORE_DISPATCH;
  21. import static org.hamcrest.CoreMatchers.equalTo;
  22. import static org.junit.Assert.assertEquals;
  23. import static org.junit.Assert.assertFalse;
  24. import static org.junit.Assert.assertNotNull;
  25. import static org.junit.Assert.assertNull;
  26. import static org.junit.Assert.assertThat;
  27. import static org.junit.Assert.assertTrue;
  28. public class UrlRouterImplTest {
  29. private UrlRouteRuleSet routeRuleSet;
  30. private UrlRouterImpl router;
  31. private MockHttpServletRequest request;
  32. private UrlRouteRuleSet.Builder builder;
  33. @Before
  34. public void setUp() throws Exception {
  35. builder = newRouteSetBuilder();
  36. router = new UrlRouterImpl(null) {
  37. Set<UrlRouteRuleSet> getRouteRuleSets(FilterLocation filterLocation, String requestURI) {
  38. return Sets.newHashSet(routeRuleSet);
  39. }
  40. };
  41. }
  42. private UrlRouteRuleSet.Builder newRouteSetBuilder() {
  43. UrlRouteRuleSet.Builder builder = new UrlRouteRuleSet.Builder();
  44. builder.setKey(new DefaultUrlRouteRuleSetKey("test.module"));
  45. builder.addTopLevelPath("avenger");
  46. return builder;
  47. }
  48. @Test
  49. public void testRoute() throws Exception {
  50. builder.addRule(
  51. "/avenger/thor/{id}/{weapon}",
  52. "/secure/Thor.jspa"
  53. );
  54. builder.addRule(
  55. "/avenger/thor/{id}/{weapon}/hair{style}",
  56. "/secure/Thor!flickHair.jspa");
  57. builder.addRule(
  58. "/avenger/hulk/{id}",
  59. "/secure/Hulk!rage.jspa");
  60. routeRuleSet = builder.build();
  61. request = new MockHttpServletRequest("/avenger/thor/id123/weapon1");
  62. //
  63. // we no longer put the extra parameters into the redirect URL
  64. // as the requestDispatcher code does this for us
  65. //
  66. request.addParameter("heat", "high");
  67. UrlRouter.Result actual = router.route(request, BEFORE_DISPATCH);
  68. assertURLEquals("/secure/Thor.jspa?id=id123&weapon=weapon1", actual);
  69. request = new MockHttpServletRequest("/miss/thor/id123/weapon1");
  70. actual = router.route(request, BEFORE_DISPATCH);
  71. assertFalse(actual.isRouted());
  72. request = new MockHttpServletRequest("/avenger/thor/id123/weapon1/hairWAVY");
  73. request.addParameter("heat", "high");
  74. actual = router.route(request, BEFORE_DISPATCH);
  75. assertURLEquals("/secure/Thor!flickHair.jspa?id=id123&weapon=weapon1&style=WAVY&", actual);
  76. request = new MockHttpServletRequest("/avenger/hulk/greenHair");
  77. actual = router.route(request, BEFORE_DISPATCH);
  78. assertURLEquals("/secure/Hulk!rage.jspa?id=greenHair", actual);
  79. }
  80. @Test
  81. public void testRouteWithGeneratorFunction() throws Exception {
  82. builder.addRule(
  83. new UriTemplate("/avenger/thor/{id}/{weapon}"),
  84. (request, variables) -> "/avenger/thor/" + variables.get("id") + "/big_" + variables.get("weapon"),
  85. Collections.emptyList());
  86. routeRuleSet = builder.build();
  87. request = new MockHttpServletRequest("/avenger/thor/id123/weapon1");
  88. UrlRouter.Result actual = router.route(request, BEFORE_DISPATCH);
  89. assertURLEquals("/avenger/thor/id123/big_weapon1", actual);
  90. }
  91. @Test
  92. public void testWithContext() throws Exception {
  93. builder.addRule(
  94. "/avenger/thor/{id}/{weapon}",
  95. "/secure/Thor.jspa");
  96. routeRuleSet = builder.build();
  97. request = new MockHttpServletRequest("/somecontext/avenger/thor/id123/weapon1");
  98. request.setContextPath("/somecontext");
  99. assertURLEquals("/secure/Thor.jspa?id=id123&weapon=weapon1", router.route(request, BEFORE_DISPATCH));
  100. }
  101. @Test
  102. public void testToURIMapping() throws Exception {
  103. builder.addRule(
  104. "/avenger/{character}/{id}/{weapon}",
  105. "/secure/LookIts{character}.jspa");
  106. routeRuleSet = builder.build();
  107. request = new MockHttpServletRequest("/avenger/Thor/id123/hammer");
  108. assertURLEquals("/secure/LookItsThor.jspa?id=id123&weapon=hammer", router.route(request, BEFORE_DISPATCH));
  109. request = new MockHttpServletRequest("/avenger/TheHulk/id456/rage");
  110. assertURLEquals("/secure/LookItsTheHulk.jspa?id=id456&weapon=rage", router.route(request, BEFORE_DISPATCH));
  111. }
  112. @Test
  113. public void testToURIMappingToRequestParams() throws Exception {
  114. builder.addRule(
  115. "/avenger/{character}/{id}/{weapon}",
  116. "/secure/LookIts{character}.jspa?tool={weapon}");
  117. routeRuleSet = builder.build();
  118. request = new MockHttpServletRequest("/avenger/Thor/id123/hammer");
  119. assertURLEquals("/secure/LookItsThor.jspa?tool=hammer&id=id123", router.route(request, BEFORE_DISPATCH));
  120. }
  121. @Test
  122. public void testHttpVerbs() throws Exception {
  123. builder.addRule(
  124. "/avenger/Thor",
  125. "/secure/Thor.jspa",
  126. Lists.newArrayList("GET"));
  127. builder.addRule(
  128. "/avenger/Thor/POSTorGET",
  129. "/secure/Thor.jspa",
  130. Lists.newArrayList("GET", "POST"));
  131. routeRuleSet = builder.build();
  132. request = new MockHttpServletRequest("/avenger/Thor");
  133. request.setMethod("POST");
  134. UrlRouterImpl.Result result = router.route(request, BEFORE_DISPATCH);
  135. assertFalse(result.isRouted());
  136. request.setMethod("get");
  137. assertURLEquals("/secure/Thor.jspa", router.route(request, BEFORE_DISPATCH));
  138. request.setMethod("GET");
  139. assertURLEquals("/secure/Thor.jspa", router.route(request, BEFORE_DISPATCH));
  140. request = new MockHttpServletRequest("/avenger/Thor/POSTorGET");
  141. request.setMethod("DELETE");
  142. result = router.route(request, BEFORE_DISPATCH);
  143. assertFalse(result.isRouted());
  144. request.setMethod("GET");
  145. assertURLEquals("/secure/Thor.jspa", router.route(request, BEFORE_DISPATCH));
  146. request.setMethod("POST");
  147. assertURLEquals("/secure/Thor.jspa", router.route(request, BEFORE_DISPATCH));
  148. }
  149. @Test
  150. public void uriWithDirectoryTraversalIsNormalised() throws Exception {
  151. request = new MockHttpServletRequest("/avenger/Thor/../CaptainAmerica");
  152. request.setMethod("get");
  153. String requestUri = router.makeRequestURI(request);
  154. assertNotNull(requestUri);
  155. assertThat(requestUri, equalTo("/avenger/CaptainAmerica"));
  156. }
  157. @Test
  158. public void badUriReturnsUnRoutableRoute() {
  159. request = new MockHttpServletRequest("http://avenger/^Thor^");
  160. request.setMethod("get");
  161. UrlRouterImpl.Result route = router.route(request, BEFORE_DISPATCH);
  162. assertNotNull(route);
  163. assertFalse(route.isRouted());
  164. assertNull(route.toURI());
  165. }
  166. @Test
  167. public void testLowLevelRoutePredicates() throws Exception {
  168. builder.addRule(
  169. "/avenger/Thor",
  170. "/secure/Thor.jspa",
  171. Lists.newArrayList("GET"),
  172. RoutePredicates.alwaysFalse());
  173. builder.addRule(
  174. "/avenger/Thor/POSTorGET",
  175. "/secure/Thor.jspa",
  176. Lists.newArrayList("GET", "POST"),
  177. RoutePredicates.alwaysTrue());
  178. routeRuleSet = builder.build();
  179. request = new MockHttpServletRequest("/avenger/Thor");
  180. request.setMethod("GET");
  181. UrlRouterImpl.Result result = router.route(request, BEFORE_DISPATCH);
  182. assertFalse(result.isRouted());
  183. request = new MockHttpServletRequest("/avenger/Thor/POSTorGET");
  184. request.setMethod("GET");
  185. result = router.route(request, BEFORE_DISPATCH);
  186. assertTrue(result.isRouted());
  187. }
  188. @Test
  189. public void testTopLevelRoutePredicates_when_off() throws Exception {
  190. // turn the top level off
  191. builder.setPredicate(RoutePredicates.<UrlRouteRuleSet>alwaysFalse());
  192. builder.addRule(
  193. "/avenger/Thor",
  194. "/secure/Thor.jspa",
  195. Lists.newArrayList("GET"),
  196. RoutePredicates.alwaysTrue());
  197. builder.addRule(
  198. "/avenger/Thor/POSTorGET",
  199. "/secure/Thor.jspa",
  200. Lists.newArrayList("GET", "POST"),
  201. RoutePredicates.alwaysTrue());
  202. routeRuleSet = builder.build();
  203. request = new MockHttpServletRequest("/avenger/Thor");
  204. UrlRouterImpl.Result result = router.route(request, BEFORE_DISPATCH);
  205. assertFalse(result.isRouted());
  206. request = new MockHttpServletRequest("/avenger/Thor/POSTorGET");
  207. result = router.route(request, BEFORE_DISPATCH);
  208. assertFalse(result.isRouted());
  209. }
  210. @Test
  211. public void testTopLevelRoutePredicates_when_on() throws Exception {
  212. builder.setPredicate(RoutePredicates.<UrlRouteRuleSet>alwaysTrue());
  213. builder.addRule(
  214. "/avenger/Thor",
  215. "/secure/Thor.jspa",
  216. Lists.newArrayList("GET"),
  217. RoutePredicates.alwaysTrue());
  218. builder.addRule(
  219. "/avenger/Thor/POSTorGET",
  220. "/secure/Thor.jspa",
  221. Lists.newArrayList("GET", "POST"),
  222. RoutePredicates.alwaysTrue());
  223. routeRuleSet = builder.build();
  224. request = new MockHttpServletRequest("/avenger/Thor");
  225. UrlRouterImpl.Result result = router.route(request, BEFORE_DISPATCH);
  226. assertTrue(result.isRouted());
  227. request = new MockHttpServletRequest("/avenger/Thor/POSTorGET");
  228. result = router.route(request, BEFORE_DISPATCH);
  229. assertTrue(result.isRouted());
  230. }
  231. @Test
  232. public void testMultipleRuleSetsDoesJaxRSMatching() throws Exception {
  233. builder = newRouteSetBuilder();
  234. builder.addRule(
  235. "/avenger/{character}/{id}/{weapon}",
  236. "/secure/LookIts{character}.jspa?withHis={weapon}");
  237. UrlRouteRuleSet routeRuleSet1 = builder.build();
  238. // in a single set world the former would over-ride this
  239. // but not when there are 2 sets
  240. builder = newRouteSetBuilder();
  241. builder.addRule(
  242. "/avenger/{character}/{id}/{weapon}/{shield}",
  243. "/secure/LookItsAlso{character}.jspa");
  244. UrlRouteRuleSet routeRuleSet2 = builder.build();
  245. router = new UrlRouterImpl(null) {
  246. Set<UrlRouteRuleSet> getRouteRuleSets(FilterLocation filterLocation, String requestURI) {
  247. return Sets.newHashSet(routeRuleSet1, routeRuleSet2);
  248. }
  249. };
  250. //
  251. // with multiple rule sets we use JAX-RS matching.
  252. request = new MockHttpServletRequest("/avenger/Thor/1/Hammer/Hair");
  253. UrlRouter.Result actual = router.route(request, BEFORE_DISPATCH);
  254. assertURLEquals("/secure/LookItsAlsoThor.jspa", actual);
  255. request = new MockHttpServletRequest("/avenger/Thor/1/Hammer/Hair");
  256. request = new MockHttpServletRequest("/avenger/Hulk/1/Fists");
  257. actual = router.route(request, BEFORE_DISPATCH);
  258. assertURLEquals("/secure/LookItsHulk.jspa?withHis=Fists", actual);
  259. }
  260. private void assertURLEquals(String expected, UrlRouter.Result result) {
  261. assertTrue(result.isRouted());
  262. URI expectedURI = UriBuilder.fromUri(expected).build();
  263. URI actualURI = UriBuilder.fromUri(result.toURI()).build();
  264. assertEquals(expectedURI.getPath(), actualURI.getPath());
  265. List<NameValuePair> expectedPairs = URLEncodedUtils.parse(expectedURI, "UTF-8");
  266. List<NameValuePair> actualPairs = URLEncodedUtils.parse(actualURI, "UTF-8");
  267. assertTrue(sameNVP(expectedPairs, actualPairs));
  268. }
  269. private boolean sameNVP(List<NameValuePair> expectedPairs, List<NameValuePair> actualPairs) {
  270. return containsNVPs(expectedPairs, actualPairs) && containsNVPs(expectedPairs, actualPairs);
  271. }
  272. private boolean containsNVPs(List<NameValuePair> expectedPairs, List<NameValuePair> actualPairs) {
  273. for (NameValuePair expectedPair : expectedPairs) {
  274. boolean containedWithin = false;
  275. for (NameValuePair actualPair : actualPairs) {
  276. if (NVP_COMPARATOR.compare(expectedPair, actualPair) == 0) {
  277. containedWithin = true;
  278. break;
  279. }
  280. }
  281. if (!containedWithin) {
  282. return false;
  283. }
  284. }
  285. return true;
  286. }
  287. public static final NVPComparator NVP_COMPARATOR = new NVPComparator();
  288. private static class NVPComparator implements Comparator<NameValuePair> {
  289. @Override
  290. public int compare(NameValuePair o1, NameValuePair o2) {
  291. int rc = o1.getName().compareTo(o2.getName());
  292. if (rc == 0) {
  293. rc = o1.getValue().compareTo(o2.getValue());
  294. }
  295. return rc;
  296. }
  297. }
  298. }