// mainHandler responds to an HTTP request. func mainHandler(w http.ResponseWriter, req *http.Request) { log.SetPrefix(fmt.Sprintf("[%s %s] ", req.Method, req.URL)) if req.Method != "GET" { fail(w, "invalid request method") return } ifModSince := req.Header.Get("If-Modified-Since") cacheTime, err := time.Parse(http.TimeFormat, ifModSince) if err == nil && modifiedTime.Unix() <= cacheTime.Unix() { w.WriteHeader(http.StatusNotModified) return } w.Header().Set("Last-Modified", modifiedTime.Format(http.TimeFormat)) params := parseParams(req.URL) log.Printf("Rendering %+v\n", params) svg, err := renderSVG(params) if err != nil { fail(w, err.Error()) return } if params.onlySVG { w.Header().Set("Content-Type", "image/svg+xml") io.WriteString(w, svg) } else { depth, _ := strconv.Atoi(params.depth) max := system.Named(params.name).MaxDepth() query := "?" + req.URL.RawQuery if query == "?" { query = "" } page := pageData{ Name: params.name, Thickness: params.thickness, Color: params.color, Query: query, Depth: depth, MaxDepth: max, StepFactor: system.StepFactor, PadFactor: system.PadFactor, SVG: template.HTML(svg), Systems: systemNames, } display(w, "index", page) } }
// renderSVG generates the SVG data for the specified curve. func renderSVG(params parameters) (string, error) { sys := system.Named(params.name) if sys == nil { return "", fmt.Errorf("no system named %q", params.name) } depth, err := strconv.Atoi(params.depth) if err != nil { return "", err } if depth < minimumDepth || depth > sys.MaxDepth() { return "", fmt.Errorf("invalid depth %d", depth) } thickness, err := strconv.ParseFloat(params.thickness, 64) if err != nil { return "", err } if thickness <= 0 { return "", fmt.Errorf("invalid thickness %f", thickness) } if params.color == "" { return "", fmt.Errorf("invalid color \"\"") } precision, err := strconv.Atoi(params.precision) if err != nil { return "", err } if precision < minimumPrecision || precision > maximumPrecision { return "", fmt.Errorf("invalid precision %d", precision) } opts := system.Options{ Depth: depth, Thickness: thickness, Color: params.color, Precision: precision, } return sys.SVG(&opts), nil }