3 files changed, 63 insertions(+), 55 deletions(-)

M restlog.go
M restlog_test.go
M rlog
M restlog.go +58 -51
@@ 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)
 	}

          
M restlog_test.go +3 -3
@@ 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")
 		}
 	}
 }

          
M rlog +2 -1
@@ 1,6 1,7 @@ 
 #!/bin/sh
 
-readonly url='http://henry.precheur.org/log/rlog'
+# readonly url='http://henry.precheur.org/log/rlog'
+readonly url='http://localhost:8080/log'
 
 if test -z "$*"
 then