goyave.dev/goyave/v4@v4.4.11/request_test.go (about)

     1  package goyave
     2  
     3  import (
     4  	"net"
     5  	"net/http"
     6  	"net/http/httptest"
     7  	"net/url"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"goyave.dev/goyave/v4/cors"
    13  	"goyave.dev/goyave/v4/util/fsutil"
    14  
    15  	"github.com/google/uuid"
    16  	"github.com/stretchr/testify/assert"
    17  	"goyave.dev/goyave/v4/validation"
    18  )
    19  
    20  func createTestRequest(rawRequest *http.Request) *Request {
    21  	return &Request{
    22  		httpRequest: rawRequest,
    23  		Rules:       &validation.Rules{},
    24  		Params:      map[string]string{},
    25  	}
    26  }
    27  func TestRequestContentLength(t *testing.T) {
    28  	rawRequest := httptest.NewRequest("GET", "/test-route", strings.NewReader("body"))
    29  	request := createTestRequest(rawRequest)
    30  	assert.Equal(t, int64(4), request.ContentLength())
    31  }
    32  
    33  func TestRequestMethod(t *testing.T) {
    34  	rawRequest := httptest.NewRequest("GET", "/test-route", strings.NewReader("body"))
    35  	request := createTestRequest(rawRequest)
    36  	assert.Equal(t, "GET", request.Method())
    37  
    38  	rawRequest = httptest.NewRequest("POST", "/test-route", strings.NewReader("body"))
    39  	request = createTestRequest(rawRequest)
    40  	assert.Equal(t, "POST", request.Method())
    41  }
    42  
    43  func TestRequestRemoteAddress(t *testing.T) {
    44  	rawRequest := httptest.NewRequest("GET", "/test-route", strings.NewReader("body"))
    45  	request := createTestRequest(rawRequest)
    46  	assert.Equal(t, "192.0.2.1:1234", request.RemoteAddress())
    47  }
    48  
    49  func TestRequestProtocol(t *testing.T) {
    50  	rawRequest := httptest.NewRequest("GET", "/test-route", strings.NewReader("body"))
    51  	request := createTestRequest(rawRequest)
    52  	assert.Equal(t, "HTTP/1.1", request.Protocol())
    53  }
    54  
    55  func TestRequestURL(t *testing.T) {
    56  	rawRequest := httptest.NewRequest("GET", "/test-route", strings.NewReader("body"))
    57  	request := createTestRequest(rawRequest)
    58  	assert.Equal(t, "/test-route", request.URI().Path)
    59  }
    60  
    61  func TestRequestReferrer(t *testing.T) {
    62  	rawRequest := httptest.NewRequest("GET", "/test-route", strings.NewReader("body"))
    63  	rawRequest.Header.Set("Referer", "https://www.google.com")
    64  	request := createTestRequest(rawRequest)
    65  	assert.Equal(t, "https://www.google.com", request.Referrer())
    66  }
    67  
    68  func TestRequestUserAgent(t *testing.T) {
    69  	rawRequest := httptest.NewRequest("GET", "/test-route", strings.NewReader("body"))
    70  	rawRequest.Header.Set("User-Agent", "goyave/version")
    71  	request := createTestRequest(rawRequest)
    72  	assert.Equal(t, "goyave/version", request.UserAgent())
    73  }
    74  
    75  func TestRequestCookies(t *testing.T) {
    76  	rawRequest := httptest.NewRequest("GET", "/test-route", strings.NewReader("body"))
    77  	rawRequest.AddCookie(&http.Cookie{
    78  		Name:  "cookie-name",
    79  		Value: "test",
    80  	})
    81  	request := createTestRequest(rawRequest)
    82  	cookies := request.Cookies()
    83  	assert.Equal(t, 1, len(cookies))
    84  	assert.Equal(t, "cookie-name", cookies[0].Name)
    85  	assert.Equal(t, "test", cookies[0].Value)
    86  }
    87  
    88  func TestRequestValidate(t *testing.T) {
    89  	rawRequest := httptest.NewRequest("POST", "/test-route", strings.NewReader("string=hello%20world&number=42"))
    90  	rawRequest.Header.Set("Content-Type", "application/json")
    91  	request := createTestRequest(rawRequest)
    92  
    93  	validation.AddRule("test_extra_request", &validation.RuleDefinition{
    94  		Function: func(ctx *validation.Context) bool {
    95  			r, ok := ctx.Extra["request"].(*Request)
    96  			assert.True(t, ok)
    97  			assert.Equal(t, request, r)
    98  			return true
    99  		},
   100  	})
   101  
   102  	request.Data = map[string]interface{}{
   103  		"string": "hello world",
   104  		"number": 42,
   105  	}
   106  	request.Rules = validation.RuleSet{
   107  		"string": validation.List{"required", "string", "test_extra_request"},
   108  		"number": validation.List{"required", "numeric", "min:10"},
   109  	}.AsRules()
   110  	errors := request.validate()
   111  	assert.Nil(t, errors)
   112  
   113  	rawRequest = httptest.NewRequest("POST", "/test-route", strings.NewReader("string=hello%20world"))
   114  	rawRequest.Header.Set("Content-Type", "application/json")
   115  	request = createTestRequest(rawRequest)
   116  	request.Data = map[string]interface{}{
   117  		"string": "hello world",
   118  	}
   119  
   120  	request.Rules = &validation.Rules{
   121  		Fields: validation.FieldMap{
   122  			"string": &validation.Field{
   123  				Rules: []*validation.Rule{
   124  					{Name: "required"},
   125  					{Name: "string"},
   126  				},
   127  			},
   128  			"number": &validation.Field{
   129  				Rules: []*validation.Rule{
   130  					{Name: "required"},
   131  					{Name: "numeric"},
   132  					{Name: "min", Params: []string{"50"}},
   133  				},
   134  			},
   135  		},
   136  	}
   137  	errors = request.validate()
   138  	assert.NotNil(t, errors)
   139  	assert.Equal(t, 2, len(errors["number"].Errors))
   140  
   141  	rawRequest = httptest.NewRequest("POST", "/test-route", strings.NewReader("string=hello%20world&number=42"))
   142  	rawRequest.Header.Set("Content-Type", "application/json")
   143  	request = createTestRequest(rawRequest)
   144  	request.Rules = nil
   145  	errors = request.validate()
   146  	assert.Nil(t, errors)
   147  }
   148  
   149  func TestRequestAccessors(t *testing.T) {
   150  	loc, err := time.LoadLocation("America/New_York")
   151  	if err != nil {
   152  		panic(err)
   153  	}
   154  
   155  	uid, err := uuid.Parse("3bbcee75-cecc-5b56-8031-b6641c1ed1f1")
   156  	if err != nil {
   157  		panic(err)
   158  	}
   159  
   160  	date, err := time.Parse("2006-01-02", "2019-11-21")
   161  	if err != nil {
   162  		panic(err)
   163  	}
   164  
   165  	url, err := url.ParseRequestURI("https://google.com")
   166  	if err != nil {
   167  		panic(err)
   168  	}
   169  
   170  	rawRequest := httptest.NewRequest("POST", "/test-route", nil)
   171  	request := createTestRequest(rawRequest)
   172  	request.Data = map[string]interface{}{
   173  		"string":   "hello world",
   174  		"integer":  42,
   175  		"numeric":  42.3,
   176  		"bool":     true,
   177  		"file":     []fsutil.File{{MIMEType: "image/png"}},
   178  		"timezone": loc,
   179  		"ip":       net.ParseIP("127.0.0.1"),
   180  		"uuid":     uid,
   181  		"date":     date,
   182  		"url":      url,
   183  		"object": map[string]interface{}{
   184  			"hello": "world",
   185  		},
   186  	}
   187  
   188  	assert.Equal(t, "hello world", request.String("string"))
   189  	assert.Equal(t, 42, request.Integer("integer"))
   190  	assert.Equal(t, 42.3, request.Numeric("numeric"))
   191  	assert.Equal(t, rawRequest, request.Request())
   192  	assert.True(t, request.Bool("bool"))
   193  
   194  	files := request.File("file")
   195  	assert.Len(t, files, 1)
   196  	assert.Equal(t, "image/png", files[0].MIMEType)
   197  
   198  	assert.Equal(t, "America/New_York", request.Timezone("timezone").String())
   199  	assert.Equal(t, "127.0.0.1", request.IP("ip").String())
   200  	assert.Equal(t, "3bbcee75-cecc-5b56-8031-b6641c1ed1f1", request.UUID("uuid").String())
   201  	assert.Equal(t, "2019-11-21 00:00:00 +0000 UTC", request.Date("date").String())
   202  	assert.Equal(t, "https://google.com", request.URL("url").String())
   203  	assert.Equal(t, request.Data["object"], request.Object("object"))
   204  
   205  	assert.Panics(t, func() { request.String("integer") })
   206  	assert.Panics(t, func() { request.Integer("string") })
   207  	assert.Panics(t, func() { request.Numeric("string") })
   208  	assert.Panics(t, func() { request.Bool("string") })
   209  	assert.Panics(t, func() { request.File("string") })
   210  	assert.Panics(t, func() { request.Timezone("string") })
   211  	assert.Panics(t, func() { request.IP("string") })
   212  	assert.Panics(t, func() { request.UUID("string") })
   213  	assert.Panics(t, func() { request.Date("string") })
   214  	assert.Panics(t, func() { request.URL("string") })
   215  	assert.Panics(t, func() { request.String("doesn't exist") })
   216  	assert.Panics(t, func() { request.Object("doesn't exist") })
   217  }
   218  
   219  func TestRequestHas(t *testing.T) {
   220  	request := createTestRequest(httptest.NewRequest("POST", "/test-route", nil))
   221  	request.Data = map[string]interface{}{
   222  		"string": "hello world",
   223  	}
   224  
   225  	assert.True(t, request.Has("string"))
   226  	assert.False(t, request.Has("not_in_request"))
   227  }
   228  
   229  func TestRequestCors(t *testing.T) {
   230  	request := createTestRequest(httptest.NewRequest("POST", "/test-route", nil))
   231  
   232  	assert.Nil(t, request.CORSOptions())
   233  
   234  	request.corsOptions = cors.Default()
   235  	options := request.CORSOptions()
   236  	assert.NotNil(t, options)
   237  
   238  	// Check cannot alter config
   239  	options.MaxAge = time.Second
   240  	assert.NotEqual(t, request.corsOptions.MaxAge, options.MaxAge)
   241  }
   242  
   243  func TestGetBearerToken(t *testing.T) {
   244  	request := createTestRequest(httptest.NewRequest("POST", "/test-route", nil))
   245  	request.Header().Set("Authorization", "NotBearer 123456789")
   246  	token, ok := request.BearerToken()
   247  	assert.Empty(t, token)
   248  	assert.False(t, ok)
   249  
   250  	request.Header().Set("Authorization", "Bearer123456789")
   251  	token, ok = request.BearerToken()
   252  	assert.Empty(t, token)
   253  	assert.False(t, ok)
   254  
   255  	request.Header().Set("Authorization", "Bearer 123456789")
   256  	token, ok = request.BearerToken()
   257  	assert.Equal(t, "123456789", token)
   258  	assert.True(t, ok)
   259  }
   260  
   261  func TestToStruct(t *testing.T) {
   262  	type UserInsertRequest struct {
   263  		Username string
   264  		Email    string
   265  	}
   266  
   267  	request := createTestRequest(httptest.NewRequest("POST", "/test-route", nil))
   268  	request.Data = map[string]interface{}{
   269  		"username": "johndoe",
   270  		"email":    "johndoe@example.org",
   271  	}
   272  
   273  	userInsertRequest := UserInsertRequest{}
   274  
   275  	if err := request.ToStruct(&userInsertRequest); err != nil {
   276  		assert.FailNow(t, err.Error())
   277  	}
   278  
   279  	assert.Equal(t, "johndoe", userInsertRequest.Username)
   280  	assert.Equal(t, "johndoe@example.org", userInsertRequest.Email)
   281  }