/caddytest/integration/reverseproxy_test.go
https://gitlab.com/caddy/caddy · Go · 491 lines · 460 code · 28 blank · 3 comment · 29 complexity · c4c0f35af82ad2f0e6f3ded61a1bcb7f MD5 · raw file
- package integration
- import (
- "fmt"
- "net"
- "net/http"
- "os"
- "runtime"
- "strings"
- "testing"
- "github.com/caddyserver/caddy/v2/caddytest"
- )
- func TestSRVReverseProxy(t *testing.T) {
- tester := caddytest.NewTester(t)
- tester.InitServer(`
- {
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":8080"
- ],
- "routes": [
- {
- "handle": [
- {
- "handler": "reverse_proxy",
- "upstreams": [
- {
- "lookup_srv": "srv.host.service.consul"
- }
- ]
- }
- ]
- }
- ]
- }
- }
- }
- }
- }
- `, "json")
- }
- func TestSRVWithDial(t *testing.T) {
- caddytest.AssertLoadError(t, `
- {
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":8080"
- ],
- "routes": [
- {
- "handle": [
- {
- "handler": "reverse_proxy",
- "upstreams": [
- {
- "dial": "tcp/address.to.upstream:80",
- "lookup_srv": "srv.host.service.consul"
- }
- ]
- }
- ]
- }
- ]
- }
- }
- }
- }
- }
- `, "json", `upstream: specifying dial address is incompatible with lookup_srv: 0: {\"dial\": \"tcp/address.to.upstream:80\", \"lookup_srv\": \"srv.host.service.consul\"}`)
- }
- func TestDialWithPlaceholderUnix(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.SkipNow()
- }
- f, err := os.CreateTemp("", "*.sock")
- if err != nil {
- t.Errorf("failed to create TempFile: %s", err)
- return
- }
- // a hack to get a file name within a valid path to use as socket
- socketName := f.Name()
- os.Remove(f.Name())
- server := http.Server{
- Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- w.Write([]byte("Hello, World!"))
- }),
- }
- unixListener, err := net.Listen("unix", socketName)
- if err != nil {
- t.Errorf("failed to listen on the socket: %s", err)
- return
- }
- go server.Serve(unixListener)
- t.Cleanup(func() {
- server.Close()
- })
- runtime.Gosched() // Allow other goroutines to run
- tester := caddytest.NewTester(t)
- tester.InitServer(`
- {
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":8080"
- ],
- "routes": [
- {
- "handle": [
- {
- "handler": "reverse_proxy",
- "upstreams": [
- {
- "dial": "unix/{http.request.header.X-Caddy-Upstream-Dial}"
- }
- ]
- }
- ]
- }
- ]
- }
- }
- }
- }
- }
- `, "json")
- req, err := http.NewRequest(http.MethodGet, "http://localhost:8080", nil)
- if err != nil {
- t.Fail()
- return
- }
- req.Header.Set("X-Caddy-Upstream-Dial", socketName)
- tester.AssertResponse(req, 200, "Hello, World!")
- }
- func TestReverseProxyWithPlaceholderDialAddress(t *testing.T) {
- tester := caddytest.NewTester(t)
- tester.InitServer(`
- {
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":8080"
- ],
- "routes": [
- {
- "match": [
- {
- "host": [
- "localhost"
- ]
- }
- ],
- "handle": [
- {
- "handler": "static_response",
- "body": "Hello, World!"
- }
- ],
- "terminal": true
- }
- ],
- "automatic_https": {
- "skip": [
- "localhost"
- ]
- }
- },
- "srv1": {
- "listen": [
- ":9080"
- ],
- "routes": [
- {
- "match": [
- {
- "host": [
- "localhost"
- ]
- }
- ],
- "handle": [
- {
-
- "handler": "reverse_proxy",
- "upstreams": [
- {
- "dial": "{http.request.header.X-Caddy-Upstream-Dial}"
- }
- ]
- }
- ],
- "terminal": true
- }
- ],
- "automatic_https": {
- "skip": [
- "localhost"
- ]
- }
- }
- }
- }
- }
- }
- `, "json")
- req, err := http.NewRequest(http.MethodGet, "http://localhost:9080", nil)
- if err != nil {
- t.Fail()
- return
- }
- req.Header.Set("X-Caddy-Upstream-Dial", "localhost:8080")
- tester.AssertResponse(req, 200, "Hello, World!")
- }
- func TestReverseProxyWithPlaceholderTCPDialAddress(t *testing.T) {
- tester := caddytest.NewTester(t)
- tester.InitServer(`
- {
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":8080"
- ],
- "routes": [
- {
- "match": [
- {
- "host": [
- "localhost"
- ]
- }
- ],
- "handle": [
- {
- "handler": "static_response",
- "body": "Hello, World!"
- }
- ],
- "terminal": true
- }
- ],
- "automatic_https": {
- "skip": [
- "localhost"
- ]
- }
- },
- "srv1": {
- "listen": [
- ":9080"
- ],
- "routes": [
- {
- "match": [
- {
- "host": [
- "localhost"
- ]
- }
- ],
- "handle": [
- {
-
- "handler": "reverse_proxy",
- "upstreams": [
- {
- "dial": "tcp/{http.request.header.X-Caddy-Upstream-Dial}:8080"
- }
- ]
- }
- ],
- "terminal": true
- }
- ],
- "automatic_https": {
- "skip": [
- "localhost"
- ]
- }
- }
- }
- }
- }
- }
- `, "json")
- req, err := http.NewRequest(http.MethodGet, "http://localhost:9080", nil)
- if err != nil {
- t.Fail()
- return
- }
- req.Header.Set("X-Caddy-Upstream-Dial", "localhost")
- tester.AssertResponse(req, 200, "Hello, World!")
- }
- func TestSRVWithActiveHealthcheck(t *testing.T) {
- caddytest.AssertLoadError(t, `
- {
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":8080"
- ],
- "routes": [
- {
- "handle": [
- {
- "handler": "reverse_proxy",
- "health_checks": {
- "active": {
- "path": "/ok"
- }
- },
- "upstreams": [
- {
- "lookup_srv": "srv.host.service.consul"
- }
- ]
- }
- ]
- }
- ]
- }
- }
- }
- }
- }
- `, "json", `upstream: lookup_srv is incompatible with active health checks: 0: {\"dial\": \"\", \"lookup_srv\": \"srv.host.service.consul\"}`)
- }
- func TestReverseProxyHealthCheck(t *testing.T) {
- tester := caddytest.NewTester(t)
- tester.InitServer(`
- {
- http_port 9080
- https_port 9443
- }
- http://localhost:2020 {
- respond "Hello, World!"
- }
- http://localhost:2021 {
- respond "ok"
- }
- http://localhost:9080 {
- reverse_proxy {
- to localhost:2020
-
- health_uri /health
- health_port 2021
- health_interval 2s
- health_timeout 5s
- }
- }
- `, "caddyfile")
- tester.AssertGetResponse("http://localhost:9080/", 200, "Hello, World!")
- }
- func TestReverseProxyHealthCheckUnixSocket(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.SkipNow()
- }
- tester := caddytest.NewTester(t)
- f, err := os.CreateTemp("", "*.sock")
- if err != nil {
- t.Errorf("failed to create TempFile: %s", err)
- return
- }
- // a hack to get a file name within a valid path to use as socket
- socketName := f.Name()
- os.Remove(f.Name())
- server := http.Server{
- Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- if strings.HasPrefix(req.URL.Path, "/health") {
- w.Write([]byte("ok"))
- return
- }
- w.Write([]byte("Hello, World!"))
- }),
- }
- unixListener, err := net.Listen("unix", socketName)
- if err != nil {
- t.Errorf("failed to listen on the socket: %s", err)
- return
- }
- go server.Serve(unixListener)
- t.Cleanup(func() {
- server.Close()
- })
- runtime.Gosched() // Allow other goroutines to run
- tester.InitServer(fmt.Sprintf(`
- {
- http_port 9080
- https_port 9443
- }
- http://localhost:9080 {
- reverse_proxy {
- to unix/%s
-
- health_uri /health
- health_port 2021
- health_interval 2s
- health_timeout 5s
- }
- }
- `, socketName), "caddyfile")
- tester.AssertGetResponse("http://localhost:9080/", 200, "Hello, World!")
- }
- func TestReverseProxyHealthCheckUnixSocketWithoutPort(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.SkipNow()
- }
- tester := caddytest.NewTester(t)
- f, err := os.CreateTemp("", "*.sock")
- if err != nil {
- t.Errorf("failed to create TempFile: %s", err)
- return
- }
- // a hack to get a file name within a valid path to use as socket
- socketName := f.Name()
- os.Remove(f.Name())
- server := http.Server{
- Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- if strings.HasPrefix(req.URL.Path, "/health") {
- w.Write([]byte("ok"))
- return
- }
- w.Write([]byte("Hello, World!"))
- }),
- }
- unixListener, err := net.Listen("unix", socketName)
- if err != nil {
- t.Errorf("failed to listen on the socket: %s", err)
- return
- }
- go server.Serve(unixListener)
- t.Cleanup(func() {
- server.Close()
- })
- runtime.Gosched() // Allow other goroutines to run
- tester.InitServer(fmt.Sprintf(`
- {
- http_port 9080
- https_port 9443
- }
- http://localhost:9080 {
- reverse_proxy {
- to unix/%s
-
- health_uri /health
- health_interval 2s
- health_timeout 5s
- }
- }
- `, socketName), "caddyfile")
- tester.AssertGetResponse("http://localhost:9080/", 200, "Hello, World!")
- }