apache / apache/grails-core

Grails 3.3.9 Static URL tokens not encoded by RegexUrlMapping

Open
#11,263 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
Groovy
Stars
2.9k
Forks
975
Avg merge
1d 22h
Merged PRs (30d)
92

Description

### Task List

- [x] Steps to reproduce provided
- [x] ~~Stacktrace (if present) provided~~
- [ ] Example that reproduces the problem uploaded to Github
- [x] Full description of the issue provided (see below)

### Steps to Reproduce

1. Create an empty grails 3.3.9 project
2. Create Controller `EncodingTestController.groovy`
```
package staticurltokenencoding

class EncodingTestController {

def index() { }

def staticToken() {
render text: """
Static Token

${g.createLink(mapping: 'staticToken')}
${g.createLink(mapping: 'semiStaticToken', params: [foo: 'bar']}
""".stripIndent(),
contentType: 'text/plain'
}

def semiStaticToken() {
render text: """
Semi Static Token

${g.createLink(mapping: 'staticToken')}
${g.createLink(mapping: 'semiStaticToken', params: [foo: params.foo])}
""".stripIndent(),
contentType: 'text/plain'
}
}
```
3. Change `UrlMappings.groovy` to
```
package staticurltokenencoding

class UrlMappings {

static final UML_a = '\u00e4' // ä -- LATIN SMALL LETTER A WITH DIAERESIS

static mappings = {
// "/StäticToken" would be equivalent with correct file encoding
name staticToken: "/St${UML_a}ticToken" (controller: 'encodingTest', action: 'staticToken')

// "/StäticToken-$foo" would be equivalent with correct file encoding
name semiStaticToken: "/St${UML_a}ticToken-$foo" (controller: 'encodingTest', action: 'semiStaticToken')

"/"(view:"/index")
"500"(view:'/error')
"404"(view:'/notFound')
}
}

```
4. Run the app on localhost:8080

### Expected Behaviour

Creating Links with `mapping: 'staticToken'` and `mapping: 'semiStaticToken'` will behave consistently.

So the response body of `http://localhost:8080/St%C3%A4ticToken` is expected to be
```

Static Token

/St%C3%A4ticToken
/St%C3%A4ticToken-bar

```

### Actual Behaviour

Creating Links with `mapping: 'staticToken'` and `mapping: 'semiStaticToken'` behaves inconsistently.

The response body of `http://localhost:8080/St%C3%A4ticToken` actually is
```

Static Token

/StäticToken
/St%C3%A4ticToken-bar

```

So the static URL-Token `StäticToken` of the mapping `staticToken` gets not encoded while link creation, but the static part of the semi static token `StäticToken-$foo` gets encoded.

This Behavior is hardcoded in `org.grails.web.mapping.RegexUrlMapping.createURLInternal(Map paramValues, String encoding, boolean includeContextPath):409ff`:
```
// tokenize URL by '/'
// for each token
// if token has placeholder(s), do replacements and encode
else {
uri.append(SLASH).append(token);
}
```

### Environment Information

Tested on various envoronments e.g.:

- **Operating System**: Ubuntu 18.04, CentOS 6
- **Grails Version:** 3.2.9, 3.3.9
- **JDK Version:** 8
- **Container Version (If Applicable):** `grails run-app`, jetty, …

### Workarround

Because we have many of those mappings with static and semi-static tokens, containing umlauts, targeting multiple controllers and actions, the only practical workarround was to provide our own Version of `org.grails.web.mapping.RegexUrlMapping`, doing this instead:
```
else {
/**
* TBSEOWNT-12821 also encode static URL tokens
*/
try {
uri.append(SLASH).append(encode(token,encoding));
} catch (UnsupportedEncodingException e) {
throw new ControllerExecutionException("Error creating URL for parameters [" +
paramValues + "], problem encoding URL part [" + token + "]: " + e.getMessage(), e);
}
}
```

If there is any good reason for not encoding static URL tokens, the behavior should be configurable. Also the handling of static URL tokens and static parts of non static URL tokens should be the same.

Contributor guide

Open the contributing guide

Research direction

Start in org.grails.web.mapping.RegexUrlMapping.createURLInternal(Map paramValues, String encoding, boolean includeContextPath) around line 409, then reproduce the issue with the provided EncodingTestController and UrlMappings.groovy. Compare staticToken with semiStaticToken and verify that both generated links encode the static URL token consistently as /St%C3%A4ticToken.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.