mirror of
https://github.com/umputun/reproxy.git
synced 2024-09-11 17:07:19 +03:00
* wip * resolve merge artifacts * full coverage for conductor * wire plugin conductor to main and proxy * wip, with separate match handler * split matching logic with another handler, add initial docs * move parts of proxy to handlers, add tests * add headers in to be sent to proxied url * merged from master * add example with docker compose * supress excesive debug reporting 0-9 disabled in docker * add plugin tests * randomize test port * lint: minor warns * lint: err shadow
86 lines
2.4 KiB
Go
86 lines
2.4 KiB
Go
package lib
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
log "github.com/go-pkgz/lgr"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestPlugin_Do(t *testing.T) {
|
|
|
|
var postCalls int32
|
|
var deleteCalls int32
|
|
tsConductor := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
case "POST":
|
|
atomic.AddInt32(&postCalls, 1)
|
|
case "DELETE":
|
|
atomic.AddInt32(&deleteCalls, 1)
|
|
default:
|
|
t.Fatalf("unexpected method %s", r.Method)
|
|
}
|
|
t.Logf("registration: %+v", r)
|
|
}))
|
|
defer tsConductor.Close()
|
|
|
|
u, err := url.Parse(tsConductor.URL)
|
|
require.NoError(t, err)
|
|
p := Plugin{Name: "Test1", Address: "localhost:12345", Methods: []string{"H1", "H2"}}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
err = p.Do(ctx, "http://"+u.Host, new(TestingHandler))
|
|
assert.EqualError(t, err, "context deadline exceeded")
|
|
assert.Equal(t, int32(1), atomic.LoadInt32(&postCalls))
|
|
assert.Equal(t, int32(1), atomic.LoadInt32(&deleteCalls))
|
|
}
|
|
|
|
func TestPlugin_DoFailed(t *testing.T) {
|
|
tsConductor := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(500)
|
|
}))
|
|
defer tsConductor.Close()
|
|
|
|
u, err := url.Parse(tsConductor.URL)
|
|
require.NoError(t, err)
|
|
p := Plugin{Name: "Test2", Address: "localhost:12345", Methods: []string{"H1", "H2"}}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
err = p.Do(ctx, "http://"+u.Host, new(TestingHandler))
|
|
assert.EqualError(t, err, "context canceled")
|
|
}
|
|
|
|
// TestingHandler is an example of middleware handler altering headers and stastus
|
|
type TestingHandler struct{}
|
|
|
|
// HeaderThing adds key:val header to the response
|
|
func (h *TestingHandler) H1(req Request, res *Response) (err error) {
|
|
log.Printf("req: %+v", req)
|
|
res.HeadersOut = http.Header{}
|
|
res.HeadersOut.Add("key", "val")
|
|
res.HeadersIn = http.Header{}
|
|
res.HeadersIn.Add("token", "something")
|
|
res.StatusCode = 200 // each handler has to set status code
|
|
return
|
|
}
|
|
|
|
// ErrorThing returns status 500 on "/fail" url. This terminated processing chain on reproxy side immediately
|
|
func (h *TestingHandler) H2(req Request, res *Response) (err error) {
|
|
log.Printf("req: %+v", req)
|
|
if req.URL == "/fail" {
|
|
res.StatusCode = 500
|
|
return
|
|
}
|
|
res.StatusCode = 200
|
|
return
|
|
}
|