@@ 15,17 15,26 @@ import (
var _ = os.Open
-type LogHandler interface {
- Writer(log string) (io.WriteCloser, error)
- Reader(log string) (io.ReadCloser, error)
+
+type Logger interface {
+ Writer(log string) (io.Writer, error)
+ Reader(log string) (io.ReadSeeker, error)
}
type HTTPLog struct {
- logHandler LogHandler
+ logger Logger
+}
+
+func NewHTTPLog(logger Logger) HTTPLog {
+ return HTTPLog{logger: logger}
}
-func NewHTTPLog(handler LogHandler) HTTPLog {
- return HTTPLog{logHandler: handler}
+func closeIfNeeded(value interface{}) error {
+ // switch v := value.(type) {
+ // case io.Closer:
+ // return v.Close()
+ // }
+ return nil
}
func validateInput(req *http.Request) ([]byte, error) {
@@ 47,30 56,41 @@ func validateInput(req *http.Request) ([
return x, nil
}
+func addLog(req *http.Request, logger Logger) (string, int, error) {
+ input, err := validateInput(req)
+ if err != nil {
+ return "", 400, err
+ }
+
+ f, err := logger.Writer(req.URL.Path)
+ if err != nil {
+ return "", 500, err
+ }
+
+ var t = time.Now().Format(time.RFC3339)
+ var line = fmt.Sprintf("%s %s\n", t, string(input))
+ io.WriteString(f, line)
+
+ if err := closeIfNeeded(logger); err != nil {
+ return line, 500, err
+ }
+
+ return line, 200, nil
+}
+
func (self HTTPLog) ServeHTTP(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case "POST":
- input, err := validateInput(req)
- if err != nil {
- http.Error(w, err.Error(), 400)
- return
- }
+ line, code, err := addLog(req, self.logger)
- f, err := self.logHandler.Writer(req.URL.Path)
if err != nil {
- http.Error(w, err.Error(), 500)
- return
+ http.Error(w, err.Error(), code)
+ } else {
+ io.WriteString(w, line)
}
-
- var t = time.Now().Format(time.RFC3339)
- var line = fmt.Sprintf("%s %s\n", t, string(input))
-
- io.WriteString(f, line)
- f.Close()
- io.WriteString(w, line)
return
case "GET":
- var f, err = self.logHandler.Reader(req.URL.Path)
+ var f, err = self.logger.Reader(req.URL.Path)
if err != nil {
code := http.StatusInternalServerError
http.Error(w, err.Error(), code)
@@ 82,7 102,7 @@ func (self HTTPLog) ServeHTTP(w http.Res
http.Error(w, "Only GET & POST", http.StatusMethodNotAllowed)
}
-type FileLogHandler struct{}
+type FileLogger struct{}
func HashPath(path string) string {
var hash = sha1.New()
@@ 101,46 121,33 @@ func fileOpenLog(path string, mode int)
return nil, fmt.Errorf("Invalid mode: %x", mode)
}
-func (h FileLogHandler) Reader(path string) (io.ReadCloser, error) {
+func (h FileLogger) Reader(path string) (io.ReadSeeker, error) {
return fileOpenLog(path, os.O_RDONLY)
}
-func (h FileLogHandler) Writer(path string) (io.WriteCloser, error) {
+func (h FileLogger) Writer(path string) (io.Writer, error) {
return fileOpenLog(path, os.O_WRONLY)
}
-type BufferCloser struct {
- bytes.Buffer
-}
+type MemoryLogger map[string][]byte
-func (_ BufferCloser) Close() error {
- return nil
-}
-
-func NewBufferCloser(buf []byte) *BufferCloser {
- return &BufferCloser{*bytes.NewBuffer(buf)}
+func (self MemoryLogger) handle(path string) []byte {
+ if self[path] == nil {
+ self[path] = make([]byte, 0)
+ }
+ return self[path]
}
-type MemoryLogHandler map[string]*BufferCloser
-
-func (h MemoryLogHandler) handle(path string) (*BufferCloser, error) {
- _, present := h[HashPath(path)]
- if !present {
- h[HashPath(path)] = new(BufferCloser)
- }
- return h[HashPath(path)], nil
+func (self MemoryLogger) Reader(path string) (io.ReadSeeker, error) {
+ return bytes.NewReader(self.handle(path)), nil
}
-func (h MemoryLogHandler) Reader(path string) (io.ReadCloser, error) {
- return h[HashPath(path)], nil
+func (self MemoryLogger) Writer(path string) (io.Writer, error) {
+ return bytes.NewBuffer(self.handle(path)), nil
}
-func (h MemoryLogHandler) Writer(path string) (io.WriteCloser, error) {
- return h.handle(path)
-}
-
-func NewMemoryHandler() *MemoryLogHandler {
- m := make(MemoryLogHandler)
+func NewMemoryLogger() *MemoryLogger {
+ m := make(MemoryLogger)
return &m
}
@@ 171,7 178,7 @@ func main() {
flag.Parse()
addr := listenAddress()
log.Println("Listening on", addr)
- err := http.ListenAndServe(addr, NewHTTPLog(new(FileLogHandler)))
+ err := http.ListenAndServe(addr, NewHTTPLog(new(FileLogger)))
if err != nil {
log.Fatal(err)
}
@@ 33,7 33,7 @@ func getRequest(t *testing.T, log string
}
func TestAddLog(t *testing.T) {
- memorylog := NewMemoryHandler()
+ memorylog := NewMemoryLogger()
var handler = NewHTTPLog(memorylog)
req := postRequest(t, "/log", "foo bar s:+1")
@@ 49,8 49,8 @@ func TestAddLog(t *testing.T) {
t.Errorf("bad # of logs: %d", len(*memorylog))
}
for _, value := range *memorylog {
- if value.Len() < 100 {
- t.Fatal("The logs look small", value.Len(), "< 100")
+ if len(value) < 100 {
+ t.Fatal("The logs look small", len(value), "< 100")
}
}
}