@@ -290,6 +290,7 @@ public static boolean isAscii(String string) {
290290 * @throws MalformedURLException if an error occurred generating the URL
291291 */
292292 public static URL resolve (URL base , String relUrl ) throws MalformedURLException {
293+ relUrl = stripControlChars (relUrl );
293294 // workaround: java resolves '//path/file + ?foo' to '//path/?foo', not '//path/file?foo' as desired
294295 if (relUrl .startsWith ("?" ))
295296 relUrl = base .getPath () + relUrl ;
@@ -308,7 +309,9 @@ public static URL resolve(URL base, String relUrl) throws MalformedURLException
308309 * @param relUrl the relative URL to resolve. (If it's already absolute, it will be returned)
309310 * @return an absolute URL if one was able to be generated, or the empty string if not
310311 */
311- public static String resolve (final String baseUrl , final String relUrl ) {
312+ public static String resolve (String baseUrl , String relUrl ) {
313+ // workaround: java will allow control chars in a path URL and may treat as relative, but Chrome / Firefox will strip and may see as a scheme. Normalize to browser's view.
314+ baseUrl = stripControlChars (baseUrl ); relUrl = stripControlChars (relUrl );
312315 try {
313316 URL base ;
314317 try {
@@ -327,6 +330,11 @@ public static String resolve(final String baseUrl, final String relUrl) {
327330 }
328331 private static final Pattern validUriScheme = Pattern .compile ("^[a-zA-Z][a-zA-Z0-9+-.]*:" );
329332
333+ private static final Pattern controlChars = Pattern .compile ("[\\ x00-\\ x1f]*" ); // matches ascii 0 - 31, to strip from url
334+ private static String stripControlChars (final String input ) {
335+ return controlChars .matcher (input ).replaceAll ("" );
336+ }
337+
330338 private static final ThreadLocal <Stack <StringBuilder >> threadLocalBuilders = new ThreadLocal <Stack <StringBuilder >>() {
331339 @ Override
332340 protected Stack <StringBuilder > initialValue () {
0 commit comments