3

Let's say my website is http://soccer.com and I want to support an unlimited amount of subdomains, eg.:

  • http://cronaldo.soccer.com
  • http://messi.soccer.com
  • http://neymar.soccer.com
  • http://muller.soccer.com
  • ...

I also want to have a few reserved sub-domains, eg.:

  • http://admin.soccer.com
  • http://help.soccer.com
  • ...

While the player's subdomains will be handled by the same logic, the reserved ones won't. So I'll need 2 routes or 2 routers?

Here's what I have:

package main

import (
    "fmt"
    "net/http"
    "log"
    "html/template"
    "strings"
)

type Mux struct {
    http.Handler
}

func (mux Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    domainParts := strings.Split(r.Host, ".")
    fmt.Println("Here: " + domainParts[0])
    if domainParts[0] == "admin" {
        // assign route?
        mux.ServeHTTP(w, r)
    } else if domainParts[0] == "help" {
        // assign route?
        mux.ServeHTTP(w, r)
    } else if isSubDomainValid(domainParts[0]) {
        // assign route for player page?
        mux.ServeHTTP(w, r)
    } else {
        // Handle 404
        http.Error(w, "Not found", 404)
    }
}

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", HomeHandler)

  http.ListenAndServe(":8080", mux)
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
  t, err := template.ParseFiles("index.html")
  if err != nil {
    log.Print("template parsing error: ", err)
  }

  err = t.Execute(w, nil)
  if err != nil {
    log.Print("template executing error: ", err)
  }

}

But I don't think I'm doing this right.

fmt.Println("Here: " + domainParts[0]) never shows up, leading me to believe that ServeHTTP() is never called.

I'm just a beginner in Go, so I might be missing some concept

Thank you

Cornwell
  • 3,304
  • 7
  • 51
  • 84
  • 3
    You haven't defined `handler` and you're not using your `Mux` type at all in this example. – JimB Jun 20 '18 at 16:20
  • You are on the right track. Define http.Handler for each kind of domain and call those handlers from the if / else statement in Mux.ServeHTTP. Also, use a Mux as the root handler. It's not used at all now. – Charlie Tumahai Jun 20 '18 at 16:23
  • @JimB I've added the handler now. It just outputs an html file for now. @ThunderCat do you mean something like this: `mux.HandleFunc("/", AdminHandler)` for the "admin" domain for instance? But I don't think it's even calling `ServeHTTP ` Regarding mux not being used in the root, isn't it handling the main domain's index request? – Cornwell Jun 20 '18 at 16:31
  • @Cornwell: you still never use `Mux` in your code, so it's unclear why you think it should produce any output if it's never used. – JimB Jun 20 '18 at 16:35

1 Answers1

4

You are on the right track. Create a http.ServeMux for each kind of domain and call those muxes from the if / else statement in Mux.ServeHTTP. Also, use a Mux as the root handler.

type Mux struct {
    help, admin, sub, main *http.ServeMux
}

func (mux *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if isMainDomain(r.Host) {
        mux.main.ServeHTTP(w, r)
        return
    }
    domainParts := strings.Split(r.Host, ".")
    if domainParts[0] == "admin" {
        mux.admin.ServeHTTP(w, r)
    } else if domainParts[0] == "help" {
        mux.help.ServeHTTP(w, r)
    } else if isSubDomainValid(domainParts[0]) {
        mux.sub.ServeHTTP(w, r)
    } else {
        http.Error(w, "Not found", 404)
    }
}

func main() {
    mux := &Mux{
        help:  http.NewServeMux(),
        admin: http.NewServeMux(),
        sub:   http.NewServeMux(),
        main:  http.NewServeMux(),
    }

    mux.help.HandleFunc("/", helpHomeHandler)
    mux.admin.HandleFunc("/", adminHomeHandler)
    mux.sub.HandleFunc("/", defaultSubdomainHomeHandler)
    mux.main.HandleFunc("/", mainHomeHandler)

    http.ListenAndServe(":8080", mux) // <-- use Mux value as root handler
}
Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242
  • Thanks! I was messing up the `mux`. Quick question, how do I handle the main domain's routes? ie. requests to `soccer.com` (without any subdomain). Where do I add the handler? – Cornwell Jun 20 '18 at 18:09
  • 1
    Use another http.ServeMux and hook into if / else statement using whatever logic you need for separating domain from sub-domain. – Charlie Tumahai Jun 20 '18 at 18:17