feat: add configurable transport-independent CORS policy
This commit is contained in:
76
examples/cors/main.go
Normal file
76
examples/cors/main.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
omni "git.yuntuo.hk/k2safe/go-omni"
|
||||
"git.yuntuo.hk/k2safe/go-omni/config"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Server config.Config `json:"server"`
|
||||
}
|
||||
|
||||
func (c Config) Validate() error { return config.AtField("server", c.Server.Validate()) }
|
||||
|
||||
func run(path string) error {
|
||||
cfg, err := config.LoadProject(path, Config{Server: config.Default()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a := omni.New(omni.WithConfig(cfg.Server))
|
||||
defer a.Close()
|
||||
a.GET("/private", func(c *omni.Context) error {
|
||||
if c.Header("Authorization") != "Bearer example-only" {
|
||||
return omni.Unauthorized("LOGIN_REQUIRED", "login required")
|
||||
}
|
||||
return c.OK("authenticated")
|
||||
})
|
||||
server := httptest.NewServer(a)
|
||||
defer server.Close()
|
||||
client := &http.Client{Timeout: 3 * time.Second}
|
||||
defer client.CloseIdleConnections()
|
||||
for _, tc := range []struct {
|
||||
method, path, auth string
|
||||
status int
|
||||
}{{"OPTIONS", "/private", "", 204}, {"GET", "/private", "", 401}, {"GET", "/private", "Bearer example-only", 200}, {"GET", "/missing", "", 404}} {
|
||||
r, _ := http.NewRequest(tc.method, server.URL+tc.path, nil)
|
||||
r.Header.Set("Origin", cfg.Server.CORS.AllowedOrigins[0])
|
||||
if tc.method == "OPTIONS" {
|
||||
r.Header.Set("Access-Control-Request-Method", "GET")
|
||||
r.Header.Set("Access-Control-Request-Headers", "authorization")
|
||||
}
|
||||
if tc.auth != "" {
|
||||
r.Header.Set("Authorization", tc.auth)
|
||||
}
|
||||
res, err := client.Do(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, readErr := io.Copy(io.Discard, res.Body)
|
||||
closeErr := res.Body.Close()
|
||||
if err := errors.Join(readErr, closeErr); err != nil {
|
||||
return err
|
||||
}
|
||||
if res.StatusCode != tc.status || res.Header.Get("Access-Control-Allow-Origin") == "" {
|
||||
return fmt.Errorf("unexpected CORS response: %d", res.StatusCode)
|
||||
}
|
||||
fmt.Printf("%s %s -> %d, CORS allowed\n", tc.method, tc.path, res.StatusCode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func main() {
|
||||
path := flag.String("config", "examples/cors/config.yaml", "selected configuration file")
|
||||
flag.Parse()
|
||||
if err := run(*path); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user