github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/pkg/proxy/register_test.go (about)

     1  // +build integration
     2  
     3  package proxy
     4  
     5  import (
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"os"
    10  	"testing"
    11  
    12  	"github.com/hellofresh/stats-go/client"
    13  	log "github.com/sirupsen/logrus"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	"github.com/hellofresh/janus/pkg/router"
    18  	"github.com/hellofresh/janus/pkg/test"
    19  )
    20  
    21  const defaultUpstreamsPort = "9089"
    22  
    23  var tests = []struct {
    24  	description         string
    25  	method              string
    26  	url                 string
    27  	expectedContentType string
    28  	expectedCode        int
    29  }{
    30  	{
    31  		description:         "Get example route",
    32  		method:              "GET",
    33  		url:                 "/example",
    34  		expectedContentType: "application/json; charset=utf-8",
    35  		expectedCode:        http.StatusOK,
    36  	}, {
    37  		description:         "Get invalid route",
    38  		method:              "GET",
    39  		url:                 "/invalid-route",
    40  		expectedContentType: "text/plain; charset=utf-8",
    41  		expectedCode:        http.StatusNotFound,
    42  	},
    43  	{
    44  		description:         "Get one posts - strip path",
    45  		method:              "GET",
    46  		url:                 "/posts/1",
    47  		expectedContentType: "application/json; charset=utf-8",
    48  		expectedCode:        http.StatusOK,
    49  	},
    50  	{
    51  		description:         "Get one posts - append path",
    52  		method:              "GET",
    53  		url:                 "/append",
    54  		expectedContentType: "application/json; charset=utf-8",
    55  		expectedCode:        http.StatusOK,
    56  	},
    57  	{
    58  		description:         "Get one recipe - parameter interpolation",
    59  		url:                 "/api/recipes/5252b1b5301bbf46038b473f",
    60  		expectedContentType: "application/json; charset=utf-8",
    61  		expectedCode:        http.StatusOK,
    62  	},
    63  	{
    64  		description:         "No parameter to interpolate",
    65  		url:                 "/api/recipes/search",
    66  		expectedContentType: "application/json",
    67  		expectedCode:        http.StatusNotFound,
    68  	},
    69  	{
    70  		description:         "named param with strip path to posts",
    71  		method:              "GET",
    72  		url:                 "/private/localhost/posts/1",
    73  		expectedContentType: "application/json; charset=utf-8",
    74  		expectedCode:        http.StatusOK,
    75  	},
    76  	{
    77  		description:         "named param with strip path - no api",
    78  		method:              "GET",
    79  		url:                 "/private/localhost/no-api",
    80  		expectedContentType: "application/json",
    81  		expectedCode:        http.StatusNotFound,
    82  	},
    83  }
    84  
    85  func TestSuccessfulProxy(t *testing.T) {
    86  	t.Parallel()
    87  
    88  	log.SetOutput(ioutil.Discard)
    89  
    90  	ts := test.NewServer(createRegisterAndRouter(t))
    91  	defer ts.Close()
    92  
    93  	for _, tc := range tests {
    94  		t.Run(tc.description, func(t *testing.T) {
    95  			res, err := ts.Do(tc.method, tc.url, make(map[string]string))
    96  			require.NoError(t, err)
    97  			t.Cleanup(func() {
    98  				err := res.Body.Close()
    99  				assert.NoError(t, err)
   100  			})
   101  
   102  			assert.Equal(t, tc.expectedContentType, res.Header.Get("Content-Type"), tc.description)
   103  			assert.Equal(t, tc.expectedCode, res.StatusCode, tc.description)
   104  		})
   105  	}
   106  }
   107  
   108  func createProxyDefinitions(t *testing.T) []*Definition {
   109  	t.Helper()
   110  
   111  	upstreamsPort := os.Getenv("DYNAMIC_UPSTREAMS_PORT")
   112  	if upstreamsPort == "" {
   113  		upstreamsPort = defaultUpstreamsPort
   114  	}
   115  
   116  	return []*Definition{
   117  		{
   118  			ListenPath: "/example/*",
   119  			Upstreams: &Upstreams{
   120  				Balancing: "roundrobin",
   121  				Targets:   []*Target{{Target: fmt.Sprintf("http://localhost:%s/hello-world", upstreamsPort)}},
   122  			},
   123  			Methods: []string{"ALL"},
   124  		},
   125  		{
   126  			ListenPath: "/posts/*",
   127  			StripPath:  true,
   128  			Upstreams: &Upstreams{
   129  				Balancing: "roundrobin",
   130  				Targets:   []*Target{{Target: fmt.Sprintf("http://localhost:%s/posts", upstreamsPort)}},
   131  			},
   132  			Methods: []string{"ALL"},
   133  		},
   134  		{
   135  			ListenPath: "/append/*",
   136  			Upstreams: &Upstreams{
   137  				Balancing: "roundrobin",
   138  				Targets:   []*Target{{Target: fmt.Sprintf("http://localhost:%s/hello-world", upstreamsPort)}},
   139  			},
   140  			AppendPath: true,
   141  			Methods:    []string{"GET"},
   142  		},
   143  		{
   144  			ListenPath: "/api/recipes/{id:[\\da-f]{24}}",
   145  			Upstreams: &Upstreams{
   146  				Balancing: "roundrobin",
   147  				Targets:   []*Target{{Target: fmt.Sprintf("http://localhost:%s/recipes/{id}", upstreamsPort)}},
   148  			},
   149  			Methods: []string{"GET"},
   150  		},
   151  		{
   152  			ListenPath: "/api/recipes/search",
   153  			Upstreams: &Upstreams{
   154  				Balancing: "roundrobin",
   155  				Targets:   []*Target{{Target: fmt.Sprintf("http://localhost:%s/recipes/{id}", upstreamsPort)}},
   156  			},
   157  			Methods: []string{"GET"},
   158  		},
   159  		{
   160  			ListenPath: "/private/{service}/*",
   161  			Upstreams: &Upstreams{
   162  				Balancing: "roundrobin",
   163  				Targets:   []*Target{{Target: fmt.Sprintf("http://{service}:%s/", upstreamsPort)}},
   164  			},
   165  			StripPath: true,
   166  			Methods: []string{"ALL"},
   167  		},
   168  	}
   169  }
   170  
   171  func createRegisterAndRouter(t *testing.T) router.Router {
   172  	t.Helper()
   173  
   174  	r := router.NewChiRouter()
   175  	createRegister(t, r)
   176  	return r
   177  }
   178  
   179  func createRegister(t *testing.T, r router.Router) *Register {
   180  	t.Helper()
   181  
   182  	register := NewRegister(WithRouter(r), WithStatsClient(client.NewNoop()))
   183  
   184  	definitions := createProxyDefinitions(t)
   185  	for _, def := range definitions {
   186  		err := register.Add(NewRouterDefinition(def))
   187  		require.NoError(t, err)
   188  	}
   189  
   190  	return register
   191  }