Status

Proposal needs feedback

Target Release

4.1

Original Authors

Dave Johnson and Sean Gilligan

Abstract

This is a proposal to enable subdomain and/or multi-domain support in Roller. It is based on Dave's work in Proposal Simple Multidomain Support but provides for explicit support for subdomains and stores custom URLs for weblogs in the weblog table rather than in roller-custom.properties.

Requirements

  • Allow Roller to use blog handles as subomains (e.g. http://handle.baseurl.com)
  • Allow one Roller instance to specify different URLs for different weblogs, stored in the database
  • Ensure that each weblog is only accessed by one root URL

Issues

  • Is this design flexible enough to meet most of the requests we've seen so far?
  • How to avoid a repeat of "handle" in the pathInfo of the URL (e.g. http://handle.baseurl.com/handle)
  • Requires adding URL column to weblog table
  • How much refactoring is required to achieve DRY in the URL resolution code?

Design

Changes to Weblog POJO

Weblog.getAbsoluteURL() uses URLStrategy to return URLs

    public String getAbsoluteURL() {
    	URLStrategy urlStrategy = WebloggerFactory.getWeblogger().getUrlStrategy();
    	return urlStrategy.getWeblogURL(this, null, true);
    }

Weblog.getURL() calls Weblog.getAbsoluteURL()

If we are going to use subdomain URLs, we'll need to always (question) use absolute URLs when referring to Weblogs (at the very least we need to change some assumptions)

    public String getURL() {
         return getAbsoluteURL();
     }

Changes to URLModel

URLModel.getAbsoluteSite() uses URLStrategy

    /** Absolute URL of Roller, e.g. http://localhost:8080/roller */
    public String getAbsoluteSite() {
  //      return WebloggerRuntimeConfig.getAbsoluteContextURL();
    	URLStrategy urlStrategy = WebloggerFactory.getWeblogger().getUrlStrategy();
    	return urlStrategy.getWeblogURL(weblog, null, true);
   }

Changes to WeblogRequestMapper

WeblogRequestMapper assumes the weblog handle is at the beginning of the pathInfo string in the request. We'll either need to subclass WeblogRequestMapper or inject (or lookup (sad)) a strategy object that can do this. A strategy object would be better than a subclass. Do we create a new strategy object for decoding a URL or do we add methods to the existing URLStrategy objects?

New SubdomainURLStrategy object

Note: For now this still uses properties to override the default subdomain URL. In "phase II" we'll look at moving this property into the Weblog object/table itself.

package org.apache.roller.weblogger.business;

import org.apache.roller.weblogger.business.MultiWeblogURLStrategy;
import org.apache.roller.weblogger.config.WebloggerConfig;
import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
import org.apache.roller.weblogger.pojos.Weblog;

/** Multi-domain URL strategy. */
public class SubdomainURLStrategy extends MultiWeblogURLStrategy {

    /** Get root url for a given weblog.  Optionally for a certain locale. */
    public String getWeblogURL(Weblog weblog, String locale, boolean absolute) {        
        if(weblog == null) return null;
        
        StringBuffer url = new StringBuffer();        
        if(absolute) {
            String weblogAbsoluteURL = 
                WebloggerConfig.getProperty("weblog.absoluteurl." + weblog.getHandle());            
            if (weblogAbsoluteURL != null) {
                url.append(weblogAbsoluteURL);
            } else {
            	String subDomainURL = replaceSubdomain(WebloggerRuntimeConfig.getAbsoluteContextURL(), weblog.getHandle());
                url.append(subDomainURL);
            }
        } else {
            url.append(WebloggerRuntimeConfig.getRelativeContextURL());
        }
        
        // TODO: Remove this, the handle shouldn't be in the hostname and in the path
        url.append("/").append(weblog.getHandle()).append("/");
        
        if(locale != null) {
            url.append(locale).append("/");
        }
        
        return url.toString();
    }
    
    private String replaceSubdomain(String url, String newSub) {
    	String			baseURL;							// Base URL for subdomains
    	StringBuffer	newURL = new StringBuffer(newSub);	// URL for this subdomain
    	
    	// For backward compatibility we leave site.absoluteurl property as the full URL of
    	// the main blog, e.g. roller.domain.com, so we'll have to remove the subdomain and re-add it
    	int firstDot = url.indexOf('.');
    	if ((firstDot == -1) || (firstDot + 2 > url.length())) {
    		// URL without a dot (!?) or dot  is last character - Use the full URL
    		// Maybe we should throw an exception here?
        	baseURL = url;  		
    	}
    	else {
    		// Take everthing after the first dot
        	baseURL = url.substring(firstDot + 1);  		   		
    	}
    	newURL.append(newSub).append('.').append(baseURL);
    	
    	return newURL.toString();
    }
}

Configuration

Server Administrator

Roller deployment is configured by the server administrator with the following settings:

Blog Administrator

Blog administrator can enable a custom domain on a per-webblog basis (if enabled by the server admin)

  • Requires an additional setting on the Weblog Settings UI screen (hidden when disabled)
  • Custom domains on Weblogs might require the subdomain URL strategy (question)

Comments

Please comment on the Roller dev mailing list.

  • No labels