Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for fasthttp #15

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# directories
.idea/
.vscode/

# files
.DS_Store
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ Helmet helps you secure your Golang web applications by setting various HTTP sec

You can see more in the [documentation](https://pkg.go.dev/github.com/goddtriffin/helmet).


`go get github.com/goddtriffin/helmet`

### With net/http

```go
package main

Expand All @@ -44,6 +45,36 @@ func main() {

This code sample can be found in [`/examples/01-quick-start/`](https://github.com/goddtriffin/helmet/blob/master/examples/01-quick-start/main.go).

### With fasthttp

```go
package main

import (
"github.com/fasthttp/router"
"github.com/goddtriffin/helmet"
"github.com/valyala/fasthttp"
)

func main() {
r := router.New()

r.GET("/", func(ctx *fasthttp.RequestCtx) {
ctx.WriteString("I love HelmetJS, I just wish there was a Go(lang) equivalent...")
})

h := helmet.Default()

httpServer := fasthttp.Server{
Handler: h.SecureFastHTTP(r.Handler),
}

httpServer.ListenAndServe(":8080")
}
```

This code sample can be found in [`/examples/01-quick-start-fasthttp/`](https://github.com/goddtriffin/helmet/blob/master/examples/01-quick-start-fasthttp/main.go).

## How It Works

Helmet is a collection of 12 smaller middleware functions that set HTTP security response headers. Initializing via `helmet.Default()` will not include all of these middleware functions by default.
Expand Down
11 changes: 10 additions & 1 deletion content-security-policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"net/http"
"strings"

"github.com/valyala/fasthttp"
)

// HeaderContentSecurityPolicy is the Content-Security-Policy HTTP security header.
Expand Down Expand Up @@ -193,7 +195,7 @@ func (csp *ContentSecurityPolicy) String() string {
return csp.cache
}

var policies = []string{}
policies := []string{}
for directive, sources := range csp.policies {
if len(sources) == 0 {
policies = append(policies, fmt.Sprintf("%s", directive))
Expand Down Expand Up @@ -222,3 +224,10 @@ func (csp *ContentSecurityPolicy) Header(w http.ResponseWriter) {
w.Header().Set(HeaderContentSecurityPolicy, csp.String())
}
}

// HeaderFastHTTP adds the Content-Security-Policy HTTP security header to the given *fasthttp.RequestCtx.
func (csp *ContentSecurityPolicy) HeaderFastHTTP(ctx *fasthttp.RequestCtx) {
if !csp.Empty() {
ctx.Response.Header.Set(HeaderContentSecurityPolicy, csp.String())
}
}
23 changes: 23 additions & 0 deletions examples/01-quick-start-fasthttp/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

import (
"github.com/fasthttp/router"
"github.com/goddtriffin/helmet"
"github.com/valyala/fasthttp"
)

func main() {
r := router.New()

r.GET("/", func(ctx *fasthttp.RequestCtx) {
ctx.WriteString("I love HelmetJS, I just wish there was a Go(lang) equivalent...")
})

h := helmet.Default()

httpServer := fasthttp.Server{
Handler: h.SecureFastHTTP(r.Handler),
}

httpServer.ListenAndServe(":8080")
}
9 changes: 9 additions & 0 deletions expect-ct.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"net/http"
"strings"

"github.com/valyala/fasthttp"
)

// HeaderExpectCT is the Expect-CT HTTP security header.
Expand Down Expand Up @@ -95,3 +97,10 @@ func (ect *ExpectCT) Header(w http.ResponseWriter) {
w.Header().Set(HeaderExpectCT, ect.String())
}
}

// HeaderFastHTTP adds the Expect-CT HTTP security header to the given *fasthttp.RequestCtx.
func (ect *ExpectCT) HeaderFastHTTP(ctx *fasthttp.RequestCtx) {
if !ect.Empty() {
ctx.Response.Header.Set(HeaderExpectCT, ect.String())
}
}
11 changes: 10 additions & 1 deletion feature-policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"net/http"
"strings"

"github.com/valyala/fasthttp"
)

// HeaderFeaturePolicy is the Feature-Policy HTTP security header.
Expand Down Expand Up @@ -135,7 +137,7 @@ func (fp *FeaturePolicy) String() string {
return fp.cache
}

var policies = []string{}
policies := []string{}
for directive, origins := range fp.policies {
originsAsStrings := []string{}
for _, origin := range origins {
Expand All @@ -160,3 +162,10 @@ func (fp *FeaturePolicy) Header(w http.ResponseWriter) {
w.Header().Set(HeaderFeaturePolicy, fp.String())
}
}

// HeaderFastHTTP adds the Feature-Policy HTTP security header to the given *fasthttp.RequestCtx.
func (fp *FeaturePolicy) HeaderFastHTTP(ctx *fasthttp.RequestCtx) {
if !fp.Empty() {
ctx.Response.Header.Set(HeaderFeaturePolicy, fp.String())
}
}
12 changes: 12 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
module github.com/goddtriffin/helmet

go 1.18

require (
github.com/fasthttp/router v1.4.10
github.com/valyala/fasthttp v1.38.0
)

require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/klauspost/compress v1.15.0 // indirect
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
)
24 changes: 23 additions & 1 deletion helmet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package helmet

import (
"net/http"

"github.com/valyala/fasthttp"
)

// Helmet is a HTTP security middleware for Go(lang) inspired by HelmetJS for Express.js.
Expand Down Expand Up @@ -51,7 +53,7 @@ func Empty() *Helmet {
}
}

// Secure is the middleware handler.
// Secure is the net/http middleware handler.
func (h *Helmet) Secure(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.ContentSecurityPolicy.Header(w)
Expand All @@ -70,3 +72,23 @@ func (h *Helmet) Secure(next http.Handler) http.Handler {
next.ServeHTTP(w, r)
})
}

// SecureFastHTTP is the fasthttp middleware handler.
func (h *Helmet) SecureFastHTTP(next fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
h.ContentSecurityPolicy.HeaderFastHTTP(ctx)
h.XContentTypeOptions.HeaderFastHTTP(ctx)
h.XDNSPrefetchControl.HeaderFastHTTP(ctx)
h.XDownloadOptions.HeaderFastHTTP(ctx)
h.ExpectCT.HeaderFastHTTP(ctx)
h.FeaturePolicy.HeaderFastHTTP(ctx)
h.XFrameOptions.HeaderFastHTTP(ctx)
h.XPermittedCrossDomainPolicies.HeaderFastHTTP(ctx)
h.XPoweredBy.HeaderFastHTTP(ctx)
h.ReferrerPolicy.HeaderFastHTTP(ctx)
h.StrictTransportSecurity.HeaderFastHTTP(ctx)
h.XXSSProtection.HeaderFastHTTP(ctx)

next(ctx)
}
}
9 changes: 9 additions & 0 deletions referrer-policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package helmet
import (
"net/http"
"strings"

"github.com/valyala/fasthttp"
)

// HeaderReferrerPolicy is the Referrer-Policy HTTP security header.
Expand Down Expand Up @@ -73,3 +75,10 @@ func (rp *ReferrerPolicy) Header(w http.ResponseWriter) {
w.Header().Set(HeaderReferrerPolicy, rp.String())
}
}

// HeaderFastHTTP adds the Referrer-Policy HTTP header to the given *fasthttp.RequestCtx.
func (rp *ReferrerPolicy) HeaderFastHTTP(ctx *fasthttp.RequestCtx) {
if !rp.Empty() {
ctx.Response.Header.Set(HeaderReferrerPolicy, rp.String())
}
}
9 changes: 9 additions & 0 deletions strict-transport-security.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"net/http"
"strings"

"github.com/valyala/fasthttp"
)

// HeaderStrictTransportSecurity is the Strict-Transport-Security HTTP security header.
Expand Down Expand Up @@ -95,3 +97,10 @@ func (hsts *StrictTransportSecurity) Header(w http.ResponseWriter) {
w.Header().Set(HeaderStrictTransportSecurity, hsts.String())
}
}

// HeaderFastHTTP adds the Strict-Transport-Security HTTP security header to the given *fasthttp.RequestCtx.
func (hsts *StrictTransportSecurity) HeaderFastHTTP(ctx *fasthttp.RequestCtx) {
if !hsts.Empty() {
ctx.Response.Header.Set(HeaderStrictTransportSecurity, hsts.String())
}
}
13 changes: 12 additions & 1 deletion x-content-type-options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package helmet

import "net/http"
import (
"net/http"

"github.com/valyala/fasthttp"
)

// HeaderXContentTypeOptions is the X-Content-Type-Options HTTP header.
const HeaderXContentTypeOptions = "X-Content-Type-Options"
Expand All @@ -26,3 +30,10 @@ func (xcto XContentTypeOptions) Header(w http.ResponseWriter) {
w.Header().Set(HeaderXContentTypeOptions, xcto.String())
}
}

// HeaderFastHTTP adds the X-Content-Type-Options HTTP security header to the given *fasthttp.RequestCtx.
func (xcto XContentTypeOptions) HeaderFastHTTP(ctx *fasthttp.RequestCtx) {
if !xcto.Empty() {
ctx.Response.Header.Set(HeaderXContentTypeOptions, xcto.String())
}
}
13 changes: 12 additions & 1 deletion x-dns-prefetch-control.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package helmet

import "net/http"
import (
"net/http"

"github.com/valyala/fasthttp"
)

// HeaderXDNSPrefetchControl is the X-DNS-Prefetch-Control HTTP header.
const HeaderXDNSPrefetchControl = "X-DNS-Prefetch-Control"
Expand Down Expand Up @@ -29,3 +33,10 @@ func (dns XDNSPrefetchControl) Header(w http.ResponseWriter) {
w.Header().Set(HeaderXDNSPrefetchControl, dns.String())
}
}

// HeaderFastHTTP adds the X-DNS-Prefetch-Control HTTP security header to the given *fasthttp.RequestCtx.
func (dns XDNSPrefetchControl) HeaderFastHTTP(ctx *fasthttp.RequestCtx) {
if !dns.Empty() {
ctx.Response.Header.Set(HeaderXDNSPrefetchControl, dns.String())
}
}
13 changes: 12 additions & 1 deletion x-download-options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package helmet

import "net/http"
import (
"net/http"

"github.com/valyala/fasthttp"
)

// HeaderXDownloadOptions is the X-Download-Options HTTP header.
const HeaderXDownloadOptions = "X-Download-Options"
Expand All @@ -26,3 +30,10 @@ func (xdo XDownloadOptions) Header(w http.ResponseWriter) {
w.Header().Set(HeaderXDownloadOptions, xdo.String())
}
}

// HeaderFastHTTP adds the X-Download-Options HTTP security header to the given *fasthttp.RequestCtx.
func (xdo XDownloadOptions) HeaderFastHTTP(ctx *fasthttp.RequestCtx) {
if !xdo.Empty() {
ctx.Response.Header.Set(HeaderXDownloadOptions, xdo.String())
}
}
13 changes: 12 additions & 1 deletion x-frame-options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package helmet

import "net/http"
import (
"net/http"

"github.com/valyala/fasthttp"
)

// HeaderXFrameOptions is the X-Frame-Options HTTP security header.
const HeaderXFrameOptions = "X-Frame-Options"
Expand Down Expand Up @@ -29,3 +33,10 @@ func (xfo XFrameOptions) Header(w http.ResponseWriter) {
w.Header().Set(HeaderXFrameOptions, xfo.String())
}
}

// HeaderFastHTTP adds the X-Frame-Options HTTP header to the given *fasthttp.RequestCtx.
func (xfo XFrameOptions) HeaderFastHTTP(ctx *fasthttp.RequestCtx) {
if !xfo.Empty() {
ctx.Response.Header.Set(HeaderXFrameOptions, xfo.String())
}
}
13 changes: 12 additions & 1 deletion x-permitted-cross-domain-policies.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package helmet

import "net/http"
import (
"net/http"

"github.com/valyala/fasthttp"
)

// HeaderXPermittedCrossDomainPolicies is the X-Permitted-Cross-Domain-Policies HTTP security header.
const HeaderXPermittedCrossDomainPolicies = "X-Permitted-Cross-Domain-Policies"
Expand Down Expand Up @@ -32,3 +36,10 @@ func (cdp XPermittedCrossDomainPolicies) Header(w http.ResponseWriter) {
w.Header().Set(HeaderXPermittedCrossDomainPolicies, cdp.String())
}
}

// HeaderFastHTTP adds the X-DNS-Prefetch-Control HTTP security header to the given *fasthttp.RequestCtx.
func (cdp XPermittedCrossDomainPolicies) HeaderFastHTTP(ctx *fasthttp.RequestCtx) {
if !cdp.Empty() {
ctx.Response.Header.Set(HeaderXPermittedCrossDomainPolicies, cdp.String())
}
}
Loading