mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-28 04:45:56 +03:00
fix lint warnings (issue 2541) (#2551)
* Lint: fix some errcheck #2541 * Lint: fix passing structcheck #2541 * Lint: update fix structcheck #2541 * Lint: fix errcheck for basicauth, browse, fastcgi_test #2541 * Lint: fix errcheck for browse, fastcgi_test, fcgiclient, fcgiclient_test #2541 * Lint: fix errcheck for responsefilter_test, fcgilient_test #2541 * Lint: fix errcheck for header_test #2541 * Lint: update errcheck for fcgiclient_test #2541 * Lint: fix errcheck for server, header_test, fastcgi_test, https_test, recorder_test #2541 * Lint: fix errcheck for tplcontext, vhosttrie_test, internal_test, handler_test #2541 * Lint: fix errcheck for log_test, markdown mholt#2541 * Lint: fix errcheck for policy, body_test, proxy_test #2541 * Lint: fix errcheck for on multiple packages #2541 - reverseproxy - reverseproxy_test - upstream - upstream_test - body_test * Lint: fix errcheck in multiple packages mholt#2541 - handler_test - redirect_test - requestid_test - rewrite_test - fileserver_test * Lint: fix errcheck in multiple packages mholt#2541 - websocket - setup - collection - redirect_test - templates_test * Lint: fix errcheck in logger test #2541 run goimports against #2551 - lexer_test - log_test - markdown * Update caddyhttp/httpserver/logger_test.go Co-Authored-By: Inconnu08 <taufiqrx8@gmail.com> * Update log_test.go * Lint: fix scope in logger_test #2541 * remove redundant err check in logger_test #2541 * fix alias in logger_test #2541 * fix import for format #2541 * refactor variable names and error check #2541
This commit is contained in:
parent
0c3d90ed21
commit
c32a0f5f71
35 changed files with 498 additions and 220 deletions
|
@ -16,6 +16,7 @@ package caddy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -103,13 +104,20 @@ func TestCaddyRestartCallbacks(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
c.instance.Restart(CaddyfileInput{Contents: []byte(""), ServerTypeName: serverName})
|
_, err := c.instance.Restart(CaddyfileInput{Contents: []byte(""), ServerTypeName: serverName})
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Restart failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(calls, test.expectedCalls) {
|
if !reflect.DeepEqual(calls, test.expectedCalls) {
|
||||||
t.Errorf("Test %d: Callbacks expected: %v, got: %v", i, test.expectedCalls, calls)
|
t.Errorf("Test %d: Callbacks expected: %v, got: %v", i, test.expectedCalls, calls)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.instance.Stop()
|
err = c.instance.Stop()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Stop failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
c.instance.Wait()
|
c.instance.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package caddyfile
|
package caddyfile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -158,7 +159,9 @@ func TestLexer(t *testing.T) {
|
||||||
|
|
||||||
func tokenize(input string) (tokens []Token) {
|
func tokenize(input string) (tokens []Token) {
|
||||||
l := lexer{}
|
l := lexer{}
|
||||||
l.load(strings.NewReader(input))
|
if err := l.load(strings.NewReader(input)); err != nil {
|
||||||
|
log.Printf("[ERROR] load failed: %v", err)
|
||||||
|
}
|
||||||
for l.next() {
|
for l.next() {
|
||||||
tokens = append(tokens, l.token)
|
tokens = append(tokens, l.token)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -193,11 +194,15 @@ func PlainMatcher(passw string) PasswordMatcher {
|
||||||
// compare hashes of equal length instead of actual password
|
// compare hashes of equal length instead of actual password
|
||||||
// to avoid leaking password length
|
// to avoid leaking password length
|
||||||
passwHash := sha1.New()
|
passwHash := sha1.New()
|
||||||
passwHash.Write([]byte(passw))
|
if _, err := passwHash.Write([]byte(passw)); err != nil {
|
||||||
|
log.Printf("[ERROR] unable to write password hash: %v", err)
|
||||||
|
}
|
||||||
passwSum := passwHash.Sum(nil)
|
passwSum := passwHash.Sum(nil)
|
||||||
return func(pw string) bool {
|
return func(pw string) bool {
|
||||||
pwHash := sha1.New()
|
pwHash := sha1.New()
|
||||||
pwHash.Write([]byte(pw))
|
if _, err := pwHash.Write([]byte(pw)); err != nil {
|
||||||
|
log.Printf("[ERROR] unable to write password hash: %v", err)
|
||||||
|
}
|
||||||
pwSum := pwHash.Sum(nil)
|
pwSum := pwHash.Sum(nil)
|
||||||
return subtle.ConstantTimeCompare([]byte(pwSum), []byte(passwSum)) == 1
|
return subtle.ConstantTimeCompare([]byte(pwSum), []byte(passwSum)) == 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,34 +59,34 @@ type Config struct {
|
||||||
|
|
||||||
// A Listing is the context used to fill out a template.
|
// A Listing is the context used to fill out a template.
|
||||||
type Listing struct {
|
type Listing struct {
|
||||||
// The name of the directory (the last element of the path)
|
// The name of the directory (the last element of the path).
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
// The full path of the request
|
// The full path of the request.
|
||||||
Path string
|
Path string
|
||||||
|
|
||||||
// Whether the parent directory is browsable
|
// Whether the parent directory is browse-able.
|
||||||
CanGoUp bool
|
CanGoUp bool
|
||||||
|
|
||||||
// The items (files and folders) in the path
|
// The items (files and folders) in the path.
|
||||||
Items []FileInfo
|
Items []FileInfo
|
||||||
|
|
||||||
// The number of directories in the listing
|
// The number of directories in the listing.
|
||||||
NumDirs int
|
NumDirs int
|
||||||
|
|
||||||
// The number of files (items that aren't directories) in the listing
|
// The number of files (items that aren't directories) in the listing.
|
||||||
NumFiles int
|
NumFiles int
|
||||||
|
|
||||||
// Which sorting order is used
|
// Which sorting order is used.
|
||||||
Sort string
|
Sort string
|
||||||
|
|
||||||
// And which order
|
// And which order.
|
||||||
Order string
|
Order string
|
||||||
|
|
||||||
// If ≠0 then Items have been limited to that many elements
|
// If ≠0 then Items have been limited to that many elements.
|
||||||
ItemsLimitedTo int
|
ItemsLimitedTo int
|
||||||
|
|
||||||
// Optional custom variables for use in browse templates
|
// Optional custom variables for use in browse templates.
|
||||||
User interface{}
|
User interface{}
|
||||||
|
|
||||||
httpserver.Context
|
httpserver.Context
|
||||||
|
@ -244,7 +244,7 @@ func (l Listing) applySort() {
|
||||||
|
|
||||||
func directoryListing(files []os.FileInfo, canGoUp bool, urlPath string, config *Config) (Listing, bool) {
|
func directoryListing(files []os.FileInfo, canGoUp bool, urlPath string, config *Config) (Listing, bool) {
|
||||||
var (
|
var (
|
||||||
fileinfos []FileInfo
|
fileInfos []FileInfo
|
||||||
dirCount, fileCount int
|
dirCount, fileCount int
|
||||||
hasIndexFile bool
|
hasIndexFile bool
|
||||||
)
|
)
|
||||||
|
@ -272,14 +272,14 @@ func directoryListing(files []os.FileInfo, canGoUp bool, urlPath string, config
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
url := url.URL{Path: "./" + name} // prepend with "./" to fix paths with ':' in the name
|
u := url.URL{Path: "./" + name} // prepend with "./" to fix paths with ':' in the name
|
||||||
|
|
||||||
fileinfos = append(fileinfos, FileInfo{
|
fileInfos = append(fileInfos, FileInfo{
|
||||||
IsDir: isDir,
|
IsDir: isDir,
|
||||||
IsSymlink: isSymlink(f),
|
IsSymlink: isSymlink(f),
|
||||||
Name: f.Name(),
|
Name: f.Name(),
|
||||||
Size: f.Size(),
|
Size: f.Size(),
|
||||||
URL: url.String(),
|
URL: u.String(),
|
||||||
ModTime: f.ModTime().UTC(),
|
ModTime: f.ModTime().UTC(),
|
||||||
Mode: f.Mode(),
|
Mode: f.Mode(),
|
||||||
})
|
})
|
||||||
|
@ -289,7 +289,7 @@ func directoryListing(files []os.FileInfo, canGoUp bool, urlPath string, config
|
||||||
Name: path.Base(urlPath),
|
Name: path.Base(urlPath),
|
||||||
Path: urlPath,
|
Path: urlPath,
|
||||||
CanGoUp: canGoUp,
|
CanGoUp: canGoUp,
|
||||||
Items: fileinfos,
|
Items: fileInfos,
|
||||||
NumDirs: dirCount,
|
NumDirs: dirCount,
|
||||||
NumFiles: fileCount,
|
NumFiles: fileCount,
|
||||||
}, hasIndexFile
|
}, hasIndexFile
|
||||||
|
@ -504,7 +504,7 @@ func (b Browse) ServeListing(w http.ResponseWriter, r *http.Request, requestedFi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.WriteTo(w)
|
_, _ = buf.WriteTo(w)
|
||||||
|
|
||||||
return http.StatusOK, nil
|
return http.StatusOK, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ package fastcgi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/fcgi"
|
"net/http/fcgi"
|
||||||
|
@ -39,11 +40,20 @@ func TestServeHTTP(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unable to create listener for test: %v", err)
|
t.Fatalf("Unable to create listener for test: %v", err)
|
||||||
}
|
}
|
||||||
defer listener.Close()
|
defer func() { _ = listener.Close() }()
|
||||||
go fcgi.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
|
go func() {
|
||||||
|
err := fcgi.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Length", bodyLenStr)
|
w.Header().Set("Content-Length", bodyLenStr)
|
||||||
w.Write([]byte(body))
|
_, err := w.Write([]byte(body))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] unable to write header: %v", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] unable to start server: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
handler := Handler{
|
handler := Handler{
|
||||||
Next: nil,
|
Next: nil,
|
||||||
|
@ -147,7 +157,7 @@ func TestBuildEnv(t *testing.T) {
|
||||||
SplitPath: ".php",
|
SplitPath: ".php",
|
||||||
IndexFiles: []string{"index.php"},
|
IndexFiles: []string{"index.php"},
|
||||||
}
|
}
|
||||||
url, err := url.Parse("http://localhost:2015/fgci_test.php?test=foobar")
|
u, err := url.Parse("http://localhost:2015/fgci_test.php?test=foobar")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("Unexpected error:", err.Error())
|
t.Error("Unexpected error:", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -155,7 +165,7 @@ func TestBuildEnv(t *testing.T) {
|
||||||
var newReq = func() *http.Request {
|
var newReq = func() *http.Request {
|
||||||
r := http.Request{
|
r := http.Request{
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
URL: url,
|
URL: u,
|
||||||
Proto: "HTTP/1.1",
|
Proto: "HTTP/1.1",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 1,
|
ProtoMinor: 1,
|
||||||
|
@ -274,7 +284,7 @@ func TestReadTimeout(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Test %d: Unable to create listener for test: %v", i, err)
|
t.Fatalf("Test %d: Unable to create listener for test: %v", i, err)
|
||||||
}
|
}
|
||||||
defer listener.Close()
|
defer func() { _ = listener.Close() }()
|
||||||
|
|
||||||
handler := Handler{
|
handler := Handler{
|
||||||
Next: nil,
|
Next: nil,
|
||||||
|
@ -293,11 +303,16 @@ func TestReadTimeout(t *testing.T) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go fcgi.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
go func() {
|
||||||
|
err := fcgi.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
time.Sleep(test.sleep)
|
time.Sleep(test.sleep)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}))
|
}))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] unable to start server: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
got, err := handler.ServeHTTP(w, r)
|
got, err := handler.ServeHTTP(w, r)
|
||||||
if test.shouldErr {
|
if test.shouldErr {
|
||||||
|
@ -334,7 +349,7 @@ func TestSendTimeout(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Test %d: Unable to create listener for test: %v", i, err)
|
t.Fatalf("Test %d: Unable to create listener for test: %v", i, err)
|
||||||
}
|
}
|
||||||
defer listener.Close()
|
defer func() { _ = listener.Close() }()
|
||||||
|
|
||||||
handler := Handler{
|
handler := Handler{
|
||||||
Next: nil,
|
Next: nil,
|
||||||
|
@ -352,9 +367,14 @@ func TestSendTimeout(t *testing.T) {
|
||||||
}
|
}
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
go fcgi.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
go func() {
|
||||||
|
err := fcgi.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}))
|
}))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] unable to start server: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
got, err := handler.ServeHTTP(w, r)
|
got, err := handler.ServeHTTP(w, r)
|
||||||
if test.shouldErr {
|
if test.shouldErr {
|
||||||
|
|
|
@ -182,8 +182,6 @@ type FCGIClient struct {
|
||||||
stderr bytes.Buffer
|
stderr bytes.Buffer
|
||||||
keepAlive bool
|
keepAlive bool
|
||||||
reqID uint16
|
reqID uint16
|
||||||
readTimeout time.Duration
|
|
||||||
sendTimeout time.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialWithDialerContext connects to the fcgi responder at the specified network address, using custom net.Dialer
|
// DialWithDialerContext connects to the fcgi responder at the specified network address, using custom net.Dialer
|
||||||
|
@ -397,7 +395,7 @@ func (c *FCGIClient) Do(p map[string]string, req io.Reader) (r io.Reader, err er
|
||||||
|
|
||||||
body := newWriter(c, Stdin)
|
body := newWriter(c, Stdin)
|
||||||
if req != nil {
|
if req != nil {
|
||||||
io.Copy(body, req)
|
_, _ = io.Copy(body, req)
|
||||||
}
|
}
|
||||||
body.Close()
|
body.Close()
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,9 @@ type FastCGIServer struct{}
|
||||||
|
|
||||||
func (s FastCGIServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
func (s FastCGIServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
||||||
|
|
||||||
req.ParseMultipartForm(100000000)
|
if err := req.ParseMultipartForm(100000000); err != nil {
|
||||||
|
log.Printf("[ERROR] failed to parse: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
stat := "PASSED"
|
stat := "PASSED"
|
||||||
fmt.Fprintln(resp, "-")
|
fmt.Fprintln(resp, "-")
|
||||||
|
@ -68,15 +70,15 @@ func (s FastCGIServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
||||||
length := 0
|
length := 0
|
||||||
for k0, v0 := range req.Form {
|
for k0, v0 := range req.Form {
|
||||||
h := md5.New()
|
h := md5.New()
|
||||||
io.WriteString(h, v0[0])
|
_, _ = io.WriteString(h, v0[0])
|
||||||
md5 := fmt.Sprintf("%x", h.Sum(nil))
|
_md5 := fmt.Sprintf("%x", h.Sum(nil))
|
||||||
|
|
||||||
length += len(k0)
|
length += len(k0)
|
||||||
length += len(v0[0])
|
length += len(v0[0])
|
||||||
|
|
||||||
// echo error when key != md5(val)
|
// echo error when key != _md5(val)
|
||||||
if md5 != k0 {
|
if _md5 != k0 {
|
||||||
fmt.Fprintln(resp, "server:err ", md5, k0)
|
fmt.Fprintln(resp, "server:err ", _md5, k0)
|
||||||
stat = "FAILED"
|
stat = "FAILED"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,8 +199,12 @@ func generateRandFile(size int) (p string, m string) {
|
||||||
for i := 0; i < size/16; i++ {
|
for i := 0; i < size/16; i++ {
|
||||||
buf := make([]byte, 16)
|
buf := make([]byte, 16)
|
||||||
binary.PutVarint(buf, rand.Int63())
|
binary.PutVarint(buf, rand.Int63())
|
||||||
fo.Write(buf)
|
if _, err := fo.Write(buf); err != nil {
|
||||||
h.Write(buf)
|
log.Printf("[ERROR] failed to write buffer: %v\n", err)
|
||||||
|
}
|
||||||
|
if _, err := h.Write(buf); err != nil {
|
||||||
|
log.Printf("[ERROR] failed to write buffer: %v\n", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m = fmt.Sprintf("%x", h.Sum(nil))
|
m = fmt.Sprintf("%x", h.Sum(nil))
|
||||||
return
|
return
|
||||||
|
@ -214,12 +220,13 @@ func DisabledTest(t *testing.T) {
|
||||||
go func() {
|
go func() {
|
||||||
listener, err := net.Listen("tcp", ipPort)
|
listener, err := net.Listen("tcp", ipPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// handle error
|
|
||||||
log.Println("listener creation failed: ", err)
|
log.Println("listener creation failed: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
srv := new(FastCGIServer)
|
srv := new(FastCGIServer)
|
||||||
fcgi.Serve(listener, srv)
|
if err := fcgi.Serve(listener, srv); err != nil {
|
||||||
|
log.Print("[ERROR] failed to start server: ", err)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
|
@ -244,7 +251,7 @@ func DisabledTest(t *testing.T) {
|
||||||
for i := 0x00; i < 0xff; i++ {
|
for i := 0x00; i < 0xff; i++ {
|
||||||
v0 := strings.Repeat(string(i), 256)
|
v0 := strings.Repeat(string(i), 256)
|
||||||
h := md5.New()
|
h := md5.New()
|
||||||
io.WriteString(h, v0)
|
_, _ = io.WriteString(h, v0)
|
||||||
k0 := fmt.Sprintf("%x", h.Sum(nil))
|
k0 := fmt.Sprintf("%x", h.Sum(nil))
|
||||||
data += k0 + "=" + url.QueryEscape(v0) + "&"
|
data += k0 + "=" + url.QueryEscape(v0) + "&"
|
||||||
}
|
}
|
||||||
|
@ -261,7 +268,7 @@ func DisabledTest(t *testing.T) {
|
||||||
for i := 0x00; i < 0xff; i++ {
|
for i := 0x00; i < 0xff; i++ {
|
||||||
v0 := strings.Repeat(string(i), 4096)
|
v0 := strings.Repeat(string(i), 4096)
|
||||||
h := md5.New()
|
h := md5.New()
|
||||||
io.WriteString(h, v0)
|
_, _ = io.WriteString(h, v0)
|
||||||
k0 := fmt.Sprintf("%x", h.Sum(nil))
|
k0 := fmt.Sprintf("%x", h.Sum(nil))
|
||||||
p1[k0] = v0
|
p1[k0] = v0
|
||||||
}
|
}
|
||||||
|
@ -285,6 +292,10 @@ func DisabledTest(t *testing.T) {
|
||||||
delete(f0, "m0")
|
delete(f0, "m0")
|
||||||
sendFcgi(1, fcgiParams, nil, nil, f0)
|
sendFcgi(1, fcgiParams, nil, nil, f0)
|
||||||
|
|
||||||
os.Remove(path0)
|
if err := os.Remove(path0); err != nil {
|
||||||
os.Remove(path1)
|
log.Println("[ERROR] failed to remove path: ", err)
|
||||||
|
}
|
||||||
|
if err := os.Remove(path1); err != nil {
|
||||||
|
log.Println("[ERROR] failed to remove path: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package gzip
|
||||||
import (
|
import (
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -77,7 +78,9 @@ func TestResponseFilterWriter(t *testing.T) {
|
||||||
for i, ts := range tests {
|
for i, ts := range tests {
|
||||||
server.Next = httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
server.Next = httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
w.Header().Set("Content-Length", fmt.Sprint(len(ts.body)))
|
w.Header().Set("Content-Length", fmt.Sprint(len(ts.body)))
|
||||||
w.Write([]byte(ts.body))
|
if _, err := w.Write([]byte(ts.body)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write response: ", err)
|
||||||
|
}
|
||||||
return 200, nil
|
return 200, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -86,7 +89,9 @@ func TestResponseFilterWriter(t *testing.T) {
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
server.ServeHTTP(w, r)
|
if _, err := server.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] unable to serve a gzipped response: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
resp := w.Body.String()
|
resp := w.Body.String()
|
||||||
|
|
||||||
|
@ -109,7 +114,9 @@ func TestResponseGzippedOutput(t *testing.T) {
|
||||||
|
|
||||||
server.Next = httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
server.Next = httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
w.Header().Set("Content-Encoding", "gzip")
|
w.Header().Set("Content-Encoding", "gzip")
|
||||||
w.Write([]byte("gzipped"))
|
if _, err := w.Write([]byte("gzipped")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write response: ", err)
|
||||||
|
}
|
||||||
return 200, nil
|
return 200, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -117,7 +124,9 @@ func TestResponseGzippedOutput(t *testing.T) {
|
||||||
r.Header.Set("Accept-Encoding", "gzip")
|
r.Header.Set("Accept-Encoding", "gzip")
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
server.ServeHTTP(w, r)
|
if _, err := server.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] unable to serve a gzipped response: ", err)
|
||||||
|
}
|
||||||
resp := w.Body.String()
|
resp := w.Body.String()
|
||||||
|
|
||||||
if resp != "gzipped" {
|
if resp != "gzipped" {
|
||||||
|
|
|
@ -16,6 +16,7 @@ package header
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
|
@ -69,7 +70,9 @@ func TestHeader(t *testing.T) {
|
||||||
// preset header
|
// preset header
|
||||||
rec.Header().Set("Server", "Caddy")
|
rec.Header().Set("Server", "Caddy")
|
||||||
|
|
||||||
he.ServeHTTP(rec, req)
|
if _, err := he.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] ServeHTTP failed: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if got := rec.Header().Get(test.name); got != test.value {
|
if got := rec.Header().Get(test.name); got != test.value {
|
||||||
t.Errorf("Test %d: Expected %s header to be %q but was %q",
|
t.Errorf("Test %d: Expected %s header to be %q but was %q",
|
||||||
|
@ -81,7 +84,9 @@ func TestHeader(t *testing.T) {
|
||||||
func TestMultipleHeaders(t *testing.T) {
|
func TestMultipleHeaders(t *testing.T) {
|
||||||
he := Headers{
|
he := Headers{
|
||||||
Next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
Next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
fmt.Fprint(w, "This is a test")
|
if _, err := fmt.Fprint(w, "This is a test"); err != nil {
|
||||||
|
log.Println("[ERROR] Fprint failed: ", err)
|
||||||
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}),
|
}),
|
||||||
Rules: []Rule{
|
Rules: []Rule{
|
||||||
|
@ -97,7 +102,9 @@ func TestMultipleHeaders(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
he.ServeHTTP(rec, req)
|
if _, err := he.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] ServeHTTP failed: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
desiredHeaders := []string{"</css/main.css>; rel=preload", "</images/image.png>; rel=preload"}
|
desiredHeaders := []string{"</css/main.css>; rel=preload", "</images/image.png>; rel=preload"}
|
||||||
actualHeaders := rec.HeaderMap[http.CanonicalHeaderKey("Link")]
|
actualHeaders := rec.HeaderMap[http.CanonicalHeaderKey("Link")]
|
||||||
|
|
|
@ -16,6 +16,7 @@ package httpserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
@ -180,7 +181,9 @@ func TestEnableAutoHTTPS(t *testing.T) {
|
||||||
{}, // not managed - no changes!
|
{}, // not managed - no changes!
|
||||||
}
|
}
|
||||||
|
|
||||||
enableAutoHTTPS(configs, false)
|
if err := enableAutoHTTPS(configs, false); err != nil {
|
||||||
|
log.Println("[ERROR] enableAutoHTTPS failed: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if !configs[0].TLS.Enabled {
|
if !configs[0].TLS.Enabled {
|
||||||
t.Errorf("Expected config 0 to have TLS.Enabled == true, but it was false")
|
t.Errorf("Expected config 0 to have TLS.Enabled == true, but it was false")
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -179,9 +180,13 @@ func bootServer(location string, ch chan format.LogParts) (*syslog.Server, error
|
||||||
|
|
||||||
switch address.network {
|
switch address.network {
|
||||||
case "tcp":
|
case "tcp":
|
||||||
server.ListenTCP(address.address)
|
if err := server.ListenTCP(address.address); err != nil {
|
||||||
|
log.Println("[ERROR] server failed to listen on TCP address: ", err)
|
||||||
|
}
|
||||||
case "udp":
|
case "udp":
|
||||||
server.ListenUDP(address.address)
|
if err := server.ListenUDP(address.address); err != nil {
|
||||||
|
log.Println("[ERROR] server failed to listen on UDP address: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server.SetHandler(syslog.NewChannelHandler(ch))
|
server.SetHandler(syslog.NewChannelHandler(ch))
|
||||||
|
|
|
@ -44,7 +44,7 @@ func TestWrite(t *testing.T) {
|
||||||
responseTestString := "test"
|
responseTestString := "test"
|
||||||
recordRequest := NewResponseRecorder(w)
|
recordRequest := NewResponseRecorder(w)
|
||||||
buf := []byte(responseTestString)
|
buf := []byte(responseTestString)
|
||||||
recordRequest.Write(buf)
|
_, _ = recordRequest.Write(buf)
|
||||||
if recordRequest.size != len(buf) {
|
if recordRequest.size != len(buf) {
|
||||||
t.Fatalf("Expected the bytes written counter to be %d, but instead found %d\n", len(buf), recordRequest.size)
|
t.Fatalf("Expected the bytes written counter to be %d, but instead found %d\n", len(buf), recordRequest.size)
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,7 +234,9 @@ func makeHTTPServerWithTimeouts(addr string, group []*SiteConfig) *http.Server {
|
||||||
|
|
||||||
func (s *Server) wrapWithSvcHeaders(previousHandler http.Handler) http.HandlerFunc {
|
func (s *Server) wrapWithSvcHeaders(previousHandler http.Handler) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
s.quicServer.SetQuicHeaders(w.Header())
|
if err := s.quicServer.SetQuicHeaders(w.Header()); err != nil {
|
||||||
|
log.Println("[Error] failed to set proper headers for QUIC: ", err)
|
||||||
|
}
|
||||||
previousHandler.ServeHTTP(w, r)
|
previousHandler.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,7 +245,7 @@ func (s *Server) wrapWithSvcHeaders(previousHandler http.Handler) http.HandlerFu
|
||||||
// used to serve requests.
|
// used to serve requests.
|
||||||
func (s *Server) Listen() (net.Listener, error) {
|
func (s *Server) Listen() (net.Listener, error) {
|
||||||
if s.Server == nil {
|
if s.Server == nil {
|
||||||
return nil, fmt.Errorf("Server field is nil")
|
return nil, fmt.Errorf("server field is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", s.Server.Addr)
|
ln, err := net.Listen("tcp", s.Server.Addr)
|
||||||
|
@ -324,7 +326,9 @@ func (s *Server) Serve(ln net.Listener) error {
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if s.quicServer != nil {
|
if s.quicServer != nil {
|
||||||
s.quicServer.Close()
|
if err := s.quicServer.Close(); err != nil {
|
||||||
|
log.Println("[ERROR] failed to close QUIC server: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -555,8 +559,12 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tc.SetKeepAlive(true)
|
if err = tc.SetKeepAlive(true); err != nil {
|
||||||
tc.SetKeepAlivePeriod(3 * time.Minute)
|
return
|
||||||
|
}
|
||||||
|
if err = tc.SetKeepAlivePeriod(3 * time.Minute); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
return tc, nil
|
return tc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,7 +602,9 @@ func WriteTextResponse(w http.ResponseWriter, status int, body string) {
|
||||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||||
w.WriteHeader(status)
|
w.WriteHeader(status)
|
||||||
w.Write([]byte(body))
|
if _, err := w.Write([]byte(body)); err != nil {
|
||||||
|
log.Println("[Error] failed to write body: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SafePath joins siteRoot and reqPath and converts it to a path that can
|
// SafePath joins siteRoot and reqPath and converts it to a path that can
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
mathrand "math/rand"
|
mathrand "math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -420,7 +421,9 @@ func (c Context) RandomString(minLen, maxLen int) string {
|
||||||
// secureRandomBytes returns a number of bytes using crypto/rand.
|
// secureRandomBytes returns a number of bytes using crypto/rand.
|
||||||
secureRandomBytes := func(numBytes int) []byte {
|
secureRandomBytes := func(numBytes int) []byte {
|
||||||
randomBytes := make([]byte, numBytes)
|
randomBytes := make([]byte, numBytes)
|
||||||
rand.Read(randomBytes)
|
if _, err := rand.Read(randomBytes); err != nil {
|
||||||
|
log.Println("[ERROR] failed to read bytes: ", err)
|
||||||
|
}
|
||||||
return randomBytes
|
return randomBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package httpserver
|
package httpserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -103,7 +104,9 @@ func populateTestTrie(trie *vhostTrie, keys []string) {
|
||||||
func(key string) {
|
func(key string) {
|
||||||
site := &SiteConfig{
|
site := &SiteConfig{
|
||||||
middlewareChain: HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
middlewareChain: HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
w.Write([]byte(key))
|
if _, err := w.Write([]byte(key)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
@ -139,7 +142,9 @@ func assertTestTrie(t *testing.T, trie *vhostTrie, tests []vhostTrieTest, hasWil
|
||||||
|
|
||||||
// And it must be the correct value
|
// And it must be the correct value
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
site.middlewareChain.ServeHTTP(resp, nil)
|
if _, err := site.middlewareChain.ServeHTTP(resp, nil); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
actualHandlerKey := resp.Body.String()
|
actualHandlerKey := resp.Body.String()
|
||||||
if actualHandlerKey != test.expectedKey {
|
if actualHandlerKey != test.expectedKey {
|
||||||
t.Errorf("Test %d: Expected match '%s' but matched '%s'",
|
t.Errorf("Test %d: Expected match '%s' but matched '%s'",
|
||||||
|
|
|
@ -16,6 +16,7 @@ package internalsrv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -126,7 +127,9 @@ func internalTestHandlerFunc(w http.ResponseWriter, r *http.Request) (int, error
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Header().Set("Content-Type", contentTypeOctetStream)
|
w.Header().Set("Content-Type", contentTypeOctetStream)
|
||||||
w.Header().Set("Content-Length", strconv.Itoa(len(internalProtectedData)))
|
w.Header().Set("Content-Length", strconv.Itoa(len(internalProtectedData)))
|
||||||
w.Write([]byte(internalProtectedData))
|
if _, err := w.Write([]byte(internalProtectedData)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ package limits
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -39,7 +40,9 @@ func TestBodySizeLimit(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
r := httptest.NewRequest("GET", "/", strings.NewReader(expectContent+expectContent))
|
r := httptest.NewRequest("GET", "/", strings.NewReader(expectContent+expectContent))
|
||||||
l.ServeHTTP(httptest.NewRecorder(), r)
|
if _, err := l.ServeHTTP(httptest.NewRecorder(), r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
if got := string(gotContent); got != expectContent {
|
if got := string(gotContent); got != expectContent {
|
||||||
t.Errorf("expected content[%s], got[%s]", expectContent, got)
|
t.Errorf("expected content[%s], got[%s]", expectContent, got)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package log
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -89,7 +90,9 @@ func TestLogRequestBody(t *testing.T) {
|
||||||
}},
|
}},
|
||||||
Next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
Next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
// drain up body
|
// drain up body
|
||||||
ioutil.ReadAll(r.Body)
|
if _, err := ioutil.ReadAll(r.Body); err != nil {
|
||||||
|
log.Println("[ERROR] failed to read request body: ", err)
|
||||||
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
@ -153,7 +156,9 @@ func TestMultiEntries(t *testing.T) {
|
||||||
}},
|
}},
|
||||||
Next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
Next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
// drain up body
|
// drain up body
|
||||||
ioutil.ReadAll(r.Body)
|
if _, err := ioutil.ReadAll(r.Body); err != nil {
|
||||||
|
log.Println("[ERROR] failed to read request body: ", err)
|
||||||
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package markdown
|
package markdown
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
@ -168,7 +169,9 @@ func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
|
||||||
w.Header().Set("Content-Length", strconv.Itoa(len(html)))
|
w.Header().Set("Content-Length", strconv.Itoa(len(html)))
|
||||||
httpserver.SetLastModifiedHeader(w, lastModTime)
|
httpserver.SetLastModifiedHeader(w, lastModTime)
|
||||||
if r.Method == http.MethodGet {
|
if r.Method == http.MethodGet {
|
||||||
w.Write(html)
|
if _, err := w.Write(html); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write html response: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return http.StatusOK, nil
|
return http.StatusOK, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -25,13 +26,15 @@ import (
|
||||||
|
|
||||||
func TestBodyRetry(t *testing.T) {
|
func TestBodyRetry(t *testing.T) {
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
io.Copy(w, r.Body)
|
if _, err := io.Copy(w, r.Body); err != nil {
|
||||||
r.Body.Close()
|
log.Println("[ERROR] failed to copy response body: ", err)
|
||||||
|
}
|
||||||
|
_ = r.Body.Close()
|
||||||
}))
|
}))
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
testcase := "test content"
|
testCase := "test content"
|
||||||
req, err := http.NewRequest(http.MethodPost, ts.URL, bytes.NewBufferString(testcase))
|
req, err := http.NewRequest(http.MethodPost, ts.URL, bytes.NewBufferString(testCase))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -47,12 +50,16 @@ func TestBodyRetry(t *testing.T) {
|
||||||
// simulate fail request
|
// simulate fail request
|
||||||
host := req.URL.Host
|
host := req.URL.Host
|
||||||
req.URL.Host = "example.com"
|
req.URL.Host = "example.com"
|
||||||
body.rewind()
|
if err := body.rewind(); err != nil {
|
||||||
|
log.Println("[ERROR] failed re-read bufferedBody: ", err)
|
||||||
|
}
|
||||||
_, _ = http.DefaultTransport.RoundTrip(req)
|
_, _ = http.DefaultTransport.RoundTrip(req)
|
||||||
|
|
||||||
// retry request
|
// retry request
|
||||||
req.URL.Host = host
|
req.URL.Host = host
|
||||||
body.rewind()
|
if err := body.rewind(); err != nil {
|
||||||
|
log.Println("[ERROR] failed re-read bufferedBody: ", err)
|
||||||
|
}
|
||||||
resp, err := http.DefaultTransport.RoundTrip(req)
|
resp, err := http.DefaultTransport.RoundTrip(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -61,13 +68,15 @@ func TestBodyRetry(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
resp.Body.Close()
|
_ = resp.Body.Close()
|
||||||
if string(result) != testcase {
|
if string(result) != testCase {
|
||||||
t.Fatalf("result = %s, want %s", result, testcase)
|
t.Fatalf("result = %s, want %s", result, testCase)
|
||||||
}
|
}
|
||||||
|
|
||||||
// try one more time for body reuse
|
// try one more time for body reuse
|
||||||
body.rewind()
|
if err := body.rewind(); err != nil {
|
||||||
|
log.Println("[ERROR] failed re-read bufferedBody: ", err)
|
||||||
|
}
|
||||||
resp, err = http.DefaultTransport.RoundTrip(req)
|
resp, err = http.DefaultTransport.RoundTrip(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -76,8 +85,8 @@ func TestBodyRetry(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
resp.Body.Close()
|
_ = resp.Body.Close()
|
||||||
if string(result) != testcase {
|
if string(result) != testCase {
|
||||||
t.Fatalf("result = %s, want %s", result, testcase)
|
t.Fatalf("result = %s, want %s", result, testCase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
|
"log"
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
@ -139,7 +140,9 @@ func hostByHashing(pool HostPool, s string) *UpstreamHost {
|
||||||
// hash calculates a hash based on string s
|
// hash calculates a hash based on string s
|
||||||
func hash(s string) uint32 {
|
func hash(s string) uint32 {
|
||||||
h := fnv.New32a()
|
h := fnv.New32a()
|
||||||
h.Write([]byte(s))
|
if _, err := h.Write([]byte(s)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
return h.Sum32()
|
return h.Sum32()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,9 @@ func TestReverseProxy(t *testing.T) {
|
||||||
requestReceived := false
|
requestReceived := false
|
||||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
// read the body (even if it's empty) to make Go parse trailers
|
// read the body (even if it's empty) to make Go parse trailers
|
||||||
io.Copy(ioutil.Discard, r.Body)
|
if _, err := io.Copy(ioutil.Discard, r.Body); err != nil {
|
||||||
|
log.Println("[ERROR] failed to copy bytes: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
verifyHeadersTrailers(r.Header, r.Trailer)
|
verifyHeadersTrailers(r.Header, r.Trailer)
|
||||||
requestReceived = true
|
requestReceived = true
|
||||||
|
@ -113,7 +115,9 @@ func TestReverseProxy(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write([]byte("Hello, client"))
|
if _, err := w.Write([]byte("Hello, client")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write response: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Set trailers.
|
// Set trailers.
|
||||||
shallowCopyTrailers(w.Header(), testTrailers, true)
|
shallowCopyTrailers(w.Header(), testTrailers, true)
|
||||||
|
@ -149,7 +153,9 @@ func TestReverseProxy(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
res := w.Result()
|
res := w.Result()
|
||||||
|
|
||||||
if !requestReceived {
|
if !requestReceived {
|
||||||
|
@ -165,7 +171,9 @@ func TestReverseProxy(t *testing.T) {
|
||||||
})
|
})
|
||||||
rr.Replacer = httpserver.NewReplacer(r, rr, "-")
|
rr.Replacer = httpserver.NewReplacer(r, rr, "-")
|
||||||
|
|
||||||
p.ServeHTTP(rr, r)
|
if _, err := p.ServeHTTP(rr, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if got, want := rr.Replacer.Replace("{upstream}"), backend.URL; got != want {
|
if got, want := rr.Replacer.Replace("{upstream}"), backend.URL; got != want {
|
||||||
t.Errorf("Expected custom placeholder {upstream} to be set (%s), but it wasn't; got: %s", want, got)
|
t.Errorf("Expected custom placeholder {upstream} to be set (%s), but it wasn't; got: %s", want, got)
|
||||||
|
@ -196,7 +204,9 @@ func TestReverseProxyInsecureSkipVerify(t *testing.T) {
|
||||||
backend := newTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backend := newTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
requestReceived = true
|
requestReceived = true
|
||||||
requestWasHTTP2 = r.ProtoAtLeast(2, 0)
|
requestWasHTTP2 = r.ProtoAtLeast(2, 0)
|
||||||
w.Write([]byte("Hello, client"))
|
if _, err := w.Write([]byte("Hello, client")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write response: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
|
||||||
|
@ -210,7 +220,9 @@ func TestReverseProxyInsecureSkipVerify(t *testing.T) {
|
||||||
r := httptest.NewRequest("GET", "/", nil)
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if !requestReceived {
|
if !requestReceived {
|
||||||
t.Error("Even with insecure HTTPS, expected backend to receive request, but it didn't")
|
t.Error("Even with insecure HTTPS, expected backend to receive request, but it didn't")
|
||||||
|
@ -306,7 +318,9 @@ func TestReverseProxyTimeout(t *testing.T) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
took := time.Since(start)
|
took := time.Since(start)
|
||||||
|
|
||||||
if took > timeout+errorMargin {
|
if took > timeout+errorMargin {
|
||||||
|
@ -342,7 +356,9 @@ func TestWebSocketReverseProxyNonHijackerPanic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nonHijacker := httptest.NewRecorder()
|
nonHijacker := httptest.NewRecorder()
|
||||||
p.ServeHTTP(nonHijacker, r)
|
if _, err := p.ServeHTTP(nonHijacker, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWebSocketReverseProxyBackendShutDown(t *testing.T) {
|
func TestWebSocketReverseProxyBackendShutDown(t *testing.T) {
|
||||||
|
@ -360,7 +376,9 @@ func TestWebSocketReverseProxyBackendShutDown(t *testing.T) {
|
||||||
// Get proxy to use for the test
|
// Get proxy to use for the test
|
||||||
p := newWebSocketTestProxy(backend.URL, false, 30*time.Second)
|
p := newWebSocketTestProxy(backend.URL, false, 30*time.Second)
|
||||||
backendProxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backendProxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer backendProxy.Close()
|
defer backendProxy.Close()
|
||||||
|
|
||||||
|
@ -404,7 +422,9 @@ func TestWebSocketReverseProxyServeHTTPHandler(t *testing.T) {
|
||||||
w := &recorderHijacker{httptest.NewRecorder(), new(fakeConn)}
|
w := &recorderHijacker{httptest.NewRecorder(), new(fakeConn)}
|
||||||
|
|
||||||
// Booya! Do the test.
|
// Booya! Do the test.
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the backend accepted the WS connection.
|
// Make sure the backend accepted the WS connection.
|
||||||
// Mostly interested in the Upgrade and Connection response headers
|
// Mostly interested in the Upgrade and Connection response headers
|
||||||
|
@ -429,7 +449,9 @@ func TestWebSocketReverseProxyFromWSClient(t *testing.T) {
|
||||||
// Echo server allows us to test that socket bytes are properly
|
// Echo server allows us to test that socket bytes are properly
|
||||||
// being proxied.
|
// being proxied.
|
||||||
wsEcho := httptest.NewServer(websocket.Handler(func(ws *websocket.Conn) {
|
wsEcho := httptest.NewServer(websocket.Handler(func(ws *websocket.Conn) {
|
||||||
io.Copy(ws, ws)
|
if _, err := io.Copy(ws, ws); err != nil {
|
||||||
|
log.Println("[ERROR] failed to copy: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer wsEcho.Close()
|
defer wsEcho.Close()
|
||||||
|
|
||||||
|
@ -441,13 +463,15 @@ func TestWebSocketReverseProxyFromWSClient(t *testing.T) {
|
||||||
// WS client will connect to this test server, not
|
// WS client will connect to this test server, not
|
||||||
// the echo client directly.
|
// the echo client directly.
|
||||||
echoProxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
echoProxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer echoProxy.Close()
|
defer echoProxy.Close()
|
||||||
|
|
||||||
// Set up WebSocket client
|
// Set up WebSocket client
|
||||||
url := strings.Replace(echoProxy.URL, "http://", "ws://", 1)
|
u := strings.Replace(echoProxy.URL, "http://", "ws://", 1)
|
||||||
ws, err := websocket.Dial(url, "", echoProxy.URL)
|
ws, err := websocket.Dial(u, "", echoProxy.URL)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -475,20 +499,24 @@ func TestWebSocketReverseProxyFromWSClient(t *testing.T) {
|
||||||
|
|
||||||
func TestWebSocketReverseProxyFromWSSClient(t *testing.T) {
|
func TestWebSocketReverseProxyFromWSSClient(t *testing.T) {
|
||||||
wsEcho := newTLSServer(websocket.Handler(func(ws *websocket.Conn) {
|
wsEcho := newTLSServer(websocket.Handler(func(ws *websocket.Conn) {
|
||||||
io.Copy(ws, ws)
|
if _, err := io.Copy(ws, ws); err != nil {
|
||||||
|
log.Println("[ERROR] failed to copy: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer wsEcho.Close()
|
defer wsEcho.Close()
|
||||||
|
|
||||||
p := newWebSocketTestProxy(wsEcho.URL, true, 30*time.Second)
|
p := newWebSocketTestProxy(wsEcho.URL, true, 30*time.Second)
|
||||||
|
|
||||||
echoProxy := newTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
echoProxy := newTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer echoProxy.Close()
|
defer echoProxy.Close()
|
||||||
|
|
||||||
// Set up WebSocket client
|
// Set up WebSocket client
|
||||||
url := strings.Replace(echoProxy.URL, "https://", "wss://", 1)
|
u := strings.Replace(echoProxy.URL, "https://", "wss://", 1)
|
||||||
wsCfg, err := websocket.NewConfig(url, echoProxy.URL)
|
wsCfg, err := websocket.NewConfig(u, echoProxy.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -558,7 +586,9 @@ func TestUnixSocketProxy(t *testing.T) {
|
||||||
p := newWebSocketTestProxy(url, false, 30*time.Second)
|
p := newWebSocketTestProxy(url, false, 30*time.Second)
|
||||||
|
|
||||||
echoProxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
echoProxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer echoProxy.Close()
|
defer echoProxy.Close()
|
||||||
|
|
||||||
|
@ -599,14 +629,14 @@ func GetSocketProxy(messageFormat string, prefix string) (*Proxy, *httptest.Serv
|
||||||
|
|
||||||
dir, err := ioutil.TempDir("", "caddy_proxytest")
|
dir, err := ioutil.TempDir("", "caddy_proxytest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, dir, fmt.Errorf("Failed to make temp dir to contain unix socket. %v", err)
|
return nil, nil, dir, fmt.Errorf("failed to make temp dir to contain unix socket. %v", err)
|
||||||
}
|
}
|
||||||
socketPath := filepath.Join(dir, "test_socket")
|
socketPath := filepath.Join(dir, "test_socket")
|
||||||
|
|
||||||
ln, err := net.Listen("unix", socketPath)
|
ln, err := net.Listen("unix", socketPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.RemoveAll(dir)
|
os.RemoveAll(dir)
|
||||||
return nil, nil, dir, fmt.Errorf("Unable to listen: %v", err)
|
return nil, nil, dir, fmt.Errorf("unable to listen: %v", err)
|
||||||
}
|
}
|
||||||
ts.Listener = ln
|
ts.Listener = ln
|
||||||
|
|
||||||
|
@ -619,7 +649,9 @@ func GetSocketProxy(messageFormat string, prefix string) (*Proxy, *httptest.Serv
|
||||||
|
|
||||||
func GetTestServerMessage(p *Proxy, ts *httptest.Server, path string) (string, error) {
|
func GetTestServerMessage(p *Proxy, ts *httptest.Server, path string) (string, error) {
|
||||||
echoProxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
echoProxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// *httptest.Server is passed so it can be `defer`red properly
|
// *httptest.Server is passed so it can be `defer`red properly
|
||||||
|
@ -628,13 +660,13 @@ func GetTestServerMessage(p *Proxy, ts *httptest.Server, path string) (string, e
|
||||||
|
|
||||||
res, err := http.Get(echoProxy.URL + path)
|
res, err := http.Get(echoProxy.URL + path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("Unable to GET: %v", err)
|
return "", fmt.Errorf("unable to GET: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
greeting, err := ioutil.ReadAll(res.Body)
|
greeting, err := ioutil.ReadAll(res.Body)
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("Unable to read body: %v", err)
|
return "", fmt.Errorf("unable to read body: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s", greeting), nil
|
return fmt.Sprintf("%s", greeting), nil
|
||||||
|
@ -707,7 +739,9 @@ func TestUpstreamHeadersUpdate(t *testing.T) {
|
||||||
var actualHeaders http.Header
|
var actualHeaders http.Header
|
||||||
var actualHost string
|
var actualHost string
|
||||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte("Hello, client"))
|
if _, err := w.Write([]byte("Hello, client")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write response: ", err)
|
||||||
|
}
|
||||||
actualHeaders = r.Header
|
actualHeaders = r.Header
|
||||||
actualHost = r.Host
|
actualHost = r.Host
|
||||||
}))
|
}))
|
||||||
|
@ -752,7 +786,9 @@ func TestUpstreamHeadersUpdate(t *testing.T) {
|
||||||
r.Header.Add("Regex-Me", "I was originally this")
|
r.Header.Add("Regex-Me", "I was originally this")
|
||||||
r.Header.Add("Regexreplace-Me", "The host is bad")
|
r.Header.Add("Regexreplace-Me", "The host is bad")
|
||||||
|
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
replacer := httpserver.NewReplacer(r, nil, "")
|
replacer := httpserver.NewReplacer(r, nil, "")
|
||||||
|
|
||||||
|
@ -790,7 +826,9 @@ func TestDownstreamHeadersUpdate(t *testing.T) {
|
||||||
w.Header().Add("Overwrite-Me", "Overwrite-Value")
|
w.Header().Add("Overwrite-Me", "Overwrite-Value")
|
||||||
w.Header().Add("Regex-Me", "I was originally this")
|
w.Header().Add("Regex-Me", "I was originally this")
|
||||||
w.Header().Add("Regexreplace-Me", "The host is bad")
|
w.Header().Add("Regexreplace-Me", "The host is bad")
|
||||||
w.Write([]byte("Hello, client"))
|
if _, err := w.Write([]byte("Hello, client")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write response: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
|
||||||
|
@ -822,7 +860,9 @@ func TestDownstreamHeadersUpdate(t *testing.T) {
|
||||||
// set a predefined overwritten header
|
// set a predefined overwritten header
|
||||||
w.Header().Set("Overwrite-Me", "Initial")
|
w.Header().Set("Overwrite-Me", "Initial")
|
||||||
|
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
replacer := httpserver.NewReplacer(r, nil, "")
|
replacer := httpserver.NewReplacer(r, nil, "")
|
||||||
actualHeaders := w.Header()
|
actualHeaders := w.Header()
|
||||||
|
@ -880,7 +920,9 @@ func TestMultiReverseProxyFromClient(t *testing.T) {
|
||||||
|
|
||||||
// This is a full end-end test, so the proxy handler.
|
// This is a full end-end test, so the proxy handler.
|
||||||
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer proxy.Close()
|
defer proxy.Close()
|
||||||
|
|
||||||
|
@ -936,7 +978,9 @@ func TestHostSimpleProxyNoHeaderForward(t *testing.T) {
|
||||||
var requestHost string
|
var requestHost string
|
||||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
requestHost = r.Host
|
requestHost = r.Host
|
||||||
w.Write([]byte("Hello, client"))
|
if _, err := w.Write([]byte("Hello, client")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write response: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
|
||||||
|
@ -951,7 +995,9 @@ func TestHostSimpleProxyNoHeaderForward(t *testing.T) {
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if !strings.Contains(backend.URL, "//") {
|
if !strings.Contains(backend.URL, "//") {
|
||||||
t.Fatalf("The URL of the backend server doesn't contains //: %s", backend.URL)
|
t.Fatalf("The URL of the backend server doesn't contains //: %s", backend.URL)
|
||||||
|
@ -1015,7 +1061,9 @@ func testReverseProxyTransparentHeaders(t *testing.T, remoteAddr, forwardedForHe
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
if got := actualHeaders["X-Forwarded-For"]; !reflect.DeepEqual(got, expected) {
|
if got := actualHeaders["X-Forwarded-For"]; !reflect.DeepEqual(got, expected) {
|
||||||
|
@ -1028,7 +1076,9 @@ func TestHostHeaderReplacedUsingForward(t *testing.T) {
|
||||||
var requestHost string
|
var requestHost string
|
||||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
requestHost = r.Host
|
requestHost = r.Host
|
||||||
w.Write([]byte("Hello, client"))
|
if _, err := w.Write([]byte("Hello, client")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write response: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
|
||||||
|
@ -1046,7 +1096,9 @@ func TestHostHeaderReplacedUsingForward(t *testing.T) {
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if proxyHostHeader != requestHost {
|
if proxyHostHeader != requestHost {
|
||||||
t.Fatalf("Expected %s as a Host header got %s\n", proxyHostHeader, requestHost)
|
t.Fatalf("Expected %s as a Host header got %s\n", proxyHostHeader, requestHost)
|
||||||
|
@ -1077,11 +1129,17 @@ func basicAuthTestcase(t *testing.T, upstreamUser, clientUser *url.Userinfo) {
|
||||||
u, p, ok := r.BasicAuth()
|
u, p, ok := r.BasicAuth()
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
w.Write([]byte(u))
|
if _, err := w.Write([]byte(u)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ok && p != "" {
|
if ok && p != "" {
|
||||||
w.Write([]byte(":"))
|
if _, err := w.Write([]byte(":")); err != nil {
|
||||||
w.Write([]byte(p))
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte(p)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
@ -1107,7 +1165,9 @@ func basicAuthTestcase(t *testing.T, upstreamUser, clientUser *url.Userinfo) {
|
||||||
}
|
}
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if w.Code != 200 {
|
if w.Code != 200 {
|
||||||
t.Fatalf("Invalid response code: %d", w.Code)
|
t.Fatalf("Invalid response code: %d", w.Code)
|
||||||
|
@ -1243,7 +1303,9 @@ func TestReverseProxyRetry(t *testing.T) {
|
||||||
|
|
||||||
// set up proxy
|
// set up proxy
|
||||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
io.Copy(w, r.Body)
|
if _, err := io.Copy(w, r.Body); err != nil {
|
||||||
|
log.Println("[ERROR] failed to copy: ", err)
|
||||||
|
}
|
||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
}))
|
}))
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
@ -1275,8 +1337,8 @@ func TestReverseProxyRetry(t *testing.T) {
|
||||||
}))
|
}))
|
||||||
defer middle.Close()
|
defer middle.Close()
|
||||||
|
|
||||||
testcase := "test content"
|
testCase := "test content"
|
||||||
r, err := http.NewRequest("POST", middle.URL, bytes.NewBufferString(testcase))
|
r, err := http.NewRequest("POST", middle.URL, bytes.NewBufferString(testCase))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -1289,8 +1351,8 @@ func TestReverseProxyRetry(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if string(b) != testcase {
|
if string(b) != testCase {
|
||||||
t.Fatalf("string(b) = %s, want %s", string(b), testcase)
|
t.Fatalf("string(b) = %s, want %s", string(b), testCase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1300,7 +1362,10 @@ func TestReverseProxyLargeBody(t *testing.T) {
|
||||||
|
|
||||||
// set up proxy
|
// set up proxy
|
||||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
io.Copy(ioutil.Discard, r.Body)
|
if _, err := io.Copy(ioutil.Discard, r.Body); err != nil {
|
||||||
|
log.Println("[ERROR] failed to copy: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
}))
|
}))
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
@ -1329,8 +1394,8 @@ func TestReverseProxyLargeBody(t *testing.T) {
|
||||||
|
|
||||||
// We want to see how much memory the proxy module requires for this request.
|
// We want to see how much memory the proxy module requires for this request.
|
||||||
// So lets record the mem stats before we start it.
|
// So lets record the mem stats before we start it.
|
||||||
begMemstats := &runtime.MemStats{}
|
begMemStats := &runtime.MemStats{}
|
||||||
runtime.ReadMemStats(begMemstats)
|
runtime.ReadMemStats(begMemStats)
|
||||||
|
|
||||||
r, err := http.NewRequest("POST", middle.URL, &noopReader{len: bodySize})
|
r, err := http.NewRequest("POST", middle.URL, &noopReader{len: bodySize})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1347,7 +1412,7 @@ func TestReverseProxyLargeBody(t *testing.T) {
|
||||||
runtime.ReadMemStats(endMemstats)
|
runtime.ReadMemStats(endMemstats)
|
||||||
|
|
||||||
// ...to calculate the total amount of allocated memory during the request.
|
// ...to calculate the total amount of allocated memory during the request.
|
||||||
totalAlloc := endMemstats.TotalAlloc - begMemstats.TotalAlloc
|
totalAlloc := endMemstats.TotalAlloc - begMemStats.TotalAlloc
|
||||||
|
|
||||||
// If that's as much as the size of the body itself it's a serious sign that the
|
// If that's as much as the size of the body itself it's a serious sign that the
|
||||||
// request was not "streamed" to the upstream without buffering it first.
|
// request was not "streamed" to the upstream without buffering it first.
|
||||||
|
@ -1369,7 +1434,9 @@ func TestCancelRequest(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write([]byte("Hello, client"))
|
if _, err := w.Write([]byte("Hello, client")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write response: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
|
||||||
|
@ -1506,7 +1573,6 @@ type fakeWsUpstream struct {
|
||||||
without string
|
without string
|
||||||
insecure bool
|
insecure bool
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
fallbackDelay time.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *fakeWsUpstream) From() string {
|
func (u *fakeWsUpstream) From() string {
|
||||||
|
@ -1574,7 +1640,9 @@ var _ httpserver.HTTPInterfaces = testResponseRecorder{}
|
||||||
|
|
||||||
func BenchmarkProxy(b *testing.B) {
|
func BenchmarkProxy(b *testing.B) {
|
||||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte("Hello, client"))
|
if _, err := w.Write([]byte("Hello, client")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write response: ", err)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
|
||||||
|
@ -1602,7 +1670,9 @@ func BenchmarkProxy(b *testing.B) {
|
||||||
b.Fatalf("Failed to create request: %v", err)
|
b.Fatalf("Failed to create request: %v", err)
|
||||||
}
|
}
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
p.ServeHTTP(w, r)
|
if _, err := p.ServeHTTP(w, r); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1684,7 +1754,9 @@ func TestQuic(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte(content))
|
if _, err := w.Write([]byte(content)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
})
|
})
|
||||||
err = h2quic.ListenAndServeQUIC(
|
err = h2quic.ListenAndServeQUIC(
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -69,7 +70,9 @@ func pooledIoCopy(dst io.Writer, src io.Reader) {
|
||||||
// Due to that we extend buf's length to its capacity here and
|
// Due to that we extend buf's length to its capacity here and
|
||||||
// ensure it's always non-zero.
|
// ensure it's always non-zero.
|
||||||
bufCap := cap(buf)
|
bufCap := cap(buf)
|
||||||
io.CopyBuffer(dst, src, buf[0:bufCap:bufCap])
|
if _, err := io.CopyBuffer(dst, src, buf[0:bufCap:bufCap]); err != nil {
|
||||||
|
log.Println("[ERROR] failed to copy buffer: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// onExitFlushLoop is a callback set by tests to detect the state of the
|
// onExitFlushLoop is a callback set by tests to detect the state of the
|
||||||
|
@ -132,12 +135,12 @@ func (rp *ReverseProxy) srvDialerFunc(locator string, timeout time.Duration) fun
|
||||||
}
|
}
|
||||||
|
|
||||||
func singleJoiningSlash(a, b string) string {
|
func singleJoiningSlash(a, b string) string {
|
||||||
aslash := strings.HasSuffix(a, "/")
|
aSlash := strings.HasSuffix(a, "/")
|
||||||
bslash := strings.HasPrefix(b, "/")
|
bSlash := strings.HasPrefix(b, "/")
|
||||||
switch {
|
switch {
|
||||||
case aslash && bslash:
|
case aSlash && bSlash:
|
||||||
return a + b[1:]
|
return a + b[1:]
|
||||||
case !aslash && !bslash && b != "":
|
case !aSlash && !bSlash && b != "":
|
||||||
return a + "/" + b
|
return a + "/" + b
|
||||||
}
|
}
|
||||||
return a + b
|
return a + b
|
||||||
|
@ -275,7 +278,9 @@ func NewSingleHostReverseProxy(target *url.URL, without string, keepalive int, t
|
||||||
transport.MaxIdleConnsPerHost = keepalive
|
transport.MaxIdleConnsPerHost = keepalive
|
||||||
}
|
}
|
||||||
if httpserver.HTTP2 {
|
if httpserver.HTTP2 {
|
||||||
http2.ConfigureTransport(transport)
|
if err := http2.ConfigureTransport(transport); err != nil {
|
||||||
|
log.Println("[ERROR] failed to configure transport to use HTTP/2: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rp.Transport = transport
|
rp.Transport = transport
|
||||||
} else {
|
} else {
|
||||||
|
@ -284,7 +289,9 @@ func NewSingleHostReverseProxy(target *url.URL, without string, keepalive int, t
|
||||||
Dial: rp.dialer.Dial,
|
Dial: rp.dialer.Dial,
|
||||||
}
|
}
|
||||||
if httpserver.HTTP2 {
|
if httpserver.HTTP2 {
|
||||||
http2.ConfigureTransport(transport)
|
if err := http2.ConfigureTransport(transport); err != nil {
|
||||||
|
log.Println("[ERROR] failed to configure transport to use HTTP/2: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rp.Transport = transport
|
rp.Transport = transport
|
||||||
}
|
}
|
||||||
|
@ -394,7 +401,9 @@ func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
outreq.Write(backendConn)
|
if err := outreq.Write(backendConn); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
defer backendConn.Close()
|
defer backendConn.Close()
|
||||||
|
|
||||||
|
@ -416,7 +425,9 @@ func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
backendConn.Write(rbuf)
|
if _, err := backendConn.Write(rbuf); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write data to connection: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -434,7 +445,7 @@ func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request,
|
||||||
bodyOpen := true
|
bodyOpen := true
|
||||||
closeBody := func() {
|
closeBody := func() {
|
||||||
if bodyOpen {
|
if bodyOpen {
|
||||||
res.Body.Close()
|
_ = res.Body.Close()
|
||||||
bodyOpen = false
|
bodyOpen = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -681,7 +692,7 @@ func getTransportDialTLS(t *http.Transport) func(network, addr string) (net.Conn
|
||||||
errc <- err
|
errc <- err
|
||||||
}()
|
}()
|
||||||
if err := <-errc; err != nil {
|
if err := <-errc; err != nil {
|
||||||
plainConn.Close()
|
_ = plainConn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !tlsClientConfig.InsecureSkipVerify {
|
if !tlsClientConfig.InsecureSkipVerify {
|
||||||
|
@ -690,7 +701,7 @@ func getTransportDialTLS(t *http.Transport) func(network, addr string) (net.Conn
|
||||||
hostname = stripPort(addr)
|
hostname = stripPort(addr)
|
||||||
}
|
}
|
||||||
if err := tlsConn.VerifyHostname(hostname); err != nil {
|
if err := tlsConn.VerifyHostname(hostname); err != nil {
|
||||||
plainConn.Close()
|
_ = plainConn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
@ -39,10 +40,14 @@ func setupTLSServer() {
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Path == "/test-path" {
|
if r.URL.Path == "/test-path" {
|
||||||
w.WriteHeader(expectedStatus)
|
w.WriteHeader(expectedStatus)
|
||||||
w.Write([]byte(expectedResponse))
|
if _, err := w.Write([]byte(expectedResponse)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(404)
|
w.WriteHeader(404)
|
||||||
w.Write([]byte("Not found"))
|
if _, err := w.Write([]byte("Not found")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -52,10 +57,14 @@ func setupTest() {
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Path == "/test-path" {
|
if r.URL.Path == "/test-path" {
|
||||||
w.WriteHeader(expectedStatus)
|
w.WriteHeader(expectedStatus)
|
||||||
w.Write([]byte(expectedResponse))
|
if _, err := w.Write([]byte(expectedResponse)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(404)
|
w.WriteHeader(404)
|
||||||
w.Write([]byte("Not found"))
|
if _, err := w.Write([]byte("Not found")); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/textproto"
|
"net/textproto"
|
||||||
|
@ -632,8 +633,10 @@ func (u *staticUpstream) healthCheck() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
io.Copy(ioutil.Discard, r.Body)
|
if _, err := io.Copy(ioutil.Discard, r.Body); err != nil {
|
||||||
r.Body.Close()
|
log.Println("[ERROR] failed to copy: ", err)
|
||||||
|
}
|
||||||
|
_ = r.Body.Close()
|
||||||
}()
|
}()
|
||||||
if r.StatusCode < 200 || r.StatusCode >= 400 {
|
if r.StatusCode < 200 || r.StatusCode >= 400 {
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
@ -249,7 +250,9 @@ func TestParseBlockHealthCheck(t *testing.T) {
|
||||||
u := staticUpstream{}
|
u := staticUpstream{}
|
||||||
c := caddyfile.NewDispenser("Testfile", strings.NewReader(test.config))
|
c := caddyfile.NewDispenser("Testfile", strings.NewReader(test.config))
|
||||||
for c.Next() {
|
for c.Next() {
|
||||||
parseBlock(&c, &u, false)
|
if err := parseBlock(&c, &u, false); err != nil {
|
||||||
|
log.Println("[ERROR] failed to parse block: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if u.HealthCheck.Interval.String() != test.interval {
|
if u.HealthCheck.Interval.String() != test.interval {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
|
@ -300,7 +303,7 @@ func TestStop(t *testing.T) {
|
||||||
// Set up proxy.
|
// Set up proxy.
|
||||||
var counter int64
|
var counter int64
|
||||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
r.Body.Close()
|
_ = r.Body.Close()
|
||||||
atomic.AddInt64(&counter, 1)
|
atomic.AddInt64(&counter, 1)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -522,7 +525,7 @@ func TestHealthCheckPort(t *testing.T) {
|
||||||
var counter int64
|
var counter int64
|
||||||
|
|
||||||
healthCounter := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
healthCounter := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
r.Body.Close()
|
_ = r.Body.Close()
|
||||||
atomic.AddInt64(&counter, 1)
|
atomic.AddInt64(&counter, 1)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -592,8 +595,8 @@ func TestHealthCheckPort(t *testing.T) {
|
||||||
|
|
||||||
func TestHealthCheckContentString(t *testing.T) {
|
func TestHealthCheckContentString(t *testing.T) {
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintf(w, "blablabla good blablabla")
|
_, _ = fmt.Fprintf(w, "blablabla good blablabla")
|
||||||
r.Body.Close()
|
_ = r.Body.Close()
|
||||||
}))
|
}))
|
||||||
_, port, err := net.SplitHostPort(server.Listener.Addr().String())
|
_, port, err := net.SplitHostPort(server.Listener.Addr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -638,7 +641,9 @@ func TestHealthCheckContentString(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Errorf("Health check bad response")
|
t.Errorf("Health check bad response")
|
||||||
}
|
}
|
||||||
upstream.Stop()
|
if err := upstream.Stop(); err != nil {
|
||||||
|
log.Println("[ERROR] failed to stop upstream: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package push
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
|
@ -67,7 +68,9 @@ func TestMiddlewareWillPushResources(t *testing.T) {
|
||||||
pushingWriter := &MockedPusher{ResponseWriter: writer}
|
pushingWriter := &MockedPusher{ResponseWriter: writer}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
middleware.ServeHTTP(pushingWriter, request)
|
if _, err := middleware.ServeHTTP(pushingWriter, request); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expectedPushedResources := map[string]*http.PushOptions{
|
expectedPushedResources := map[string]*http.PushOptions{
|
||||||
|
@ -111,7 +114,9 @@ func TestMiddlewareWillPushResourcesWithMergedHeaders(t *testing.T) {
|
||||||
pushingWriter := &MockedPusher{ResponseWriter: writer}
|
pushingWriter := &MockedPusher{ResponseWriter: writer}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
middleware.ServeHTTP(pushingWriter, request)
|
if _, err := middleware.ServeHTTP(pushingWriter, request); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expectedPushedResources := map[string]*http.PushOptions{
|
expectedPushedResources := map[string]*http.PushOptions{
|
||||||
|
@ -156,7 +161,9 @@ func TestMiddlewareShouldntDoRecursivePush(t *testing.T) {
|
||||||
pushingWriter := &MockedPusher{ResponseWriter: writer}
|
pushingWriter := &MockedPusher{ResponseWriter: writer}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
middleware.ServeHTTP(pushingWriter, request)
|
if _, err := middleware.ServeHTTP(pushingWriter, request); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
// then
|
// then
|
||||||
if len(pushingWriter.pushed) > 0 {
|
if len(pushingWriter.pushed) > 0 {
|
||||||
|
@ -190,7 +197,9 @@ func TestMiddlewareShouldStopPushingOnError(t *testing.T) {
|
||||||
pushingWriter := &MockedPusher{ResponseWriter: writer, returnedError: errors.New("Cannot push right now")}
|
pushingWriter := &MockedPusher{ResponseWriter: writer, returnedError: errors.New("Cannot push right now")}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
middleware.ServeHTTP(pushingWriter, request)
|
if _, err := middleware.ServeHTTP(pushingWriter, request); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expectedPushedResources := map[string]*http.PushOptions{
|
expectedPushedResources := map[string]*http.PushOptions{
|
||||||
|
@ -406,7 +415,7 @@ func TestMiddlewareShouldPushIndexFile(t *testing.T) {
|
||||||
|
|
||||||
pushingWriter := &MockedPusher{
|
pushingWriter := &MockedPusher{
|
||||||
ResponseWriter: httptest.NewRecorder(),
|
ResponseWriter: httptest.NewRecorder(),
|
||||||
returnedError: errors.New("Cannot push right now"),
|
returnedError: errors.New("cannot push right now"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
@ -461,7 +470,7 @@ func TestMiddlewareShouldNotPushIndexFileWhenNotARule(t *testing.T) {
|
||||||
|
|
||||||
pushingWriter := &MockedPusher{
|
pushingWriter := &MockedPusher{
|
||||||
ResponseWriter: httptest.NewRecorder(),
|
ResponseWriter: httptest.NewRecorder(),
|
||||||
returnedError: errors.New("Cannot push right now"),
|
returnedError: errors.New("cannot push right now"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -84,7 +85,9 @@ func TestRedirect(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
re.ServeHTTP(rec, req)
|
if _, err := re.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if rec.Header().Get("Location") != test.expectedLocation {
|
if rec.Header().Get("Location") != test.expectedLocation {
|
||||||
t.Errorf("Test %d: Expected Location header to be %q but was %q",
|
t.Errorf("Test %d: Expected Location header to be %q but was %q",
|
||||||
|
@ -117,7 +120,9 @@ func TestParametersRedirect(t *testing.T) {
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
re.ServeHTTP(rec, req)
|
if _, err := re.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if got, want := rec.Header().Get("Location"), "http://example.com/a?b=c"; got != want {
|
if got, want := rec.Header().Get("Location"), "http://example.com/a?b=c"; got != want {
|
||||||
t.Fatalf("Test 1: expected location header %s but was %s", want, got)
|
t.Fatalf("Test 1: expected location header %s but was %s", want, got)
|
||||||
|
@ -136,7 +141,9 @@ func TestParametersRedirect(t *testing.T) {
|
||||||
ctx = context.WithValue(req.Context(), httpserver.OriginalURLCtxKey, *req.URL)
|
ctx = context.WithValue(req.Context(), httpserver.OriginalURLCtxKey, *req.URL)
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
re.ServeHTTP(rec, req)
|
if _, err := re.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if got, want := rec.Header().Get("Location"), "http://example.com/a/d?b=c&e=f"; got != want {
|
if got, want := rec.Header().Get("Location"), "http://example.com/a/d?b=c&e=f"; got != want {
|
||||||
t.Fatalf("Test 2: expected location header %s but was %s", want, got)
|
t.Fatalf("Test 2: expected location header %s but was %s", want, got)
|
||||||
|
@ -158,7 +165,9 @@ func TestMetaRedirect(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
re.ServeHTTP(rec, req)
|
if _, err := re.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(rec.Body)
|
body, err := ioutil.ReadAll(rec.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package requestid
|
package requestid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -39,7 +40,9 @@ func TestRequestIDHandler(t *testing.T) {
|
||||||
}
|
}
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
handler.ServeHTTP(rec, req)
|
if _, err := handler.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRequestIDFromHeader(t *testing.T) {
|
func TestRequestIDFromHeader(t *testing.T) {
|
||||||
|
@ -63,5 +66,7 @@ func TestRequestIDFromHeader(t *testing.T) {
|
||||||
req.Header.Set(headerName, headerValue)
|
req.Header.Set(headerName, headerValue)
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
handler.ServeHTTP(rec, req)
|
if _, err := handler.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package rewrite
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -123,7 +124,9 @@ func TestRewrite(t *testing.T) {
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
rw.ServeHTTP(rec, req)
|
if _, err := rw.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if got, want := rec.Body.String(), test.expectedTo; got != want {
|
if got, want := rec.Body.String(), test.expectedTo; got != want {
|
||||||
t.Errorf("Test %d: Expected URL to be '%s' but was '%s'", i, want, got)
|
t.Errorf("Test %d: Expected URL to be '%s' but was '%s'", i, want, got)
|
||||||
|
@ -162,7 +165,9 @@ func TestWordpress(t *testing.T) {
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
rw.ServeHTTP(rec, req)
|
if _, err := rw.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if got, want := rec.Body.String(), test.expectedTo; got != want {
|
if got, want := rec.Body.String(), test.expectedTo; got != want {
|
||||||
t.Errorf("Test %d: Expected URL to be '%s' but was '%s'", i, want, got)
|
t.Errorf("Test %d: Expected URL to be '%s' but was '%s'", i, want, got)
|
||||||
|
@ -171,6 +176,6 @@ func TestWordpress(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func urlPrinter(w http.ResponseWriter, r *http.Request) (int, error) {
|
func urlPrinter(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
fmt.Fprint(w, r.URL.String())
|
_, _ = fmt.Fprint(w, r.URL.String())
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
|
@ -35,7 +36,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
tmpWebRootDir := beforeServeHTTPTest(t)
|
tmpWebRootDir := beforeServeHTTPTest(t)
|
||||||
defer afterServeHTTPTest(t, tmpWebRootDir)
|
defer afterServeHTTPTest(t, tmpWebRootDir)
|
||||||
|
|
||||||
fileserver := FileServer{
|
fileServer := FileServer{
|
||||||
Root: http.Dir(filepath.Join(tmpWebRootDir, webrootName)),
|
Root: http.Dir(filepath.Join(tmpWebRootDir, webrootName)),
|
||||||
Hide: []string{"dir/hidden.html"},
|
Hide: []string{"dir/hidden.html"},
|
||||||
IndexPages: DefaultIndexPages,
|
IndexPages: DefaultIndexPages,
|
||||||
|
@ -288,7 +289,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform the test
|
// perform the test
|
||||||
status, err := fileserver.ServeHTTP(responseRecorder, request)
|
status, err := fileServer.ServeHTTP(responseRecorder, request)
|
||||||
etag := responseRecorder.Header().Get("Etag")
|
etag := responseRecorder.Header().Get("Etag")
|
||||||
body := responseRecorder.Body.String()
|
body := responseRecorder.Body.String()
|
||||||
vary := responseRecorder.Header().Get("Vary")
|
vary := responseRecorder.Header().Get("Vary")
|
||||||
|
@ -357,7 +358,9 @@ func beforeServeHTTPTest(t *testing.T) string {
|
||||||
parentDir := filepath.Dir(absFile)
|
parentDir := filepath.Dir(absFile)
|
||||||
_, err = os.Stat(parentDir)
|
_, err = os.Stat(parentDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.MkdirAll(parentDir, os.ModePerm)
|
if err := os.MkdirAll(parentDir, os.ModePerm); err != nil {
|
||||||
|
log.Println("[ERROR] MkdirAll failed: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now create the test files
|
// now create the test files
|
||||||
|
@ -371,7 +374,7 @@ func beforeServeHTTPTest(t *testing.T) string {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to write to %s. Error was: %v", absFile, err)
|
t.Fatalf("Failed to write to %s. Error was: %v", absFile, err)
|
||||||
}
|
}
|
||||||
f.Close()
|
_ = f.Close()
|
||||||
|
|
||||||
// and set the last modified time
|
// and set the last modified time
|
||||||
err = os.Chtimes(absFile, fixedTime, fixedTime)
|
err = os.Chtimes(absFile, fixedTime, fixedTime)
|
||||||
|
@ -511,7 +514,7 @@ func TestServeHTTPFailingStat(t *testing.T) {
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
// initialize a file server. The FileSystem will not fail, but calls to the Stat method of the returned File object will
|
// initialize a file server. The FileSystem will not fail, but calls to the Stat method of the returned File object will
|
||||||
fileserver := FileServer{Root: failingFS{err: nil, fileImpl: failingFile{err: test.statErr}}}
|
fileServer := FileServer{Root: failingFS{err: nil, fileImpl: failingFile{err: test.statErr}}}
|
||||||
|
|
||||||
// prepare the request and response
|
// prepare the request and response
|
||||||
request, err := http.NewRequest("GET", "https://foo/", nil)
|
request, err := http.NewRequest("GET", "https://foo/", nil)
|
||||||
|
@ -520,7 +523,7 @@ func TestServeHTTPFailingStat(t *testing.T) {
|
||||||
}
|
}
|
||||||
responseRecorder := httptest.NewRecorder()
|
responseRecorder := httptest.NewRecorder()
|
||||||
|
|
||||||
status, actualErr := fileserver.ServeHTTP(responseRecorder, request)
|
status, actualErr := fileServer.ServeHTTP(responseRecorder, request)
|
||||||
|
|
||||||
// check the status
|
// check the status
|
||||||
if status != test.expectedStatus {
|
if status != test.expectedStatus {
|
||||||
|
|
|
@ -17,6 +17,7 @@ package templates
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -127,7 +128,9 @@ func TestTemplates(t *testing.T) {
|
||||||
|
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
c.tpl.ServeHTTP(rec, req)
|
if _, err := c.tpl.ServeHTTP(rec, req); err != nil {
|
||||||
|
log.Println("[ERROR] failed to serve HTTP: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
if rec.Code != c.respCode {
|
if rec.Code != c.respCode {
|
||||||
t.Fatalf("Test: Wrong response code: %d, should be %d", rec.Code, c.respCode)
|
t.Fatalf("Test: Wrong response code: %d, should be %d", rec.Code, c.respCode)
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
@ -80,9 +81,9 @@ type (
|
||||||
|
|
||||||
// ServeHTTP converts the HTTP request to a WebSocket connection and serves it up.
|
// ServeHTTP converts the HTTP request to a WebSocket connection and serves it up.
|
||||||
func (ws WebSocket) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
func (ws WebSocket) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
for _, sockconfig := range ws.Sockets {
|
for _, sockConfig := range ws.Sockets {
|
||||||
if httpserver.Path(r.URL.Path).Matches(sockconfig.Path) {
|
if httpserver.Path(r.URL.Path).Matches(sockConfig.Path) {
|
||||||
return serveWS(w, r, &sockconfig)
|
return serveWS(w, r, &sockConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +136,7 @@ func serveWS(w http.ResponseWriter, r *http.Request, config *Config) (int, error
|
||||||
go pumpStdout(conn, stdout, done)
|
go pumpStdout(conn, stdout, done)
|
||||||
pumpStdin(conn, stdin)
|
pumpStdin(conn, stdin)
|
||||||
|
|
||||||
stdin.Close() // close stdin to end the process
|
_ = stdin.Close() // close stdin to end the process
|
||||||
|
|
||||||
if err := cmd.Process.Signal(os.Interrupt); err != nil { // signal an interrupt to kill the process
|
if err := cmd.Process.Signal(os.Interrupt); err != nil { // signal an interrupt to kill the process
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
|
@ -155,7 +156,9 @@ func serveWS(w http.ResponseWriter, r *http.Request, config *Config) (int, error
|
||||||
// status for an "exited" process is greater
|
// status for an "exited" process is greater
|
||||||
// than 0, but isn't really an error per se.
|
// than 0, but isn't really an error per se.
|
||||||
// just going to ignore it for now.
|
// just going to ignore it for now.
|
||||||
cmd.Wait()
|
if err := cmd.Wait(); err != nil {
|
||||||
|
log.Println("[ERROR] failed to release resources: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
@ -221,8 +224,15 @@ func pumpStdin(conn *websocket.Conn, stdin io.WriteCloser) {
|
||||||
// Setup our connection's websocket ping/pong handlers from our const values.
|
// Setup our connection's websocket ping/pong handlers from our const values.
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
conn.SetReadLimit(maxMessageSize)
|
conn.SetReadLimit(maxMessageSize)
|
||||||
conn.SetReadDeadline(time.Now().Add(pongWait))
|
if err := conn.SetReadDeadline(time.Now().Add(pongWait)); err != nil {
|
||||||
conn.SetPongHandler(func(string) error { conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
log.Println("[ERROR] failed to set read deadline: ", err)
|
||||||
|
}
|
||||||
|
conn.SetPongHandler(func(string) error {
|
||||||
|
if err := conn.SetReadDeadline(time.Now().Add(pongWait)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to set read deadline: ", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
for {
|
for {
|
||||||
_, message, err := conn.ReadMessage()
|
_, message, err := conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -240,19 +250,24 @@ func pumpStdin(conn *websocket.Conn, stdin io.WriteCloser) {
|
||||||
func pumpStdout(conn *websocket.Conn, stdout io.Reader, done chan struct{}) {
|
func pumpStdout(conn *websocket.Conn, stdout io.Reader, done chan struct{}) {
|
||||||
go pinger(conn, done)
|
go pinger(conn, done)
|
||||||
defer func() {
|
defer func() {
|
||||||
conn.Close()
|
_ = conn.Close()
|
||||||
close(done) // make sure to close the pinger when we are done.
|
close(done) // make sure to close the pinger when we are done.
|
||||||
}()
|
}()
|
||||||
|
|
||||||
s := bufio.NewScanner(stdout)
|
s := bufio.NewScanner(stdout)
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
conn.SetWriteDeadline(time.Now().Add(writeWait))
|
if err := conn.SetWriteDeadline(time.Now().Add(writeWait)); err != nil {
|
||||||
|
log.Println("[ERROR] failed to set write deadline: ", err)
|
||||||
|
}
|
||||||
if err := conn.WriteMessage(websocket.TextMessage, bytes.TrimSpace(s.Bytes())); err != nil {
|
if err := conn.WriteMessage(websocket.TextMessage, bytes.TrimSpace(s.Bytes())); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.Err() != nil {
|
if s.Err() != nil {
|
||||||
conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseGoingAway, s.Err().Error()), time.Time{})
|
err := conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseGoingAway, s.Err().Error()), time.Time{})
|
||||||
|
if err != nil {
|
||||||
|
log.Println("[ERROR] WriteControl failed: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +280,10 @@ func pinger(conn *websocket.Conn, done chan struct{}) {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
if err := conn.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(writeWait)); err != nil {
|
if err := conn.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(writeWait)); err != nil {
|
||||||
conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseGoingAway, err.Error()), time.Time{})
|
err := conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseGoingAway, err.Error()), time.Time{})
|
||||||
|
if err != nil {
|
||||||
|
log.Println("[ERROR] WriteControl failed: ", err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case <-done:
|
case <-done:
|
||||||
|
|
|
@ -36,7 +36,9 @@ import (
|
||||||
func init() {
|
func init() {
|
||||||
// opt-in TLS 1.3 for Go1.12
|
// opt-in TLS 1.3 for Go1.12
|
||||||
// TODO: remove this line when Go1.13 is released.
|
// TODO: remove this line when Go1.13 is released.
|
||||||
os.Setenv("GODEBUG", os.Getenv("GODEBUG")+",tls13=1")
|
if err := os.Setenv("GODEBUG", os.Getenv("GODEBUG")+",tls13=1"); err != nil {
|
||||||
|
log.Println("[ERROR] failed to set environment variable: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
caddy.RegisterPlugin("tls", caddy.Plugin{Action: setupTLS})
|
caddy.RegisterPlugin("tls", caddy.Plugin{Action: setupTLS})
|
||||||
|
|
||||||
|
@ -409,26 +411,34 @@ func loadCertsInDir(cfg *Config, c *caddy.Controller, dir string) error {
|
||||||
|
|
||||||
if derBlock.Type == "CERTIFICATE" {
|
if derBlock.Type == "CERTIFICATE" {
|
||||||
// Re-encode certificate as PEM, appending to certificate chain
|
// Re-encode certificate as PEM, appending to certificate chain
|
||||||
pem.Encode(certBuilder, derBlock)
|
if err := pem.Encode(certBuilder, derBlock); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write PEM encoding: ", err)
|
||||||
|
}
|
||||||
} else if derBlock.Type == "EC PARAMETERS" {
|
} else if derBlock.Type == "EC PARAMETERS" {
|
||||||
// EC keys generated from openssl can be composed of two blocks:
|
// EC keys generated from openssl can be composed of two blocks:
|
||||||
// parameters and key (parameter block should come first)
|
// parameters and key (parameter block should come first)
|
||||||
if !foundKey {
|
if !foundKey {
|
||||||
// Encode parameters
|
// Encode parameters
|
||||||
pem.Encode(keyBuilder, derBlock)
|
if err := pem.Encode(keyBuilder, derBlock); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write PEM encoding: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Key must immediately follow
|
// Key must immediately follow
|
||||||
derBlock, bundle = pem.Decode(bundle)
|
derBlock, bundle = pem.Decode(bundle)
|
||||||
if derBlock == nil || derBlock.Type != "EC PRIVATE KEY" {
|
if derBlock == nil || derBlock.Type != "EC PRIVATE KEY" {
|
||||||
return c.Errf("%s: expected elliptic private key to immediately follow EC parameters", path)
|
return c.Errf("%s: expected elliptic private key to immediately follow EC parameters", path)
|
||||||
}
|
}
|
||||||
pem.Encode(keyBuilder, derBlock)
|
if err := pem.Encode(keyBuilder, derBlock); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write PEM encoding: ", err)
|
||||||
|
}
|
||||||
foundKey = true
|
foundKey = true
|
||||||
}
|
}
|
||||||
} else if derBlock.Type == "PRIVATE KEY" || strings.HasSuffix(derBlock.Type, " PRIVATE KEY") {
|
} else if derBlock.Type == "PRIVATE KEY" || strings.HasSuffix(derBlock.Type, " PRIVATE KEY") {
|
||||||
// RSA key
|
// RSA key
|
||||||
if !foundKey {
|
if !foundKey {
|
||||||
pem.Encode(keyBuilder, derBlock)
|
if err := pem.Encode(keyBuilder, derBlock); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write PEM encoding: ", err)
|
||||||
|
}
|
||||||
foundKey = true
|
foundKey = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -283,7 +283,10 @@ func atomicAdd(key string, amount int) {
|
||||||
// Do not use this for cryptographic purposes.
|
// Do not use this for cryptographic purposes.
|
||||||
func FastHash(input []byte) string {
|
func FastHash(input []byte) string {
|
||||||
h := fnv.New32a()
|
h := fnv.New32a()
|
||||||
h.Write(input)
|
if _, err := h.Write(input); err != nil {
|
||||||
|
log.Println("[ERROR] failed to write bytes: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%x", h.Sum32())
|
return fmt.Sprintf("%x", h.Sum32())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue