I have a site that have URL similar to this:
/mysite/admin/controller/action/id
/mysite/search/controller/action/id
/mysite/user/controller/action/id
I have my URL mapping like this
"/$prefix/$controller/$action?/$id?"{
constraints {}
}
I am able to get to the controller correctly.
But on the GSP side
<g:link controller="controller">abc</g:link> ==> abc
Notice how I lose the prefix between mysite and the controller.
You can use named url mappings and then pass the prefix as part of the params:
URLMappings:
name prefix: "/$prefix/$controller/$action?/$id?"{
constraints {}
}
GSP:
<g:link mapping="prefix" params="[prefix:$prefix, controller:...]">abc</g:link>
To use sortableColumn, just put all of the URLMapping parameters in the params property:
<g:sortableColumn property="col" title="title" params="[ prefix: 'prefix', controller:'controller', action:'action']" />
It works when you hit the URL in browser, because prefix is available in URL. It does not work when you use link tag to create url, because grails does not have information about which prefix should be used for this controller. You will need to provide the value for prefix to link tag.
Try this
<g:link controller="controller" params="[prefix:'admin']">abc</g:link>
in-short - You have to pass those dynamic variables as params if you want link re-writing to consider them. Read more docs here
Related
If I have a simple GSP (using Grails 2.3.6):
<% page import=org.me.Widget %>
<header>
<!-- Header stuff -->
</header>
<body>
The requested URL is ${url}!
</body>
How do I inspect the HTTP request URL (the current URL the server is responding to) and inject it into the ${url} variable?
Note: I need to do this inside of GSP and not from inside a controller, if at all humanly possible, even if it is a violation of best practices.
you could try
def var = request.forwardURI
forwardURI - Useful for obtaining the current request URI since the request object’s requestURI property returns the original URI, not the matched one.
You can even check for additional methods added to the request object here
You have quite a few options in a GSP to find out the current URL.
First, you can always access the request object which is an HttpServletRequest. Using methods such as getRequestURL() or getRequestURI(), you can inspect the request.
${request.getRequestURL()}
However, actionName and controllerName may be more useful. Both of these properties are exposed to the GSP within the model. With these you can construct the URL current using the standard createLink tag if needed.
${createLink(controller: controllerName, action: actionName)}
These should give you enough options to accomplish what you need.
According to the Grails documentation, the default URL mapping (between controller actions and URLs) uses camel case. You can easily change the URL mapping to use hyphenated URLs:
grails.web.url.converter = 'hyphenated'
So for instance, HelloWorldController.showUsers would map to:
/hello-world/show-users
In Grails, you can have a default controller action which by convention is "index". So for instance, if you have a method named index(), the following URL will hit that method:
/hello-world
You can create an anchor tag which links to that URL like this:
<g:link controller="HelloWorld">Go!</g:link>
I noticed a strange bug where if my controller name prefix is only one "word" such as HelloController, then:
<g:link controller="Hello">Go!</g:link>
... will always generate URLs which point to:
/hello/index
... instead of:
/hello
I refactored and renamed it to other single word controllers and the problem persisted. I was using Grails 2.2.2 so I upgraded to Grails 2.3.4 and was surprised this bug still existed. Renaming the controller to any two word prefix, like HomePageController, HelloWorldController, OneTwoController, etc, is a workaround for now.
This is my first time really using GSP. Am I doing something wrong?
URLs are part of the user experience and should be clean, so the index problem is really annoying.
It's inconvenient, but you can eliminate the index part of the URL for single word controllers by mapping each page and omitting the action.
grails-app/config/UrlMappings.groovy
class UrlMappings {
static mappings = {
"/hello" (controller: "hello")
"/settings" (controller: "settings")
"/dashboard" (controller: "dashboard")
...
According to Marc Palmer
Preventing XSS attacks
In a nutshell, to protect your app from code injection XSS exploits
you must:
Set the default grails.views.default.codec in config to "HTML"
OK.
So if I have this below in my Config.groovy
grails.views.default.codec = "none"
And in my Controller, I add:
def afterInterceptor = { model ->
model.headerJs = "alert('bingo for '+[$params.unitId]);"
}
And in my GSP:
<r:script disposition="head">${headerJs}</r:script>
It works. I see the expected javascript alert when I do View Source and I get my alert when the page serves.
But, if in Config.groovy I apply the recommended change:
grails.views.default.codec = "html"
My GSP renders
<script type="text/javascript">alert('halooba for '+[1]);</script>
which I can see is very secure.
My goal with this app is to have custom JS snippets, various properties and other values stored for the customer in the Domain. These values would be entered by our Admins (not the customer). Based on who invokes the page with an HTTP request, such as www.mydomain.com/ThisApp/?customerId=13423 (but an encoded customerId) I'd make calls to Services from my Controller to fetch the associated settings for the customer from the Domain and inject them into the GSP.
I know that I can put JS and CSS into files and then use the Resources Plugin to bring them in properly, but I'm also looking at this method for specific customizations.
So, to follow this security method, I either need to be able to unencode this, or I need to determine another method for including javascript into the GSP that does not encode it.
Any suggestions?
THANKS!
You can suggest Grails not to escape by using raw() available in GSP as:
<r:script disposition="head">${raw(headerJs)}</r:script>
For Grails 2.2.x and below, you can put the recommended encoding in your Config.groovy:
grails.views.default.codec = "html"
and use a Taglib to bring in values that are SAFE and should not be HTML encoded:
<r:script><com_myapp:getJSDeferred unitId="${params.unitId}" /></r:script>
and it will be rendered raw.
FYI: Above solution will not allow for JSON output to assign to javascript variable.
My workaround, say you have model.data defined as hashmap:
var someVar= ${raw(data as JSON).toString())};
I can call the closure of a controller in a gsp view using the following link:
<g:link url="${request.contextPath}/data/${params.name}/myController/myClosure">
Text Goes Here
</g:link>
However I would like to use remoteLink because I don't want to render anything, just perform a task. Am I correct to want to use remoteLink?
Unfortunately remoteLink does not have a url attribute. So I use controller and action:
<g:remoteLink controller="myController" action="myClosure">
Text Goes Here
</g:remoteLink>
Which unsuccessfully uses the url "/myApp/MyController/MyClosure", which is different from the url that works.
So my questions are,
How did my controller get that longer url? It does not appear in my URLMappings. What controls this?
Is there anyway I can use remoteLink to access that url?
Thank you!
The URL mapping must be named:
static mappings = {
name <mapping name>: <url pattern> {
// …
}
}
Then you can do:
<g:remoteLink mapping="<mapping name>" controller="myController" action="myClosure">
Text Goes Here
</g:remoteLink>
In my application, a login controller should return redirect URL if client is authorized:
<path to grails app> + <another controller, method, params>
How can I get application URL?
You should be able to build a URL using the grails tags as method calls. createLink is likely what you want. This has action, controller, params and absolute as options to get a full URL to a controller action (you may need to configure the base url as noted in the docs). In an example in the first link, something like this would get the absolute URL to that resource:
g.createLink(action:"myact", controller:"somecontroller", params:[foo:'bar', boo:'far'], absolute:true)
For generic approach you can inject LinkGenerator and then call
linkGenerator.link(controller: "foo", action: "bar", absolute: true)
For some reason, tag use completely different logic.