diff --git a/grails-web-url-mappings/src/main/groovy/org/codehaus/groovy/grails/web/mapping/DefaultLinkGenerator.groovy b/grails-web-url-mappings/src/main/groovy/org/codehaus/groovy/grails/web/mapping/DefaultLinkGenerator.groovy index 75eb720db5c..ffad44c34b0 100644 --- a/grails-web-url-mappings/src/main/groovy/org/codehaus/groovy/grails/web/mapping/DefaultLinkGenerator.groovy +++ b/grails-web-url-mappings/src/main/groovy/org/codehaus/groovy/grails/web/mapping/DefaultLinkGenerator.groovy @@ -15,6 +15,8 @@ */ package org.codehaus.groovy.grails.web.mapping +import java.util.regex.Pattern + import grails.util.Environment import grails.util.GrailsNameUtils import grails.util.GrailsWebUtil @@ -44,6 +46,8 @@ import org.springframework.http.HttpMethod @CompileStatic class DefaultLinkGenerator implements LinkGenerator, PluginManagerAware { + private static final Pattern absoluteUrlPattern = Pattern.compile('^[A-Za-z][A-Za-z0-9+\\-.]*:.*$') + private static final Map REST_RESOURCE_ACTION_TO_HTTP_METHOD_MAP = [ create:"GET", save:"POST", @@ -97,18 +101,19 @@ class DefaultLinkGenerator implements LinkGenerator, PluginManagerAware { def writer = new StringBuilder() // prefer URI attribute if (attrs.get(ATTRIBUTE_URI) != null) { - final base = handleAbsolute(attrs) - if (base != null) { - writer << base - } - else { - def cp = attrs.get(ATTRIBUTE_CONTEXT_PATH) - if (cp == null) cp = getContextPath() - if (cp != null) { - writer << cp + def uri = attrs.get(ATTRIBUTE_URI).toString() + if(!isUriAbsolute(uri)){ + final base = handleAbsolute(attrs) + if (base != null) { + writer << base + } + else { + def cp = attrs.get(ATTRIBUTE_CONTEXT_PATH) + if (cp == null) cp = getContextPath() + if (cp != null) + writer << cp } } - def uri = attrs.get(ATTRIBUTE_URI).toString() writer << uri def paramsAttribute = attrs.get(ATTRIBUTE_PARAMS) @@ -364,6 +369,10 @@ class DefaultLinkGenerator implements LinkGenerator, PluginManagerAware { } } + private boolean isUriAbsolute(String uri) { + // not using new URI(uri).absolute in order to avoid create the URI object, which is slow + return absoluteUrlPattern.matcher(uri).matches() + } /** * Get the declared URL of the server from config, or guess at localhost for non-production. diff --git a/grails-web-url-mappings/src/test/groovy/org/codehaus/groovy/grails/web/mapping/LinkGeneratorSpec.groovy b/grails-web-url-mappings/src/test/groovy/org/codehaus/groovy/grails/web/mapping/LinkGeneratorSpec.groovy index 99c35bd8de9..6a93f2362a1 100644 --- a/grails-web-url-mappings/src/test/groovy/org/codehaus/groovy/grails/web/mapping/LinkGeneratorSpec.groovy +++ b/grails-web-url-mappings/src/test/groovy/org/codehaus/groovy/grails/web/mapping/LinkGeneratorSpec.groovy @@ -19,12 +19,27 @@ class LinkGeneratorSpec extends Specification { def baseUrl = "http://myserver.com/foo" def context = "/bar" + def someAbsoluteUrl = "http://www.grails.org/" def resource = null def linkParams = [:] def pluginManager def mainCssResource = [dir:'css', file:'main.css'] + def "Test absolute link"() { + when: + linkParams.uri = someAbsoluteUrl + linkParams.absolute = true + then: + link == someAbsoluteUrl + + when: + linkParams.uri = someAbsoluteUrl + + then: + link == someAbsoluteUrl + } + def "Test create link with root URI"() { when: linkParams.uri = '/' @@ -307,4 +322,4 @@ class Widget { String toString() { name } -} \ No newline at end of file +}