Tuesday, June 22, 2010

Grails multiple web sites, same web application

We had a need recently to have one web application serving many web sites, where the same data schema was in place with data shared across multiple web sites, but we wanted to show different styling and different data depending on the URI. In the end it turned out to be fairly simple. With our naming conventions, it's possible to hit one of several URIs for the same site, such as:

* project.testing.com
* project.staging.com
* project.com

So I had created a domain lookup service that when passed the request URI could work out what site the request for targeting.


def targetUri = request.getServerName()


I did a lookup for that target name against an object stored in the database relating to that targetUri and passed that back, making it available for queries for the correct data to show, and passing that down into the views to render the relevant CSS and Javascript files.

2 comments:

El Santo said...

Hi, you can use a Filter and Wapper for request.




import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.net.URL;
import java.util.*;

/**
* User: Pablo Moretti
* Date: 08/06/2010
* Time: 23:16:28
* To change this template use File | Settings | File Templates.
*/
public class MyFirstFilter implements javax.servlet.Filter {



public void init(FilterConfig filterConfig) throws ServletException {
}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

String url = ((HttpServletRequest) servletRequest).getRequestURL().toString().replace(":8080","");

URLWrappedRequest request = new URLWrappedRequest((HttpServletRequest) servletRequest);
request.addParameter("country","AR");

request.setRequestURI("/untitled/test/index");

filterChain.doFilter(servletRequest,servletResponse);
}

public void destroy() {
}

}


class URLWrappedRequest extends HttpServletRequestWrapper
{
private final Map modifiableParameters;
private String requestURI;

/**
* Create a new request wrapper that will merge additional parameters into
* the request object without prematurely reading parameters from the
* original request.
*
* @param request
*/
public URLWrappedRequest(final HttpServletRequest request)
{
super(request);
modifiableParameters = new TreeMap();
}

public void addParameter(String name,String value){
String[] values = { value };
modifiableParameters.put(name,values);
}

@Override
public String getParameter(final String name)
{
String[] strings = getParameterMap().get(name);
if (strings != null)
{
return strings[0];
}
return null;
}

@Override
public Map getParameterMap()
{
Map allParameters = new HashMap();
allParameters.putAll(super.getParameterMap());
allParameters.putAll(modifiableParameters);
//Return an unmodifiable collection because we need to uphold the interface contract.
return Collections.unmodifiableMap(allParameters);
}

@Override
public Enumeration getParameterNames()
{
return Collections.enumeration(getParameterMap().keySet());
}

@Override
public String[] getParameterValues(final String name)
{
return getParameterMap().get(name);
}

@
public void setRequestURI(String requestURI){
this.requestURI = requestURI;
}

@Override
public String getRequestURI(){
return requestURI;
}

}

Robbie said...

Hi Santo,

Where would I use something like that?