func MakeStaticFunc() LabHandler {
	return func(w http.ResponseWriter, r *http.Request) *LabResp {
		err := DoTemplate(w, r.URL.Path, &InData{})
		if err != nil {
			log.Printf("Error in MakeStaticFunc, DoTemplate returned Err: %s\n", err)
			return &LabResp{Err: err, Code: http.StatusInternalServerError}
		}
		return &LabResp{Err: nil, Code: http.StatusOK}
	}
}
MakeStaticFunc creates a "static function" processing a template
with empty data input.
package webseclab
import (
	"errors"
	"fmt"
	"html/template"
	"io"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
)
type LabResp struct {
	Err      error
	Code     int
	Redirect string
	Path     string
	Fixed    bool
	InData
}
func (r *LabResp) String() string {
	return "Error: " + r.Err.Error() + ", code: " + strconv.Itoa(r.Code) + ", redirect: " + r.Redirect
}
type LabHandler func(http.ResponseWriter, *http.Request) *LabResp
func (fn LabHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	resp := fn(w, r)
	if resp.Code == http.StatusFound {
		http.Redirect(w, r, resp.Redirect, http.StatusFound)
		return
	}
	if resp.Err != nil && resp.Code != 0 {
		w.WriteHeader(resp.Code)
		w.Header().Set("Content-type", "text/html; charset=utf-8")
		log.Printf("ERROR in LabHandler, errorText: %s\n", resp.Err.Error())
		tmpl, err := template.New("Error").Parse("ERROR: {{.}}\n")
		if err != nil {
			panic(err)
		}
		err = tmpl.Execute(w, resp.Err.Error())
		return
	}
}
func MakeMainHandler(noindex bool) LabHandler {
	return func(w http.ResponseWriter, r *http.Request) *LabResp {
		indexFn := MakeIndexFunc("index.html")
		if r.URL.Path == "/" || r.URL.Path == "/index.html" {
			if noindex {
				return &LabResp{
					Err:  errors.New("index page is prevented with -noindex option"),
					Code: http.StatusForbidden,
				}
			}
			indexFn(w, r)
			return &LabResp{Err: nil, Code: http.StatusOK}
		}
		safe := IsSafeHost(r.Host)
		if !safe {
			ipurl, err := GetIPURL(r.Host, r.URL)
			if err != nil {
				return &LabResp{Err: errors.New("ERROR in GetIPUrl(" + r.URL.String() + "): " + err.Error()),
					Code: http.StatusInternalServerError}
			}
			return &LabResp{Err: errors.New(r.Host + " - not an IP quad pair"),
				Code:     http.StatusFound,
				Redirect: ipurl.String()}
		}
		funcmap := CustomMap()
		handler, ok := funcmap[r.URL.Path]
		if ok {
			return handler(w, r)
		}
		filterMap := filterMap()
		filters, ok := filterMap[r.URL.Path]
		if ok {
			return HandleFilterBased(w, r, filters)
		}
		return DoLabTestStandard(w, r)
	}
}
func Ruok(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "text/plain; charset=utf-8")
	fmt.Fprintf(w, "imok\n")
}
func MakeExitFunc(ln net.Listener) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		parts := strings.Split(r.RemoteAddr, ":")
		if len(parts) > 0 {
			if parts[0] != "127.0.0.1" && parts[0] != "localhost" {
				w.WriteHeader(http.StatusForbidden)
				io.WriteString(w, "Access denied. (/exit called from non-local IP: "+parts[0]+")\n")
				return
			}
		}
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		io.WriteString(w, `bye`)
		log.Println("Received exit request, exiting")
		ln.Close()
	}
}
func MakeIndexFunc(page string) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		var data = &InData{}
		if !IsIP(r.Host) {
			iplink, err := GetIPURL(r.Host, r.URL)
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				w.Write([]byte(`Internal Server Error`))
				log.Printf("ERROR - unable to find out my own IP address: r.Host = %s, r.URL = %s\n", r.Host, r.URL.String())
				return
			}
			data.In = iplink.Host
		}
		err := DoTemplate(w, "/index.html", data)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte(`Internal Server Error`))
			return
		}
	}
}