func Start(cfg Config) *HTMLServer {
	flag.Parse()
	_, cancel := context.WithCancel(context.Background())
	defer cancel()
	r := mux.NewRouter()
	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		var user string
		identifyUser(&w, r, &user)
		w.Header().Set("Content-Type", "text/html")
		vars := map[string]interface{}{
			"Header": "Web Scraping Playground",
			"User":   user,
		}
		render(w, r, indexTpl, "base", vars)
	})
	r.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
		var user string
		identifyUser(&w, r, &user)
		w.Header().Set("Content-Type", "text/html")
		vars := map[string]interface{}{
			"User": user,
		}
		if user != "" {
			http.Redirect(w, r, "/", http.StatusFound)
			return
		}
		if r.Method == "POST" {
			username := strings.Trim(r.FormValue("username"), " ")
			if username != "" {
				registerUser(&w, r, username)
			}
			http.Redirect(w, r, "/", http.StatusFound)
			return
		}
		render(w, r, loginFormTpl, "base", vars)
	})
	r.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) {
		if cookie, err := r.Cookie("sessionId"); err == nil {
			cookie.MaxAge = -1
			http.SetCookie(w, cookie)
		}
		http.Redirect(w, r, "/", http.StatusFound)
	})
	r.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		w.Write([]byte(`<!DOCTYPE html><html><body><h1>Hello World</h1></body></html>`))
	})
	r.HandleFunc("/countries", countriesHandler)
	r.HandleFunc("/country/{country}", countryHandler)
	r.HandleFunc("/country/{country}/city/{city}", personsV2PagedHandler)
	r.HandleFunc("/country/{country}/city/{city}/page/{page}", personsV2PagedHandler)
	r.HandleFunc("/persons/page-{page}", personsHandler)
	r.HandleFunc("/persons/{id}", personDetailsHandler)
	r.HandleFunc("/persons-table", personTableHandler)
	r.HandleFunc("/robots.txt", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		w.Write([]byte(`User-agent: *
		Disallow: /`))
	})
	r.HandleFunc("/allowed", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(200)
		w.Write([]byte("allowed"))
	})
	r.HandleFunc("/disallowed", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(403)
		w.Write([]byte("disallowed"))
	})
	r.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "/redirected", http.StatusMovedPermanently)
	})
	r.HandleFunc("/redirected", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(200)
		w.Write([]byte("Redirected"))
	})
	r.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(200)
		w.Header().Set("Content-Type", "application/json")
		w.Write([]byte(`{"alive": true}`))
	})
	r.HandleFunc("/status/{status}", func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		st, err := strconv.Atoi(vars["status"])
		if err != nil {
			fmt.Println(err)
		}
		w.WriteHeader(st)
		w.Write([]byte(vars["status"]))
	})
	r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(*baseDir+"/static"))))
	htmlServer := HTMLServer{
		server: &http.Server{
			Addr:    cfg.Host,
			Handler: r,
			MaxHeaderBytes: 1 << 20,
		},
	}
	htmlServer.wg.Add(1)
	if !cfg.HTTPS {
		go func() {
			fmt.Printf("\nTest Server : Service started (HTTP): Host=%v\n", htmlServer.server.Addr)
			htmlServer.server.ListenAndServe()
			htmlServer.wg.Done()
		}()
	} else {
		go func() {
			fmt.Printf("\nTest Server : Service started (HTTPS) : Host=%v\n", htmlServer.server.Addr)
			htmlServer.server.ListenAndServeTLS(
				*certFile,
				*keyFile,
			)
			htmlServer.wg.Done()
		}()
		go http.ListenAndServe(":80", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			http.Redirect(w, r, "https://"+r.Host+r.URL.String(), http.StatusMovedPermanently)
		}))
	}
	return &htmlServer
}
Start launches the HTML Server
package main
import (
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"sync"
	"time"
	"github.com/alecthomas/template"
	"github.com/gorilla/mux"
)
const PERSONS_PER_PAGE = 6
var (
	personsTpl      *template.Template
	indexTpl        *template.Template
	personDetailTpl *template.Template
	personTableTpl  *template.Template
	loginFormTpl    *template.Template
	citiesTpl       *template.Template
	countriesTpl    *template.Template
	personsV2       *template.Template
	errorTpl        *template.Template
	personsJSON     string
	persons         []Person
	port            = flag.String("p", ":12345", "HTTP(S) listen address")
	https           = flag.Bool("s", false, "expect HTTPS connections")
	certFile        = flag.String("c", "", "certificate file path")
	keyFile         = flag.String("k", "", "private key file path")
	fetcherPort     = flag.String("f", ":8000", "DFK Fetcher port")
	baseDir         = flag.String("b", "./web", "HTML files location.")
	personCount     int
)
type Person struct {
	Name    string          `json:"Name"`
	Phone   json.RawMessage `json:"Phone"`
	Email   string          `json:"Email"`
	Company string          `json:"Company"`
	Counter string          `json:"Counter"`
	Bio     string          `json:"Bio"`
	Country string          `json:"Country"`
	City    string          `json:"City"`
}
func init() {
	flag.Parse()
	personsTpl = template.Must(template.New(*baseDir+"/base.html").Funcs(funcMap).ParseFiles(*baseDir+"/persons.html", *baseDir+"/base.html"))
	personTableTpl = template.Must(template.New(*baseDir+"/base.html").Funcs(funcMap).ParseFiles(*baseDir+"/persons-table.html", *baseDir+"/base.html"))
	indexTpl = template.Must(template.ParseFiles(*baseDir+"/index.html", *baseDir+"/base.html"))
	personDetailTpl = template.Must(template.New(*baseDir+"/base.html").Funcs(funcMap).ParseFiles(*baseDir+"/p_detail.html", *baseDir+"/base.html"))
	loginFormTpl = template.Must(template.ParseFiles(*baseDir+"/base.html", *baseDir+"/login_form.html"))
	citiesTpl = template.Must(template.ParseFiles(*baseDir+"/base.html", *baseDir+"/cities.html"))
	countriesTpl = template.Must(template.ParseFiles(*baseDir+"/base.html", *baseDir+"/countries.html"))
	personsV2 = template.Must(template.New(*baseDir+"/base.html").Funcs(funcMap).ParseFiles(*baseDir+"/base.html", *baseDir+"/persons_v2.html"))
	errorTpl = template.Must(template.ParseFiles(*baseDir+"/base.html", *baseDir+"/error.html"))
	dat, err := ioutil.ReadFile(*baseDir + "/data/persons.json")
	if err != nil {
		fmt.Println(err)
	}
	personsJSON = string(dat)
	if err := json.Unmarshal(dat, &persons); err != nil {
		panic(err)
	}
	personCount = len(persons)
}
type Config struct {
	Host     string
	HTTPS    bool  
	KeyFile  string
	CertFile string
}
type HTMLServer struct {
	server *http.Server
	wg     sync.WaitGroup
}