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

feat(middleware/cors): Add support for Access-Control-Allow-Private-Network #2908

Merged
merged 17 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 4 additions & 0 deletions docs/api/middleware/cors.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ app.Use(cors.New(cors.Config{
| ExposeHeaders | `string` | ExposeHeaders defines a whitelist headers that clients are allowed to access. | `""` |
| MaxAge | `int` | MaxAge indicates how long (in seconds) the results of a preflight request can be cached. If you pass MaxAge 0, Access-Control-Max-Age header will not be added and browser will use 5 seconds by default. To disable caching completely, pass MaxAge value negative. It will set the Access-Control-Max-Age header 0. | `0` |

gaby marked this conversation as resolved.
Show resolved Hide resolved
| `AllowPrivateNetworkAccess` | `bool` | Indicates whether the `Access-Control-Allow-Private-Network` response header should be set to `true`, allowing requests from private networks. This aligns with modern security practices for web applications interacting with private networks. |


## Default Config

```go
Expand All @@ -99,5 +102,6 @@ var ConfigDefault = Config{
AllowCredentials: false,
ExposeHeaders: "",
MaxAge: 0,
AllowPrivateNetworkAccess: false,
}
```
1 change: 1 addition & 0 deletions helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@

// HTTP Headers were copied from net/http.
const (
HeaderAuthorization = "Authorization"

Check failure on line 859 in helpers.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofmt`-ed with `-s` (gofmt)
HeaderProxyAuthenticate = "Proxy-Authenticate"
HeaderProxyAuthorization = "Proxy-Authorization"
HeaderWWWAuthenticate = "WWW-Authenticate"
Expand Down Expand Up @@ -978,6 +978,7 @@
HeaderXRequestedWith = "X-Requested-With"
HeaderXRobotsTag = "X-Robots-Tag"
HeaderXUACompatible = "X-UA-Compatible"
HeaderAccessControlAllowPrivateNetwork = "Access-Control-Allow-Private-Network"
gaby marked this conversation as resolved.
Show resolved Hide resolved
)

// Network types that are commonly used
Expand Down
12 changes: 12 additions & 0 deletions middleware/cors/cors.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ type Config struct {
//
// Optional. Default value 0.
MaxAge int

// AllowPrivateNetworkAccess indicates whether the Access-Control-Allow-Private-Network
// response header should be set to true, allowing requests from private networks.
//
// Optional. Default value false.
AllowPrivateNetworkAccess bool
gaby marked this conversation as resolved.
Show resolved Hide resolved
}

// ConfigDefault is the default config
Expand Down Expand Up @@ -227,6 +233,12 @@ func New(config ...Config) fiber.Handler {
c.Set(fiber.HeaderAccessControlMaxAge, "0")
}

// Set Preflight request handling
if cfg.AllowPrivateNetworkAccess {
gaby marked this conversation as resolved.
Show resolved Hide resolved
// Set the Access-Control-Allow-Private-Network header to "true"
c.Set(fiber.HeaderAccessControlAllowPrivateNetwork, "true")
}

// Send 204 No Content
return c.SendStatus(fiber.StatusNoContent)
}
Expand Down
37 changes: 37 additions & 0 deletions middleware/cors/cors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,43 @@
}
}

// The Enhancement for issue #2804
func Test_CORS_AllowPrivateNetworkAccess(t *testing.T) {
gaby marked this conversation as resolved.
Show resolved Hide resolved
t.Parallel()

// Test scenario where AllowPrivateNetworkAccess is enabled
app := fiber.New()
app.Use(New(Config{
AllowPrivateNetworkAccess: true,
}))

handler := app.Handler()

ctx := &fasthttp.RequestCtx{}
ctx.Request.Header.SetMethod(fiber.MethodOptions)
ctx.Request.Header.Set(fiber.HeaderOrigin, "https://example.com")
ctx.Request.Header.Set("Access-Control-Request-Private-Network", "true")
gaby marked this conversation as resolved.
Show resolved Hide resolved
handler(ctx)

// Verify the Access-Control-Allow-Private-Network header is set to "true"
require.Equal(t, "true", string(ctx.Response.Header.Peek("Access-Control-Allow-Private-Network")), "The Access-Control-Allow-Private-Network header should be set to 'true' when AllowPrivateNetworkAccess is enabled")

// Reset ctx for next test
ctx = &fasthttp.RequestCtx{}
ctx.Request.Header.SetMethod(fiber.MethodOptions)
ctx.Request.Header.Set(fiber.HeaderOrigin, "https://example.com")

Check failure on line 717 in middleware/cors/cors_test.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofmt`-ed with `-s` (gofmt)
// Test scenario where AllowPrivateNetworkAccess is disabled (default)
app = fiber.New()
app.Use(New())

handler = app.Handler()
handler(ctx)

// Verify the Access-Control-Allow-Private-Network header is not present
require.Equal(t, "", string(ctx.Response.Header.Peek("Access-Control-Allow-Private-Network")), "The Access-Control-Allow-Private-Network header should not be present by default")
}

// go test -v -run=^$ -bench=Benchmark_CORS_NewHandler -benchmem -count=4
func Benchmark_CORS_NewHandler(b *testing.B) {
app := fiber.New()
Expand Down
Loading