I'm having a problem with relative URLs.
If the current page is:
content/mypage/n1/p1/n2/fred
And it contains a link to
content/mypage/n1/p1/n2/jane
The relative URL rendered to HTML is:
../../../../../../jane
Which of course is wrong as the browser tries to jump to:
jane
instead of
content/mypage/n1/p1/n2/jane
I looked at the URL renderer and it was returning just 'jane' instead of
../jane
I'm not sure if this is the right approach but I changed
UrlRenderer.java (seemed like an 'out by 1' bug) so that it returns the
correct relative URL string. The git diff with a very recent
wicket-1.5.x branch HEAD is shown below.
../jane
Even though this now returns the correct relative URL this doesn't the
problem. Somehow later at render time the extra ../../../../ sequence
was prefixed to the already correct URL.
I think I know why - the URL is double processed by the UrlRenderer.
First it is converted from a Url object to a relative string via String
UrlRenderer.renderRelativeUrl(final Url url) - returning ../jane as
above (after patch is applied).
Second, during rendering it is passed to
RelativePathPrefixHandler.onComponentTag which makes a relative path of
the path that is already relative, using String
UrlRenderer.renderContextRelativeUrl(String url) - of course this time
there is no common path segments so the sequence of ../ segments
prefixed to the given URL string takes it right back to the root.
Why would the relative path be processed again?
I can understand that UrlRenderer might need two relative Url creation
methods - one that works on a Url object and one that works on a String
object but I can't understand why both would be called as that breaks
things.
Path to 'fix' (maybe, if it is actually broken)
UrlRenderer.renderRelativeUrl(final Url url).
index d636450..ebe87f5 100644
---
a/wicket-request/src/main/java/org/apache/wicket/request/UrlRenderer.jav
a
+++
b/wicket-request/src/main/java/org/apache/wicket/request/UrlRenderer.jav
a
@@ -25,6 +25,8 @@ import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.string.PrependingStringBuffer;
import org.apache.wicket.util.string.Strings;
+import javax.servlet.http.HttpServletRequest;
+
/**
* Takes care of rendering URLs.
* <p>
@@ -211,30 +213,41 @@ public class UrlRenderer
}
}
- // we want the new URL to have at least one
segment (other than possible ../)
- if ((last != null) && (urlSegments.isEmpty() ||
(baseUrlSegments.size() == common)))
- {
- --common;
- urlSegments.add(0, last);
- }
-
- int baseUrlSize = baseUrlSegments.size();
- if (common + 1 == baseUrlSize &&
urlSegments.isEmpty())
+ if ( common > 0 )
{
- newSegments.add(".");
+ // URL has some elements common to
baseUrl so output a relative URL
+
+ // we want the new URL to have at least
one segment (other than possible ../)
+ if ((last != null) &&
(urlSegments.isEmpty() || (baseUrlSegments.size() == common)))
+ {
+ --common;
+ urlSegments.add(0, last);
+ }
+
+ int baseUrlSize =
baseUrlSegments.size();
+ if (common + 1 == baseUrlSize &&
urlSegments.isEmpty())
+ {
+ newSegments.add(".");
+ }
+ else
+ {
+
+ for (int i = common; i <
baseUrlSize; ++i)
+ {
+ newSegments.add("..");
+ }
+ }
+ newSegments.addAll(urlSegments);
+
+ String renderedUrl = new
Url(newSegments, url.getQueryParameters()).toString();
+ return Strings.isEmpty(renderedUrl) ?
"." : renderedUrl;
}
else
{
-
- for (int i = common + 1; i <
baseUrlSize; ++i)
- {
- newSegments.add("..");
- }
+ // Url has no common elements so convert
to an absolute URL
+ return "/" + url.toString();
}
- newSegments.addAll(urlSegments);
-
- String renderedUrl = new Url(newSegments,
url.getQueryParameters()).toString();
- return Strings.isEmpty(renderedUrl) ? "." :
renderedUrl;
+ }