-
-
Notifications
You must be signed in to change notification settings - Fork 966
Description
RestfulController has bad logic for json requests
Performing a application/json save or update request with multipartForm data results in a text/html response.
For modern REST usage it’s a leaky abstraction—mixing input and output negotiation leads to surprising 302s.
Either the redirect logic should change for json requests or the default response type binding should change.
grails-core/grails-rest-transforms/src/main/groovy/grails/rest/RestfulController.groovy
Lines 112 to 122 in 0de145d
| request.withFormat { | |
| form(multipartForm { | |
| flash.message = message(code: 'default.created.message', args: [classMessageArg, instance.id]) | |
| redirect instance | |
| }) | |
| '*' { | |
| response.addHeader(HttpHeaders.LOCATION, | |
| grailsLinkGenerator.link(resource: this.controllerName, action: 'show', id: instance.id, absolute: true, | |
| namespace: hasProperty('namespace') ? this.namespace : null)) | |
| respond(instance, [status: CREATED, view: 'show']) | |
| } |
With that logic:
curl -i -L -X POST 'http://localhost:8081/user/save' \
-H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
-H 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148' \
-H 'Accept: application/json' \
--data 'name=Sample'
results in
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>
Show User
</title>
</head>
<body>
....even a subsequent get request returns text/html
curl -i 'http://localhost:8081/user/shoe/1' \
-H 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148' \
-H 'Accept: application/json'
instead of what is expected
{"id":6,"name":"Sample"}This is due to
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 which is Safari web browser.
A decision needs to be made:
Should json save/update events result in redirects when json is requested?
A default grails app has the following yml
grails:
mime:
disable:
accept:
header:
userAgents:
- Gecko
- WebKit
- Presto
- TridentSupposedly that configuration is there because Grails was configured to disable Accept header processing for certain user agents (Gecko, WebKit, Presto, Trident) - a legacy workaround for old browser quirks that's no longer needed and was breaking API clients.
But removing WebKit has no impact on results. That is because that is the default behavior which can be overridden like this:
grails:
mime:
disable:
accept:
header:
userAgents: []These defaults were introduced 11 years ago. Is this still necessary in 2025?
grails-core/grails-mimetypes/src/main/groovy/org/grails/web/mime/HttpServletResponseExtension.groovy
Lines 72 to 76 in 0de145d
| private static void useDefaultConfig() { | |
| disableForUserAgents = ~/(Gecko(?i)|WebKit(?i)|Presto(?i)|Trident(?i))/ | |
| useAcceptHeaderXhr = true | |
| useAcceptHeader = true | |
| } |
If so, RestfulController logic should be rewritten to stop the redirect on save. Forcing .json format at the end of the url does not work because it is lost in the redirect.
Version
7.0.0
Metadata
Metadata
Assignees
Labels
Type
Projects
Status