Skip to content

Commit

Permalink
Package Cleanup (#7)
Browse files Browse the repository at this point in the history
* cleaning up errors so they are errors.Is able

* assert error types

* correct name for test

* showcase default options in example

* unsigned up top

* update documentaiton lines to be specific
  • Loading branch information
syntaqx authored Jul 1, 2024
1 parent b218b27 commit 056c306
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 22 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,16 @@ cookie.Set(w, "debug", "true", &cookie.Options{
})
```

This will require the use of the `GetSigned` method to retrieve cookie values.

```go
debug, err := cookie.GetSigned(r, "debug")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
```

When defaulting to signed cookies, unsigned cookies can still be populated by
using the `unsigned` tag in the struct field:

Expand All @@ -187,7 +197,7 @@ type MyCookies struct {
}
```

Or retrieve unsigned cookies using the `Get` method:
Or retrieved using the `Get` method, which always retrieves the plaintext value:

```go
debug, err := cookie.Get(r, "debug")
Expand Down
34 changes: 21 additions & 13 deletions _example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (

type RequestCookies struct {
ApplicationID uuid.UUID `cookie:"Application-ID"`
Theme string `cookie:"THEME"`
Debug bool `cookie:"DEBUG"`
AccessToken string `cookie:"Access-Token,signed"`
UserID int `cookie:"User-ID,signed"`
IsAdmin bool `cookie:"Is-Admin,signed"`
Permissions []string `cookie:"Permissions,signed"`
ExpiresAt time.Time `cookie:"Expires-At,signed"`
Theme string `cookie:"THEME"`
Debug bool `cookie:"DEBUG"`
}

func handler(w http.ResponseWriter, r *http.Request) {
Expand All @@ -43,27 +43,35 @@ func handler(w http.ResponseWriter, r *http.Request) {
}

func setDemoCookies(w http.ResponseWriter) {
options := &cookie.Options{
// Set cookies
cookie.Set(w, "Application-ID", uuid.Must(uuid.NewV7()).String(), nil)
cookie.Set(w, "THEME", "default", nil)
cookie.Set(w, "DEBUG", "true", nil)

secureOptions := &cookie.Options{
Path: "/",
Expires: time.Now().Add(24 * time.Hour),
HttpOnly: true,
Secure: true,
}

// Set cookies
cookie.Set(w, "Application-ID", uuid.Must(uuid.NewV7()).String(), options)
cookie.Set(w, "THEME", "default", options)
cookie.Set(w, "DEBUG", "true", options)

// Set signed cookies
cookie.SetSigned(w, "Access-Token", "some-access-token", options)
cookie.SetSigned(w, "User-ID", "123", options)
cookie.SetSigned(w, "Is-Admin", "true", options)
cookie.SetSigned(w, "Permissions", "read,write,execute", options)
cookie.SetSigned(w, "Expires-At", time.Now().Add(24*time.Hour).Format(time.RFC3339), options)
cookie.SetSigned(w, "Access-Token", "some-access-token", secureOptions)
cookie.SetSigned(w, "User-ID", "123", secureOptions)
cookie.SetSigned(w, "Is-Admin", "true", secureOptions)
cookie.SetSigned(w, "Permissions", "read,write,execute", secureOptions)
cookie.SetSigned(w, "Expires-At", time.Now().Add(24*time.Hour).Format(time.RFC3339), secureOptions)
}

func main() {
cookie.DefaultOptions = &cookie.Options{
Path: "/",
Expires: time.Now().Add(24 * time.Hour),
HttpOnly: true,
}

http.HandleFunc("/", handler)

fmt.Println("Listening on :8080")
http.ListenAndServe(":8080", nil)
}
13 changes: 8 additions & 5 deletions cookie.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ var (
)

var (
// ErrInvalidSignedCookieFormat is returned when a signed cookie is not in the correct format.
ErrInvalidSignedCookieFormat = errors.New("cookie: invalid signed cookie format")
// ErrInvalidSignedFormat is returned when a signed cookie is not in the correct format.
ErrInvalidSignedFormat = errors.New("cookie: invalid signed cookie format")

// ErrInvalidSignature is returned when a signed cookie has an invalid signature.
ErrInvalidSignature = errors.New("cookie: invalid cookie signature")
)

// ErrUnsupportedType is returned when a field type is not supported.
Expand Down Expand Up @@ -86,7 +89,7 @@ func Set(w http.ResponseWriter, name, value string, options *Options) {
http.SetCookie(w, cookie)
}

// Get retrieves the value of a cookie with the given name.
// Get retrieves the plaintext value of a cookie with the given name.
func Get(r *http.Request, name string) (string, error) {
cookie, err := r.Cookie(name)
if err != nil {
Expand Down Expand Up @@ -114,7 +117,7 @@ func GetSigned(r *http.Request, name string) (string, error) {

parts := strings.SplitN(signedValue, "|", 2)
if len(parts) != 2 {
return "", ErrInvalidSignedCookieFormat
return "", ErrInvalidSignedFormat
}

value, err := base64.URLEncoding.DecodeString(parts[0])
Expand All @@ -132,7 +135,7 @@ func GetSigned(r *http.Request, name string) (string, error) {
expectedSignature := h.Sum(nil)

if !hmac.Equal(signature, expectedSignature) {
return "", errors.New("cookie: invalid cookie signature")
return "", ErrInvalidSignature
}

return string(value), nil
Expand Down
14 changes: 11 additions & 3 deletions cookie_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func TestGetSignedNonexistentCookie(t *testing.T) {
}
}

func TestGetSignedInvalidFormat(t *testing.T) {
func TestGetSignedInvalidSignedFormat(t *testing.T) {
r := httptest.NewRequest(http.MethodGet, "/", nil)
cookieName := "myCookie"
cookieValue := "myValue"
Expand All @@ -201,6 +201,10 @@ func TestGetSignedInvalidFormat(t *testing.T) {
if err == nil {
t.Error("Expected error, got nil")
}

if err != ErrInvalidSignedFormat {
t.Errorf("Expected error ErrInvalidSignedFormat, got %v", err)
}
}

func TestGetSignedInvalidValue(t *testing.T) {
Expand All @@ -222,7 +226,7 @@ func TestGetSignedInvalidValue(t *testing.T) {
}
}

func TestGetSignedInvalidSignature(t *testing.T) {
func TestGetSignedInvalidBase64(t *testing.T) {
r := httptest.NewRequest(http.MethodGet, "/", nil)
cookieName := "myCookie"
cookieValue := "myValue"
Expand All @@ -241,7 +245,7 @@ func TestGetSignedInvalidSignature(t *testing.T) {
}
}

func TestGetSignedInvalidHMAC(t *testing.T) {
func TestGetSignedInvalidSignature(t *testing.T) {
r := httptest.NewRequest(http.MethodGet, "/", nil)
cookieName := "myCookie"
cookieValue := "myValue"
Expand All @@ -259,6 +263,10 @@ func TestGetSignedInvalidHMAC(t *testing.T) {
if err == nil {
t.Error("Expected error, got nil")
}

if err != ErrInvalidSignature {
t.Errorf("Expected error ErrInvalidSignature, got %v", err)
}
}

func TestRemove(t *testing.T) {
Expand Down

0 comments on commit 056c306

Please sign in to comment.