diff --git a/certgen_test.go b/certgen_test.go index d2cee04..65ada2e 100644 --- a/certgen_test.go +++ b/certgen_test.go @@ -1,14 +1,13 @@ package devd import ( - "io/ioutil" "os" "path" "testing" ) func TestGenerateCert(t *testing.T) { - d, err := ioutil.TempDir("", "devdtest") + d, err := os.MkdirTemp("", "devdtest") if err != nil { t.Error(err) return diff --git a/fileserver/fileserver.go b/fileserver/fileserver.go index f188800..c6eb7e2 100644 --- a/fileserver/fileserver.go +++ b/fileserver/fileserver.go @@ -4,6 +4,7 @@ package fileserver import ( + "context" "errors" "fmt" "html/template" @@ -18,8 +19,6 @@ import ( "strings" "time" - "golang.org/x/net/context" - "github.com/cortesi/devd/inject" "github.com/cortesi/devd/routespec" "github.com/cortesi/termlog" @@ -115,7 +114,7 @@ func serveContent(ci inject.CopyInject, w http.ResponseWriter, r *http.Request, var buf [sniffLen]byte n, _ := io.ReadFull(content, buf[:]) ctype = http.DetectContentType(buf[:n]) - _, err := content.Seek(0, os.SEEK_SET) // rewind to output whole file + _, err := content.Seek(0, io.SeekStart) // rewind to output whole file if err != nil { http.Error(w, "seeker can't seek", http.StatusInternalServerError) return err @@ -229,7 +228,7 @@ func localRedirect(w http.ResponseWriter, r *http.Request, newPath string) { // To use the operating system's file system implementation, // use http.Dir: // -// http.Handle("/", &fileserver.FileServer{Root: http.Dir("/tmp")}) +// http.Handle("/", &fileserver.FileServer{Root: http.Dir("/tmp")}) type FileServer struct { Version string Root http.FileSystem @@ -301,10 +300,7 @@ func _getType(ext string) string { func matchTypes(spec string, req string) bool { smime := _getType(path.Ext(spec)) rmime := _getType(path.Ext(req)) - if smime == rmime { - return true - } - return false + return smime == rmime } func (fserver *FileServer) serve404(w http.ResponseWriter) error { diff --git a/fileserver/fileserver_test.go b/fileserver/fileserver_test.go index 1a7fcf2..5c584e0 100644 --- a/fileserver/fileserver_test.go +++ b/fileserver/fileserver_test.go @@ -6,9 +6,7 @@ package fileserver import ( "bytes" - "errors" "io" - "io/ioutil" "net/http" "net/http/httptest" "net/url" @@ -17,7 +15,6 @@ import ( "path/filepath" "reflect" "runtime" - "strconv" "strings" "sync" "testing" @@ -49,11 +46,11 @@ func ServeFile(w http.ResponseWriter, r *http.Request, name string) { func ServeContent(w http.ResponseWriter, req *http.Request, name string, modtime time.Time, content io.ReadSeeker) error { sizeFunc := func() (int64, error) { - size, err := content.Seek(0, os.SEEK_END) + size, err := content.Seek(0, io.SeekEnd) if err != nil { return 0, errSeeker } - _, err = content.Seek(0, os.SEEK_SET) + _, err = content.Seek(0, io.SeekStart) if err != nil { return 0, errSeeker } @@ -67,12 +64,6 @@ const ( testFileLen = 11 ) -type wantRange struct { - start, end int64 // range [start,end) -} - -var itoa = strconv.Itoa - var notFoundSearchPathsSpecs = []struct { path string spec string @@ -131,7 +122,7 @@ func TestServeFile(t *testing.T) { var err error - file, err := ioutil.ReadFile(testFile) + file, err := os.ReadFile(testFile) if err != nil { t.Fatal("reading file:", err) } @@ -188,47 +179,6 @@ func TestFSRedirect(t *testing.T) { } } -type testFileSystem struct { - open func(name string) (http.File, error) -} - -func (fs *testFileSystem) Open(name string) (http.File, error) { - return fs.open(name) -} - -func _TestFileServerCleans(t *testing.T) { - defer afterTest(t) - ch := make(chan string, 1) - fs := &FileServer{ - "version", - &testFileSystem{ - func(name string) (http.File, error) { - ch <- name - return nil, errors.New("file does not exist") - }, - }, - inject.CopyInject{}, - ricetemp.MustMakeTemplates(rice.MustFindBox("../templates")), - []routespec.RouteSpec{}, - "", - } - tests := []struct { - reqPath, openArg string - }{ - {"/foo.txt", "/foo.txt"}, - {"/../foo.txt", "/foo.txt"}, - } - req, _ := http.NewRequest("GET", "http://example.com", nil) - for n, test := range tests { - rec := httptest.NewRecorder() - req.URL.Path = test.reqPath - fs.ServeHTTP(rec, req) - if got := <-ch; got != test.openArg { - t.Errorf("test %d: got %q, want %q", n, got, test.openArg) - } - } -} - func mustRemoveAll(dir string) { err := os.RemoveAll(dir) if err != nil { @@ -238,12 +188,12 @@ func mustRemoveAll(dir string) { func TestFileServerImplicitLeadingSlash(t *testing.T) { defer afterTest(t) - tempDir, err := ioutil.TempDir("", "") + tempDir, err := os.MkdirTemp("", "") if err != nil { t.Fatalf("TempDir: %v", err) } defer mustRemoveAll(tempDir) - if err := ioutil.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil { + if err := os.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil { t.Fatalf("WriteFile: %v", err) } fs := &FileServer{ @@ -262,7 +212,7 @@ func TestFileServerImplicitLeadingSlash(t *testing.T) { if err != nil { t.Fatalf("Get %s: %v", suffix, err) } - b, err := ioutil.ReadAll(res.Body) + b, err := io.ReadAll(res.Body) if err != nil { t.Fatalf("ReadAll %s: %v", suffix, err) } @@ -427,7 +377,7 @@ func TestServeIndexHtml(t *testing.T) { if err != nil { t.Fatal(err) } - b, err := ioutil.ReadAll(res.Body) + b, err := io.ReadAll(res.Body) if err != nil { t.Fatal("reading Body:", err) } @@ -455,7 +405,7 @@ func TestFileServerZeroByte(t *testing.T) { if err != nil { t.Fatal(err) } - b, err := ioutil.ReadAll(res.Body) + b, err := io.ReadAll(res.Body) if err != nil { t.Fatal("reading Body:", err) } @@ -623,7 +573,7 @@ func TestDirectoryIfNotModified(t *testing.T) { if err != nil { t.Fatal(err) } - b, err := ioutil.ReadAll(res.Body) + b, err := io.ReadAll(res.Body) if err != nil { t.Fatal(err) } @@ -806,7 +756,7 @@ func TestServeContent(t *testing.T) { if err != nil { t.Fatal(err) } - _, err = io.Copy(ioutil.Discard, res.Body) + _, err = io.Copy(io.Discard, res.Body) if err != nil { t.Fatal(err) } @@ -828,7 +778,7 @@ func getBody(t *testing.T, testName string, req http.Request) (*http.Response, [ if err != nil { t.Fatalf("%s: for URL %q, send error: %v", testName, req.URL.String(), err) } - b, err := ioutil.ReadAll(r.Body) + b, err := io.ReadAll(r.Body) if err != nil { t.Fatalf("%s: for URL %q, reading body: %v", testName, req.URL.String(), err) } diff --git a/httpctx/httpctx.go b/httpctx/httpctx.go index 0cb5df7..ea68f89 100644 --- a/httpctx/httpctx.go +++ b/httpctx/httpctx.go @@ -2,10 +2,9 @@ package httpctx import ( + "context" "net/http" "strings" - - "golang.org/x/net/context" ) // Handler is a request handler with an added context diff --git a/inject/inject.go b/inject/inject.go index 40041e2..3be423b 100644 --- a/inject/inject.go +++ b/inject/inject.go @@ -101,7 +101,7 @@ func (ci *CopyInject) Sniff(src io.Reader, contentType string) (Injector, error) return nil, fmt.Errorf("inject could not read data to sniff: %s", err) } injector.sniffedData = buf[:n] - if bytes.Index(buf, ci.Payload) > -1 { + if bytes.Contains(buf, ci.Payload) { return injector, nil } loc := ci.Marker.FindIndex(injector.sniffedData[:min(n, ci.Within)]) @@ -114,7 +114,7 @@ func (ci *CopyInject) Sniff(src io.Reader, contentType string) (Injector, error) // ServeTemplate renders and serves a template to an http.ResponseWriter func (ci *CopyInject) ServeTemplate(statuscode int, w http.ResponseWriter, t *template.Template, data interface{}) error { - buff := bytes.NewBuffer(make([]byte, 0, 0)) + buff := bytes.NewBuffer(make([]byte, 0)) err := t.Execute(buff, data) if err != nil { return err diff --git a/inject/inject_test.go b/inject/inject_test.go index 9b8f1c2..f7b321f 100644 --- a/inject/inject_test.go +++ b/inject/inject_test.go @@ -18,7 +18,7 @@ func inject(ci CopyInject, data string, contentType string) (found bool, dstdata if err != nil { return false, "", err } - return injector.Found(), string(dst.Bytes()), nil + return injector.Found(), dst.String(), nil } func TestReverseProxyNoInject(t *testing.T) { @@ -67,7 +67,7 @@ func TestReverseProxy(t *testing.T) { if err != nil { t.Errorf("Test %d, unexpected error:\n%s\n", i, err) } - if found && strings.Index(dst, tt.payload) == -1 { + if found && !strings.Contains(dst, tt.payload) { t.Errorf( "Test %d, payload not found.", i, ) @@ -110,8 +110,8 @@ func TestNil(t *testing.T) { t.Error("Unexpected") } dst := bytes.NewBuffer(make([]byte, 0)) - injector.Copy(dst) - if string(dst.Bytes()) != val { - t.Errorf("Expected %s, got %s", val, string(dst.Bytes())) + _, _ = injector.Copy(dst) + if dst.String() != val { + t.Errorf("Expected %s, got %s", val, dst.String()) } } diff --git a/responselogger.go b/responselogger.go index 6d12a0b..9d8c3fc 100644 --- a/responselogger.go +++ b/responselogger.go @@ -41,7 +41,7 @@ func (rl *ResponseLogWriter) logCode(code int, status string) { if err != nil { rl.Log.Warn("Invalid content-length header") } else if cli > 0 { - clstr = fmt.Sprintf("%s", humanize.Bytes(uint64(cli))) + clstr = humanize.Bytes(uint64(cli)) } } rl.Log.Say("<- %s %s", codestr, clstr) diff --git a/reverseproxy/reverseproxy.go b/reverseproxy/reverseproxy.go index 7708195..c8a7944 100644 --- a/reverseproxy/reverseproxy.go +++ b/reverseproxy/reverseproxy.go @@ -4,6 +4,7 @@ package reverseproxy import ( + "context" "fmt" "io" "net" @@ -14,8 +15,6 @@ import ( "sync" "time" - "golang.org/x/net/context" - "github.com/cortesi/devd/inject" "github.com/cortesi/termlog" humanize "github.com/dustin/go-humanize" diff --git a/reverseproxy/reverseproxy_test.go b/reverseproxy/reverseproxy_test.go index 4aafbb0..c9c894b 100644 --- a/reverseproxy/reverseproxy_test.go +++ b/reverseproxy/reverseproxy_test.go @@ -7,7 +7,7 @@ package reverseproxy import ( - "io/ioutil" + "io" "net/http" "net/http/httptest" "net/url" @@ -46,7 +46,13 @@ func TestReverseProxy(t *testing.T) { w.Header().Set("X-Foo", "bar") http.SetCookie(w, &http.Cookie{Name: "flavor", Value: "chocolateChip"}) w.WriteHeader(backendStatus) - w.Write([]byte(backendResponse)) + n, err := w.Write([]byte(backendResponse)) + if err != nil { + t.Errorf("backend write error: %s", err) + } + if n != len(backendResponse) { + t.Errorf("backend write short: got %d want %d", n, len(backendResponse)) + } })) defer backend.Close() backendURL, err := url.Parse(backend.URL) @@ -78,7 +84,7 @@ func TestReverseProxy(t *testing.T) { if cookie := res.Cookies()[0]; cookie.Name != "flavor" { t.Errorf("unexpected cookie %q", cookie.Name) } - bodyBytes, _ := ioutil.ReadAll(res.Body) + bodyBytes, _ := io.ReadAll(res.Body) if g, e := string(bodyBytes), backendResponse; g != e { t.Errorf("got body %q; expected %q", g, e) } @@ -96,7 +102,13 @@ func TestXForwardedFor(t *testing.T) { t.Errorf("X-Forwarded-For didn't contain prior data") } w.WriteHeader(backendStatus) - w.Write([]byte(backendResponse)) + n, err := w.Write([]byte(backendResponse)) + if err != nil { + t.Errorf("forward write error: %s", err) + } + if n != len(backendResponse) { + t.Errorf("forward write short: got %d want %d", n, len(backendResponse)) + } })) defer backend.Close() backendURL, err := url.Parse(backend.URL) @@ -119,7 +131,7 @@ func TestXForwardedFor(t *testing.T) { if g, e := res.StatusCode, backendStatus; g != e { t.Errorf("got res.StatusCode %d; expected %d", g, e) } - bodyBytes, _ := ioutil.ReadAll(res.Body) + bodyBytes, _ := io.ReadAll(res.Body) if g, e := string(bodyBytes), backendResponse; g != e { t.Errorf("got body %q; expected %q", g, e) } @@ -139,7 +151,7 @@ var proxyQueryTests = []struct { func TestReverseProxyQuery(t *testing.T) { backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Got-Query", r.URL.RawQuery) - w.Write([]byte("hi")) + _, _ = w.Write([]byte("hi")) })) defer backend.Close() @@ -166,7 +178,7 @@ func TestReverseProxyQuery(t *testing.T) { func TestReverseProxyFlushInterval(t *testing.T) { const expected = "hi" backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(expected)) + _, _ = w.Write([]byte(expected)) })) defer backend.Close() @@ -192,7 +204,7 @@ func TestReverseProxyFlushInterval(t *testing.T) { t.Fatalf("Get: %v", err) } defer res.Body.Close() - if bodyBytes, _ := ioutil.ReadAll(res.Body); string(bodyBytes) != expected { + if bodyBytes, _ := io.ReadAll(res.Body); string(bodyBytes) != expected { t.Errorf("got body %q; expected %q", bodyBytes, expected) } diff --git a/server.go b/server.go index 7e164ff..dabf70a 100644 --- a/server.go +++ b/server.go @@ -1,6 +1,7 @@ package devd import ( + "context" "crypto/tls" "fmt" "html/template" @@ -13,8 +14,6 @@ import ( "syscall" "time" - "golang.org/x/net/context" - rice "github.com/GeertJohan/go.rice" "github.com/goji/httpauth" @@ -55,7 +54,7 @@ func pickPort(addr string, low int, high int, tls bool) (net.Listener, error) { func getTLSConfig(path string) (t *tls.Config, err error) { config := &tls.Config{} if config.NextProtos == nil { - config.NextProtos = []string{"http/1.1"} + config.NextProtos = []string{"h2", "http/1.1"} } config.Certificates = make([]tls.Certificate, 1) config.Certificates[0], err = tls.LoadX509KeyPair(path, path) @@ -245,7 +244,7 @@ func (dd *Devd) AddRoutes(specs []string, notfound []string) error { // AddIgnores adds log ignore patterns to the server func (dd *Devd) AddIgnores(specs []string) error { - dd.IgnoreLogs = make([]*regexp.Regexp, 0, 0) + dd.IgnoreLogs = make([]*regexp.Regexp, 0) for _, expr := range specs { v, err := regexp.Compile(expr) if err != nil { @@ -296,7 +295,7 @@ func (dd *Devd) Router(logger termlog.TermLog, templates *template.Template) (ht mux.Handle(livereload.ScriptPath, http.HandlerFunc(lr.ServeScript)) seen := make(map[string]bool) for _, route := range dd.Routes { - if _, ok := seen[route.Host]; route.Host != "" && ok == false { + if _, ok := seen[route.Host]; route.Host != "" && !ok { mux.Handle(route.Host+livereload.EndpointPath, lr) mux.Handle( route.Host+livereload.ScriptPath, diff --git a/timer/timer.go b/timer/timer.go index 7bbc50d..309cbfa 100644 --- a/timer/timer.go +++ b/timer/timer.go @@ -3,10 +3,9 @@ package timer import ( + "context" "fmt" "time" - - "golang.org/x/net/context" ) // Timer collects request and response timing information @@ -47,14 +46,16 @@ func (t *Timer) ResponseDone() { t.tsResponseDone = time.Now().UnixNano() } +type timerKey string + // NewContext creates a new context with the timer included func (t *Timer) NewContext(ctx context.Context) context.Context { - return context.WithValue(ctx, "timer", t) + return context.WithValue(ctx, timerKey("timer"), t) } // FromContext creates a new context with the timer included func FromContext(ctx context.Context) *Timer { - timer, ok := ctx.Value("timer").(*Timer) + timer, ok := ctx.Value(timerKey("timer")).(*Timer) if !ok { // Return a dummy timer return &Timer{} diff --git a/watch_test.go b/watch_test.go index a632575..0861d8b 100644 --- a/watch_test.go +++ b/watch_test.go @@ -2,7 +2,6 @@ package devd import ( "fmt" - "io/ioutil" "os" "sync" "testing" @@ -13,7 +12,7 @@ import ( ) func addTempFile(t *testing.T, tmpFolder string, fname string, content string) { - if err := ioutil.WriteFile(tmpFolder+"/"+fname, []byte(content), 0644); err != nil { + if err := os.WriteFile(tmpFolder+"/"+fname, []byte(content), 0644); err != nil { t.Error(err) } } @@ -22,16 +21,16 @@ func TestRouteWatch(t *testing.T) { logger := termlog.NewLog() logger.Quiet() - tmpFolder, err := ioutil.TempDir("", "") + tmpFolder, err := os.MkdirTemp("", "") if err != nil { t.Error(err) } defer os.RemoveAll(tmpFolder) // Ensure that using . for the path works: - os.Chdir(tmpFolder) + _ = os.Chdir(tmpFolder) routes := make(RouteCollection) - routes.Add(".", nil) + _ = routes.Add(".", nil) changedFiles := make(map[string]int) ch := make(chan []string, 1024)