A simple WWW Redirector without Apache or nginx

Jonathan Guthrie
Server Side Swift and More
3 min readMar 18, 2017

I ran into a perculiar problem a few weeks ago, a problem to which I could react one of several ways…

  • Go back to “traditional technologies”; or
  • Ignore it; or
  • Solve it*

Going back to using the “traditional” route hurts my pride, I’ll have to be honest. I *like* not having to use Apache or nginx. I knew I would eventually have to address the issue, but I initially chose the easy route, and pretend the issue didn’t exist.

The problem

BIND and DNS are wonderful things. They keep the ‘net a sensible place, as far as something that is still the Wild West can be. But when you have an AWS load balancer for a web system it gives you a host name to add as a CNAME, and you can’t point an A record at it because it’s a multi-zone thing with multiple IP addresses.

And setting the base host address as a CNAME is not something BIND likes to do. You can CNAME “www.”, but not the base hostname itself.

Now, AWS load balancers are great in that you don’t need to do a lot of config, and using it means that even your load balancer has high availability — but it does leave out some of the more complex functionality that load balancers like HAProxy give you. In fact if I were running HAProxy, or running any single IP load balancer, all these issues go away because you can point a base domain A record at it.

Ignoring it: Yeah, only valid for development or if you have a tolerant audience.

Solving it

Lets not make mountains out of mole-hills, the issue really isn’t hard to solve, but worth documenting so someone can build off it, and I expect I’ll get flack for putting myself in this situation to start with.

Goal: Create a simple, lightweight service on port 80 that will redirect any non-www host to a www host.

TLDR; Git repo: https://github.com/PerfectExamples/WWW-Redirector

First step: Start a new project using the Perfect Template in Perfect Assistant.

It’s got one file, and is really simple. It does one job, but even this is too complex for our needs :)

Kick the config which is more complex than this wants… replace it with:

let confData = [
"servers": [
[
"name":"localhost","port":80,
"routes":[
["method":"get", "uri":"/**", "handler":redirectHandler]
]
]
]
]

Then remove the generic demo handler with this:

func redirectHandler(data: [String:Any]) throws -> RequestHandler {
return {
request, response in
response.status = .movedPermanently
response.setHeader(
.location,
value: "www." + request.header(.custom(name: "host"))! + request.uri)
response.completed()
}
}

I was about to deploy, but realized that it’s got two flaws: what if there’s no host header, or if someone screwed up and pointed a www.example.com at this — it would redirect to www.www.example.com. No thanks.

So I added SwiftString (https://github.com/iamjono/SwiftString.git) to make things a little smoother, and changed the function to handle these two cases:

func redirectHandler(data: [String:Any]) throws -> RequestHandler {
return {
request, response in
let host = request.header(.custom(name: "host")) ?? ""
if host.startsWith("www.") {
response.setBody(string: "<html><head></head><body>ERROR: This is already a www host, cannot redirect further. Please check your DNS.</body></html>")
response.completed()
} else if host.isEmpty {
response.setBody(string: "<html><head></head><body>ERROR: No host header supplied.</body></html>")
response.completed()
}
response.status = .movedPermanently
response.setHeader(.location, value: "www." + host + request.uri)
response.completed()
}
}

So the above code will now not do a redirect in these two situations, instead will feed back the correct error to the user.

A few clicks later in the Perfect Assistant and it was deployed to a single “spare” node on AWS and once the DNS was changed to point at it, problem solved.

Follow-ups

  1. Yes, it’s technically a workaround.
  2. If you want to add HTTPS, it’s pretty simple to do so and get it responding on port 443. I’ll be doing a tutorial on that soon.
  3. Shortly after publishing this I ran across this on Hacker Newshttps://www.netlify.com/blog/2017/02/28/to-www-or-not-www/

--

--

Jonathan Guthrie
Server Side Swift and More

Developer Evangelist, Musician, and Active Activist... Newmarket ON, Canada