Skip to content

Commit

Permalink
tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tomanagle committed Mar 27, 2024
1 parent 5373f62 commit eec5776
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 24 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ jobs:
with:
go-version: ${{ matrix.go }}

- run: "go vet ./..."
- run: "make vet"

- run: "make test"

- uses: dominikh/staticcheck-action@v1.3.1
with:
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ vet:

.PHONY: staticcheck
staticcheck:
staticcheck ./...
staticcheck ./...

.PHONY: test
test:
go test -race -v -timeout 30s ./...
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
Expand All @@ -18,7 +19,10 @@ require (
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/jwx/v2 v2.0.19 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/sys v0.16.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
Expand Down
59 changes: 59 additions & 0 deletions internal/handlers/getabout_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package handlers

import (
"bytes"
"context"
"goth/internal/middleware"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
)

func TestGetAboutHandler(t *testing.T) {

testCases := []struct {
name string
expectedStatusCode int
expectedBody []byte
}{
{
name: "render successfully",
expectedStatusCode: http.StatusOK,
expectedBody: []byte("My website"),
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {

assert := assert.New(t)

handler := NewAboutHandler()

req, err := http.NewRequest("GET", "/about", nil)
assert.NoError(err)

value := middleware.Nonces{
Htmx: "nonce-1234",
ResponseTargets: "nonce-5678",
Tw: "nonce-9101",
HtmxCSSHash: "sha256-pgn1TCGZX6O77zDvy0oTODMOxemn0oj0LeCnQTRj7Kg=",
}
ctx := context.WithValue(req.Context(), middleware.NonceKey, value)
req = req.WithContext(ctx)

rr := httptest.NewRecorder()

handler.ServeHTTP(rr, req)

assert.Equal(tc.expectedStatusCode, rr.Code, "handler returned wrong status code: got %v want %v", rr.Code, tc.expectedStatusCode)

assert.True(bytes.Contains(rr.Body.Bytes(), tc.expectedBody), "handler returned unexpected body: got %v want %v", rr.Body.String(), tc.expectedBody)

})

}

}
22 changes: 22 additions & 0 deletions internal/handlers/web.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package handlers

import (
"goth/internal/templates"
"net/http"
)

type WebHandler struct{}

func NewWebHandler() *WebHandler {
return &WebHandler{}
}

func (h *WebHandler) ServeHTTPAbout(w http.ResponseWriter, r *http.Request) {
c := templates.About()
err := templates.Layout(c, "My website").Render(r.Context(), w)

if err != nil {
http.Error(w, "Error rendering template", http.StatusInternalServerError)
return
}
}
54 changes: 32 additions & 22 deletions internal/middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ type key string
var NonceKey key = "nonces"

type Nonces struct {
Htmx string
ResponseTargets string
Tw string
WordPressScripts string
WordPressStyles string
HtmxCSSHash string
Htmx string
ResponseTargets string
Tw string
HtmxCSSHash string
}

func generateRandomString(length int) string {
Expand All @@ -38,18 +36,22 @@ func CSPMiddleware(next http.Handler) http.Handler {

return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Create a new Nonces struct for every request when here.
// move to outisde the handler to use the same nonces in all responses
var nonceSet Nonces
nonceSet.Htmx = generateRandomString(16)
nonceSet.ResponseTargets = generateRandomString(16)
nonceSet.Tw = generateRandomString(16)

htmxCSSHash := "sha256-pgn1TCGZX6O77zDvy0oTODMOxemn0oj0LeCnQTRj7Kg="
// move to outside the handler to use the same nonces in all responses
nonceSet := Nonces{
Htmx: generateRandomString(16),
ResponseTargets: generateRandomString(16),
Tw: generateRandomString(16),
HtmxCSSHash: "sha256-pgn1TCGZX6O77zDvy0oTODMOxemn0oj0LeCnQTRj7Kg=",
}

// set nonces in context
ctx := context.WithValue(r.Context(), NonceKey, nonceSet)
// insert the nonces into the content security policy header
cspHeader := fmt.Sprintf("default-src 'self'; script-src 'nonce-%s' 'nonce-%s' ; style-src 'nonce-%s' '%s';", nonceSet.Htmx, nonceSet.ResponseTargets, nonceSet.Tw, htmxCSSHash)
cspHeader := fmt.Sprintf("default-src 'self'; script-src 'nonce-%s' 'nonce-%s' ; style-src 'nonce-%s' '%s';",
nonceSet.Htmx,
nonceSet.ResponseTargets,
nonceSet.Tw,
nonceSet.HtmxCSSHash)
w.Header().Set("Content-Security-Policy", cspHeader)

next.ServeHTTP(w, r.WithContext(ctx))
Expand All @@ -63,27 +65,35 @@ func TextHTMLMiddleware(next http.Handler) http.Handler {
})
}

// get the Nonce from the context, it is a struct called Nonces, so we can get the nonce we need by the key, i.e. HtmxNonce
func GetNonces(ctx context.Context) any {

// get the Nonce from the context, it is a struct called Nonces,
// so we can get the nonce we need by the key, i.e. HtmxNonce
func GetNonces(ctx context.Context) Nonces {
nonceSet := ctx.Value(NonceKey)
if nonceSet == nil {
log.Fatal("nooo no nonces")
log.Fatal("error getting nonce set - is nil")
}
return nonceSet

nonces, ok := nonceSet.(Nonces)

if !ok {
log.Fatal("error getting nonce set - not ok")
}

return nonces
}

func GetHtmxNonce(ctx context.Context) string {
nonceSet := GetNonces(ctx).(Nonces)
nonceSet := GetNonces(ctx)

return nonceSet.Htmx
}

func GetResponseTargetsNonce(ctx context.Context) string {
nonceSet := GetNonces(ctx).(Nonces)
nonceSet := GetNonces(ctx)
return nonceSet.ResponseTargets
}

func GetTwNonce(ctx context.Context) string {
nonceSet := GetNonces(ctx).(Nonces)
nonceSet := GetNonces(ctx)
return nonceSet.Tw
}

0 comments on commit eec5776

Please sign in to comment.