diff --git a/cmd/xprint/main.go b/cmd/xprint/main.go index 0a6d58c..0662675 100644 --- a/cmd/xprint/main.go +++ b/cmd/xprint/main.go @@ -5,16 +5,10 @@ package main import ( "bytes" - "encoding/base64" "encoding/json" "flag" "fmt" - "io" "io/ioutil" - "net" - "net/http" - "net/http/httputil" - "net/url" "os" "sort" "strconv" @@ -37,15 +31,15 @@ var ( s string isFile bool } - unsafe *bool = flag.Bool("u", unsafeMode(), fmt.Sprintf("allow evaluation of dangerous template functions (%v)", unsafeFuncs())) // - showFns *bool = flag.Bool("F", false, "print available template functions and exit") // - debug *bool = flag.Bool("D", false, "debug init and template rendering activities") // - startDebuggingOnce sync.Once // - output *os.File // - argsfirst *bool = flag.Bool("a", false, "output arguments (if any) before stdin (if any), instead of the opposite") // - showVersion *bool = flag.Bool("v", false, "print build version/date and exit") // - server *string = flag.String("s", "", "start a render server on given address") // - semver, commit, built = "v0.0.0-dev", "local", "a while ago" // + unsafe *bool = flag.Bool("u", unsafeMode(), fmt.Sprintf("allow evaluation of dangerous template functions (%v)", unsafeFuncs())) // + showFns *bool = flag.Bool("F", false, "print available template functions and exit") // + debug *bool = flag.Bool("D", false, "debug init and template rendering activities") // + startDebuggingOnce sync.Once // + output *os.File // + argsfirst *bool = flag.Bool("a", false, "output arguments (if any) before stdin (if any), instead of the opposite") // + showVersion *bool = flag.Bool("v", false, "print build version/date and exit") // + //server *string = flag.String("s", "", "start a render server on given address") // + semver, commit, built = "v0.0.0-dev", "local", "a while ago" // ) func unsafeFuncs() []string { @@ -202,34 +196,37 @@ func init() { } func main() { - if *server != "" { - if output == nil { - output = os.Stderr - } - var err error - l, err = log.New(log.Formats[log.StdFormat].String(), log.Formats[log.DefTimeFmt].String(), loglvl, *logcolor, *name, output) - if err != nil { - panic(err) - } - u, err := url.Parse(*server) - if err != nil { - panic(err) - } - proto := strings.Split(u.Scheme, ":")[0] - var addr string - if proto != "unix" { - addr = net.JoinHostPort(u.Hostname(), u.Port()) - } else { - addr = u.Hostname() - } - lis, err := net.Listen(proto, addr) - if err != nil { - panic(err) + /* + if *server != "" { + if output == nil { + output = os.Stderr + } + var err error + l, err = log.New(log.Formats[log.StdFormat].String(), log.Formats[log.DefTimeFmt].String(), loglvl, *logcolor, *name, output) + if err != nil { + panic(err) + } + u, err := url.Parse(*server) + if err != nil { + panic(err) + } + proto := strings.Split(u.Scheme, ":")[0] + var addr string + if proto != "unix" { + addr = net.JoinHostPort(u.Hostname(), u.Port()) + } else { + addr = u.Hostname() + } + lis, err := net.Listen(proto, addr) + if err != nil { + panic(err) + } + l.Noticef("set up %s listener on %s", proto, lis.Addr().String()) + http.HandleFunc("/render", renderServer) + http.HandleFunc("/", uiPage) + panic(http.Serve(lis, nil).Error()) } - l.Noticef("set up %s listener on %s", proto, lis.Addr().String()) - http.HandleFunc("/render", renderServer) - panic(http.Serve(lis, nil).Error()) - } + */ buf := new(bytes.Buffer) if len(_templates) > 0 { if *debug { @@ -284,93 +281,3 @@ func main() { l.Debugf("%s", buf.String()) } } - -type jresp struct { - Status int `json:"status"` - Results interface{} `json:"results,omitempty"` - Error error `json:"error,omitempty"` -} - -func renderServer(w http.ResponseWriter, r *http.Request) { - l.Noticef("new request ( %s %s ) from %s", r.Method, r.URL, r.RemoteAddr) - if *debug { - b, _ := httputil.DumpRequest(r, true) - l.Debugf("request ( %s %s ) from %s: %s", r.Method, r.URL, r.RemoteAddr, string(b)) - } - if r.Method != http.MethodPost { - l.Errorf("rejected request ( %s %s ) from %s: bad method", r.Method, r.URL, r.RemoteAddr) - w.WriteHeader(http.StatusMethodNotAllowed) - return - } - var postTemplates map[string]string - if err := json.NewDecoder(r.Body).Decode(&postTemplates); err != nil { - l.Errorf("error processing request ( %s %s ) from %s: invalid body: %s", r.Method, r.URL, r.RemoteAddr, err) - w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(jresp{ - Status: http.StatusBadRequest, - Error: fmt.Errorf( - `must submit a map[key]value JSON object where key is a string identifier for the template and value is the base64-encoded template itself. a special map["data"] field (also base64 encoded) may be provided, it will not be considered a template but as a data object to apply to the templates in template.Execute`, - ), - }) - return - } - var postedData interface{} - if v, ok := postTemplates["data"]; ok { - b, err := base64.StdEncoding.DecodeString(v) - if err != nil { - l.Warningf("error decoding map[data] from request ( %s %s ) from %s: b64dec: %s", r.Method, r.URL, r.RemoteAddr, err) - w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(jresp{ - Status: http.StatusBadRequest, - Error: err, - }) - return - } - postedData = string(b) - delete(postTemplates, "data") - } - if len(postTemplates) < 1 { - l.Infof("request ( %s %s ) from %s: no content", r.Method, r.URL, r.RemoteAddr) - w.WriteHeader(http.StatusNoContent) - return - } - tpl := template.New("").Funcs(buildFuncMap(*unsafe)) - for n, t := range postTemplates { - b, err := base64.RawStdEncoding.DecodeString(t) - if err != nil { - l.Warningf("error decoding templates from request ( %s %s ) from %s: b64dec: %s", r.Method, r.URL, r.RemoteAddr, err) - w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(jresp{ - Status: http.StatusBadRequest, - Error: err, - }) - return - } - tpl, err = tpl.New(n).Parse(string(b)) - if err != nil { - l.Warningf("error processing request ( %s %s ) from %s: tpl.New: %s", r.Method, r.URL, r.RemoteAddr, err) - w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(jresp{ - Status: http.StatusBadRequest, - Error: err, - }) - return - } - } - buf := new(bytes.Buffer) - if err := tpl.Execute(buf, postedData); err != nil { - l.Warningf("error processing request ( %s %s ) from %s: tpl.Execute: %s", r.Method, r.URL, r.RemoteAddr, err) - w.WriteHeader(http.StatusInternalServerError) - json.NewEncoder(w).Encode(jresp{ - Status: http.StatusInternalServerError, - Error: err, - }) - return - } - w.WriteHeader(http.StatusOK) - _, err := io.Copy(w, buf) - if err != nil { - l.Warningf("error sending response to request ( %s %s ) from %s: %s", r.Method, r.URL, r.RemoteAddr, err) - } - l.Infof("processed request ( %s %s ) from %s", r.Method, r.URL, r.RemoteAddr) -} diff --git a/cmd/xprint/server.go b/cmd/xprint/server.go new file mode 100644 index 0000000..28c5877 --- /dev/null +++ b/cmd/xprint/server.go @@ -0,0 +1,152 @@ +package main + +/* +import ( + "bytes" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httputil" + "text/template" +) + +type jresp struct { + Status int `json:"status"` + Results interface{} `json:"results,omitempty"` + Error error `json:"error,omitempty"` +} + +func renderServer(w http.ResponseWriter, r *http.Request) { + l.Noticef("new request ( %s %s ) from %s", r.Method, r.URL, r.RemoteAddr) + if *debug { + b, _ := httputil.DumpRequest(r, true) + l.Debugf("request ( %s %s ) from %s: %s", r.Method, r.URL, r.RemoteAddr, string(b)) + } + if r.Method != http.MethodPost { + l.Errorf("rejected request ( %s %s ) from %s: bad method", r.Method, r.URL, r.RemoteAddr) + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + if err := r.ParseMultipartForm(32 << 20); err != nil { + l.Errorf("error processing request ( %s %s ) from %s: invalid form data: %s", r.Method, r.URL, r.RemoteAddr, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + j, _ := json.MarshalIndent(r.Form, "", " ") + fmt.Println(string(j)) + var postTemplates map[string]string + if err := json.NewDecoder(r.Body).Decode(&postTemplates); err != nil { + l.Errorf("error processing request ( %s %s ) from %s: invalid body: %s", r.Method, r.URL, r.RemoteAddr, err) + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(jresp{ + Status: http.StatusBadRequest, + Error: fmt.Errorf( + `must submit a map[key]value JSON object where key is a string identifier for the template and value is the base64-encoded template itself. a special map["data"] field (also base64 encoded) may be provided, it will not be considered a template but as a data object to apply to the templates in template.Execute`, + ), + }) + return + } + var postedData interface{} + if v, ok := postTemplates["data"]; ok { + b, err := base64.StdEncoding.DecodeString(v) + if err != nil { + l.Warningf("error decoding map[data] from request ( %s %s ) from %s: b64dec: %s", r.Method, r.URL, r.RemoteAddr, err) + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(jresp{ + Status: http.StatusBadRequest, + Error: err, + }) + return + } + postedData = string(b) + delete(postTemplates, "data") + } + if len(postTemplates) < 1 { + l.Infof("request ( %s %s ) from %s: no content", r.Method, r.URL, r.RemoteAddr) + w.WriteHeader(http.StatusNoContent) + return + } + tpl := template.New("").Funcs(buildFuncMap(*unsafe)) + for n, t := range postTemplates { + b, err := base64.RawStdEncoding.DecodeString(t) + if err != nil { + l.Warningf("error decoding templates from request ( %s %s ) from %s: b64dec: %s", r.Method, r.URL, r.RemoteAddr, err) + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(jresp{ + Status: http.StatusBadRequest, + Error: err, + }) + return + } + tpl, err = tpl.New(n).Parse(string(b)) + if err != nil { + l.Warningf("error processing request ( %s %s ) from %s: tpl.New: %s", r.Method, r.URL, r.RemoteAddr, err) + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(jresp{ + Status: http.StatusBadRequest, + Error: err, + }) + return + } + } + buf := new(bytes.Buffer) + if err := tpl.Execute(buf, postedData); err != nil { + l.Warningf("error processing request ( %s %s ) from %s: tpl.Execute: %s", r.Method, r.URL, r.RemoteAddr, err) + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(jresp{ + Status: http.StatusInternalServerError, + Error: err, + }) + return + } + w.WriteHeader(http.StatusOK) + _, err := io.Copy(w, buf) + if err != nil { + l.Warningf("error sending response to request ( %s %s ) from %s: %s", r.Method, r.URL, r.RemoteAddr, err) + } + l.Infof("processed request ( %s %s ) from %s", r.Method, r.URL, r.RemoteAddr) +} + +//http.Error() + +func uiPage(w http.ResponseWriter, r *http.Request) { + l.Noticef("new request ( %s %s ) from %s", r.Method, r.URL, r.RemoteAddr) + if *debug { + b, _ := httputil.DumpRequest(r, true) + l.Debugf("request ( %s %s ) from %s: %s", r.Method, r.URL, r.RemoteAddr, string(b)) + } + if r.Method != http.MethodGet { + l.Errorf("rejected request ( %s %s ) from %s: bad method", r.Method, r.URL, r.RemoteAddr) + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + w.WriteHeader(http.StatusOK) + w.Write([]byte(` + + +
+