diff --git a/format.go b/cmd/circologd/format.go similarity index 56% rename from format.go rename to cmd/circologd/format.go index 90237ce..4818d2f 100644 --- a/format.go +++ b/cmd/circologd/format.go @@ -1,7 +1,9 @@ -package circolog +package main import ( - "bytes" + "encoding/json" + "fmt" + "io" "text/template" "time" @@ -31,9 +33,32 @@ func init() { )) } -// FormatSyslog format a message in the typical format used in /var/log/messages -func FormatSyslog(msg format.LogParts) string { - var buf bytes.Buffer - syslogTmpl.Execute(&buf, msg) - return buf.String() +type renderFormat int + +func parseRenderFormat(s string) (renderFormat, error) { + switch s { + case "json": + return formatJSON, nil + case "syslog": + return formatSyslog, nil + default: + return 0, fmt.Errorf("Undefined format `%s`", s) + } +} + +const ( + formatSyslog = iota // 0 + formatJSON = iota +) + +func writeFormatted(w io.Writer, f renderFormat, msg format.LogParts) error { + switch f { + case formatSyslog: + return syslogTmpl.Execute(w, msg) + case formatJSON: + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + return enc.Encode(msg) + } + return nil } diff --git a/cmd/circologd/http.go b/cmd/circologd/http.go index 8bec128..92a1a29 100644 --- a/cmd/circologd/http.go +++ b/cmd/circologd/http.go @@ -2,6 +2,7 @@ package main import ( "errors" + "fmt" "log" "net/http" "strconv" @@ -36,7 +37,7 @@ func parseParameterL(r *http.Request) (int, error) { return requestMessageLen, nil } -func parseParameters(w http.ResponseWriter, r *http.Request) (circolog.ClientOptions, error) { +func parseParameters(r *http.Request) (circolog.ClientOptions, error) { var opts circolog.ClientOptions err := r.ParseForm() if err != nil { @@ -52,13 +53,46 @@ func parseParameters(w http.ResponseWriter, r *http.Request) (circolog.ClientOpt return opts, err } +type renderOptions struct { // those are options relevant to the rendered (that is, the HTTP side of circologd) + Format renderFormat +} + +func parseRenderParameters(r *http.Request) (renderOptions, error) { + opts := renderOptions{} + err := r.ParseForm() + if err != nil { + log.Println("error parsing http request", err) + return opts, err + } + if val, ok := r.Form["fmt"]; ok { + if len(val) != 1 { + return opts, errors.New("Format repeated multiple times") + } + format, err := parseRenderFormat(val[0]) + if err != nil { + return opts, err + } + opts.Format = format + } + return opts, nil +} + func getHTTPHandler(hub circolog.Hub) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // Looking for known parameter in the request - opts, err := parseParameters(w, r) + render_opts, err := parseRenderParameters(r) + if err != nil { + log.Println("Error parsing:", err) + w.WriteHeader(400) + fmt.Fprintln(w, err) + return + } + + opts, err := parseParameters(r) if err != nil { log.Println("Error on request parameter \"l\":", err) w.WriteHeader(400) + fmt.Fprintln(w, err) return } opts.Nofollow = true @@ -70,8 +104,10 @@ func getHTTPHandler(hub circolog.Hub) http.HandlerFunc { hub.Register <- client for x := range client.Messages { - w.Write([]byte(circolog.FormatSyslog(x))) - w.Write([]byte("\n")) + writeFormatted(w, render_opts.Format, x) + if render_opts.Format != formatJSON { // bleah + w.Write([]byte("\n")) + } } } } @@ -82,7 +118,7 @@ func getWSHandler(hub circolog.Hub) http.HandlerFunc { WriteBufferSize: 1024, } return func(w http.ResponseWriter, r *http.Request) { - opts, err := parseParameters(w, r) + opts, err := parseParameters(r) if err != nil { log.Println("Error on request parameter \"l\":", err) w.WriteHeader(400) @@ -120,7 +156,7 @@ func getWSHandler(hub circolog.Hub) http.HandlerFunc { if err != nil { return } - w.Write([]byte(circolog.FormatSyslog(message))) + writeFormatted(w, formatSyslog, message) if err := w.Close(); err != nil { return