Skip to content

Commit

Permalink
Merge pull request #41 from xushiwei/q
Browse files Browse the repository at this point in the history
x/http/fs.Root(), x/http/tracer.Tee/NewCodeRecorder
  • Loading branch information
xushiwei authored Aug 23, 2023
2 parents 1952d88 + e552abd commit 29fc16d
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 1 deletion.
65 changes: 65 additions & 0 deletions http/fs/fs.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fs

import (
"io"
"io/fs"
"net/http"
"os"
Expand Down Expand Up @@ -119,3 +120,67 @@ func FilesWithContent(files ...string) http.FileSystem {
}

// -----------------------------------------------------------------------------------------

type rootDir struct {
}

func (p rootDir) Name() string {
return "/"
}

func (p rootDir) Size() int64 {
return 0
}

func (p rootDir) Mode() fs.FileMode {
return fs.ModeDir
}

func (p rootDir) ModTime() time.Time {
return time.Now()
}

func (p rootDir) IsDir() bool {
return true
}

func (p rootDir) Sys() interface{} {
return nil
}

func (p rootDir) Close() error {
return nil
}

func (p rootDir) Write(b []byte) (n int, err error) {
return 0, io.ErrUnexpectedEOF
}

func (p rootDir) Read(b []byte) (n int, err error) {
return 0, io.EOF
}

func (p rootDir) Readdir(count int) ([]fs.FileInfo, error) {
return nil, io.EOF
}

func (p rootDir) Seek(offset int64, whence int) (int64, error) {
return 0, io.EOF
}

func (p rootDir) Stat() (fs.FileInfo, error) {
return rootDir{}, nil
}

func (p rootDir) Open(name string) (f http.File, err error) {
if name == "/" {
return rootDir{}, nil
}
return nil, os.ErrNotExist
}

func Root() http.FileSystem {
return rootDir{}
}

// -----------------------------------------------------------------------------------------
63 changes: 62 additions & 1 deletion http/tracer/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,72 @@ package tracer
import (
"log"
"net/http"
"time"
)

// -------------------------------------------------------------------------------

type teeResponseWriter struct {
w []http.ResponseWriter
}

func (p *teeResponseWriter) Header() http.Header {
return p.w[0].Header()
}

func (p *teeResponseWriter) Write(buf []byte) (n int, err error) {
n, err = p.w[0].Write(buf)
for _, w := range p.w[1:] {
w.Write(buf)
}
return
}

func (p *teeResponseWriter) WriteHeader(statusCode int) {
p.w[0].WriteHeader(statusCode)
for _, w := range p.w[1:] {
w.WriteHeader(statusCode)
}
}

func Tee(w ...http.ResponseWriter) http.ResponseWriter {
return &teeResponseWriter{w}
}

// -------------------------------------------------------------------------------

type CodeRecorder struct {
Code int
}

func (p *CodeRecorder) Header() http.Header {
return nil
}

func (p *CodeRecorder) Write(buf []byte) (n int, err error) {
return
}

func (p *CodeRecorder) WriteHeader(statusCode int) {
p.Code = statusCode
}

func NewCodeRecorder() *CodeRecorder {
return &CodeRecorder{}
}

// -------------------------------------------------------------------------------

func New(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
recorder := NewCodeRecorder()
tee := Tee(w, recorder)
log.Printf("%s %v\n", r.Method, r.URL)
h.ServeHTTP(w, r)
start := time.Now()
h.ServeHTTP(tee, r)
dur := time.Since(start)
log.Printf("Returned %d in %d ms\n", recorder.Code, dur.Milliseconds())
})
}

// -------------------------------------------------------------------------------

0 comments on commit 29fc16d

Please sign in to comment.