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: cors support #595

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ require (
github.com/moby/moby v20.10.22+incompatible
github.com/nitrictech/go-mods-direct v0.0.0-20221212215233-12bba0c74a7f
github.com/nitrictech/nitric/cloud/aws v0.0.0-20230718015326-80e1b8640347
github.com/nitrictech/nitric/core v0.0.0-20230928000037-7261774edded
github.com/nitrictech/nitric/core v0.0.0-20231107061027-b246cc30347a
github.com/pkg/errors v0.9.1
github.com/pterm/pterm v0.12.54
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
github.com/valyala/fasthttp v1.47.0
github.com/valyala/fasthttp v1.50.0
golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea
golang.org/x/mod v0.10.0 // indirect
golang.org/x/oauth2 v0.6.0 // indirect
Expand All @@ -54,7 +54,7 @@ require (
github.com/fasthttp/websocket v1.5.3
github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e
github.com/mitchellh/mapstructure v1.5.0
github.com/nitrictech/nitric/cloud/common v0.0.0-20230710061936-f8ccb102d31b
github.com/nitrictech/nitric/cloud/common v0.0.0-20231107061027-b246cc30347a
github.com/nitrictech/pearls v0.0.0-20230927035425-dc9ec468bb24
github.com/olahol/melody v1.1.3
github.com/samber/lo v1.38.1
Expand Down
14 changes: 6 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1649,12 +1649,10 @@ github.com/nitrictech/go-mods-direct v0.0.0-20221212215233-12bba0c74a7f h1:awate
github.com/nitrictech/go-mods-direct v0.0.0-20221212215233-12bba0c74a7f/go.mod h1:jqImBS1Tsk12vV2Gk7yP9+jajhpG+cHXrg7UhVxFruQ=
github.com/nitrictech/nitric/cloud/aws v0.0.0-20230718015326-80e1b8640347 h1:/9BIGv7ed6qWkeXchLXX0FIMqDp+7khBY5WlbHcJJEI=
github.com/nitrictech/nitric/cloud/aws v0.0.0-20230718015326-80e1b8640347/go.mod h1:HTToJAkzkFpLszJp2Vy9vDoplEOmWcuv86wW1o0J3YY=
github.com/nitrictech/nitric/cloud/common v0.0.0-20230710061936-f8ccb102d31b h1:9pAldJTjky0UlyEpibr355HsZWXwZdy7ZEvctVyV48U=
github.com/nitrictech/nitric/cloud/common v0.0.0-20230710061936-f8ccb102d31b/go.mod h1:nz8/tXPMb5o2yv8g4+NsvDu0dPyrY6iZyXZ1EprenlM=
github.com/nitrictech/nitric/core v0.0.0-20230718015326-80e1b8640347 h1:5c6IDgweLzybxniL9OkTdk9AvheDP2F6p1sFOGteICI=
github.com/nitrictech/nitric/core v0.0.0-20230718015326-80e1b8640347/go.mod h1:iz/seHApmfpML52NVjankr+9izPddUUwZHdcSQEvm9E=
github.com/nitrictech/nitric/core v0.0.0-20230928000037-7261774edded h1:Nm+S/GAnvKJfQHu75MY7o5LIJUukiM4WNnFj43gb2OA=
github.com/nitrictech/nitric/core v0.0.0-20230928000037-7261774edded/go.mod h1:iz/seHApmfpML52NVjankr+9izPddUUwZHdcSQEvm9E=
github.com/nitrictech/nitric/cloud/common v0.0.0-20231107061027-b246cc30347a h1:S6wm26B6MIZnpf1h4ZPv0+R9nrbh2Fd+nFfSgVMK01M=
github.com/nitrictech/nitric/cloud/common v0.0.0-20231107061027-b246cc30347a/go.mod h1:+X62o2IvXWO1jw3758kdy+JWDCd5f1hCgqdPa4/Gtbo=
github.com/nitrictech/nitric/core v0.0.0-20231107061027-b246cc30347a h1:eBANKkpskCtrUot9B3rbfwKvdLge4hnIsmFU7pG8QPc=
github.com/nitrictech/nitric/core v0.0.0-20231107061027-b246cc30347a/go.mod h1:s1jivAiMfES33W80gdV/YiVPpUpDQrpnNpu9gdYyMKM=
github.com/nitrictech/pearls v0.0.0-20230927035425-dc9ec468bb24 h1:Jb61oiwZoyMDqmLzNdgHjKYDLtDmbeb4GYEGSK/ZqgA=
github.com/nitrictech/pearls v0.0.0-20230927035425-dc9ec468bb24/go.mod h1:IXCOsqYAR5KRqXbbXnHkMp9NJrfY0qOeV3IcbBR5uSA=
github.com/nitrictech/protoutils v0.0.0-20220321044654-02667a814cdf h1:8MB8W8ylM8sCM2COGfiO39/tB6BTdiawLszaUGCNL5w=
Expand Down Expand Up @@ -2143,8 +2141,8 @@ github.com/uudashr/gocognit v1.0.6 h1:2Cgi6MweCsdB6kpcVQp7EW4U23iBFQWfTXiWlyp842
github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c=
github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M=
github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
github.com/viant/assertly v0.5.4 h1:5Hh4U3pLZa6uhCFAGpYOxck/8l9TZczEzoHNfJAhHEQ=
github.com/viant/ptrie v0.3.0 h1:SDaRd7Gqr1+ItCNz0GpTxRdK21nOfqjV6YtBm9jGlMY=
github.com/viant/ptrie v0.3.0/go.mod h1:VguMnbGfz95Zw+V5VarYSqtqslDxJbOv++xLzxkMhec=
Expand Down
8 changes: 8 additions & 0 deletions pkg/codeconfig/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Api struct {
parent *FunctionDependencies
securityDefinitions map[string]*v1.ApiSecurityDefinition
security map[string][]string
cors *v1.ApiCorsDefinition
workers []*v1.ApiWorker
lock sync.RWMutex
}
Expand Down Expand Up @@ -108,3 +109,10 @@ func (a *Api) AddSecurity(name string, scopes []string) {
a.security[name] = []string{}
}
}

func (a *Api) AddCors(cors *v1.ApiCorsDefinition) {
a.lock.Lock()
defer a.lock.Unlock()

a.cors = cors
}
4 changes: 3 additions & 1 deletion pkg/codeconfig/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,16 @@ func (a *FunctionDependencies) AddApiSecurityDefinitions(name string, sds map[st
}
}

func (a *FunctionDependencies) AddApiSecurity(name string, security map[string]*v1.ApiScopes) {
func (a *FunctionDependencies) AddApiSecurity(name string, security map[string]*v1.ApiScopes, cors *v1.ApiCorsDefinition) {
a.lock.Lock()
defer a.lock.Unlock()

if a.apis[name] == nil {
a.apis[name] = newApi(a)
}

a.apis[name].AddCors(cors)

for n, scopes := range security {
a.apis[name].AddSecurity(n, scopes.Scopes)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/codeconfig/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (s *Server) Declare(ctx context.Context, req *v1.ResourceDeclareRequest) (*
s.function.AddSecret(req.Resource.Name, req.GetSecret())
case v1.ResourceType_Api:
s.function.AddApiSecurityDefinitions(req.Resource.Name, req.GetApi().SecurityDefinitions)
s.function.AddApiSecurity(req.Resource.Name, req.GetApi().Security)
s.function.AddApiSecurity(req.Resource.Name, req.GetApi().Security, req.GetApi().GetCors())
case v1.ResourceType_Websocket:
// TODO: Add websocket configuration here when available
break
Expand Down
3 changes: 2 additions & 1 deletion pkg/codeconfig/uprequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func (c *codeConfig) ToUpRequest() (*deploy.DeployUpRequest, error) {
builder.set(res)
}

for k := range f.apis {
for k, api := range f.apis {
spec, err := c.apiSpec(k, nil)
if err != nil {
errs.Push(fmt.Errorf("could not build spec for api: %s; %w", k, err))
Expand All @@ -216,6 +216,7 @@ func (c *codeConfig) ToUpRequest() (*deploy.DeployUpRequest, error) {
Document: &deploy.Api_Openapi{
Openapi: string(apiBody),
},
Cors: api.cors,
},
},
})
Expand Down
37 changes: 33 additions & 4 deletions pkg/run/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/nitrictech/cli/pkg/history"
"github.com/nitrictech/cli/pkg/project"
"github.com/nitrictech/cli/pkg/utils"
"github.com/nitrictech/nitric/cloud/common/cors"
base_http "github.com/nitrictech/nitric/cloud/common/runtime/gateway"
v1 "github.com/nitrictech/nitric/core/pkg/api/nitric/v1"
"github.com/nitrictech/nitric/core/pkg/plugins/gateway"
Expand Down Expand Up @@ -71,10 +72,11 @@ type BaseHttpGateway struct {
websocketPlugin *RunWebsocketService
serviceListener net.Listener
gateway.UnimplementedGatewayPlugin
stop chan bool
pool pool.WorkerPool
project *project.Project
dash *dashboard.Dashboard
stop chan bool
pool pool.WorkerPool
project *project.Project
dash *dashboard.Dashboard
corsCache map[string]map[string]string
}

var _ gateway.GatewayService = &BaseHttpGateway{}
Expand Down Expand Up @@ -213,6 +215,8 @@ func (s *BaseHttpGateway) handleHttpProxyRequest(idx int) fasthttp.RequestHandle
}

func (s *BaseHttpGateway) handleApiHttpRequest(idx int) fasthttp.RequestHandler {
corsMiddleware := cors.CreateCorsMiddleware(s.corsCache)

return func(ctx *fasthttp.RequestCtx) {
if idx >= len(s.apis) {
ctx.Error("Sorry, nitric is listening on this port but is waiting for an API to be available to handle, you may have removed an API during development this port will be assigned to an API when one becomes available", 404)
Expand All @@ -221,6 +225,10 @@ func (s *BaseHttpGateway) handleApiHttpRequest(idx int) fasthttp.RequestHandler

apiName := s.apis[idx]

ctx.Request.Header.Add("X-Nitric-Api", apiName)

corsMiddleware(ctx, s.pool)

headerMap := base_http.HttpHeadersToMap(&ctx.Request.Header)

headers := map[string]*v1.HeaderValue{}
Expand Down Expand Up @@ -264,6 +272,12 @@ func (s *BaseHttpGateway) handleApiHttpRequest(idx int) fasthttp.RequestHandler
Trigger: httpTrigger,
Filter: apiWorkerFilter(apiName),
})

if worker == nil && s.corsCache[apiName] != nil && string(ctx.Request.Header.Method()) == "OPTIONS" {
ctx.Response.SetStatusCode(204)
return
}

if err != nil {
ctx.Redirect(fmt.Sprintf("http://localhost:%v/not-found", s.dash.GetPort()), fasthttp.StatusTemporaryRedirect)
return
Expand Down Expand Up @@ -814,10 +828,25 @@ func (s *BaseHttpGateway) Stop() error {
return nil
}

func (s *BaseHttpGateway) AddCors(apiName string, def *v1.ApiCorsDefinition) {
if def == nil {
s.corsCache[apiName] = nil
return
}

headers, err := cors.GetCorsHeaders(def)
if err != nil {
s.corsCache[apiName] = nil
} else {
s.corsCache[apiName] = *headers
}
}

// Create new HTTP gateway
// XXX: No External Args for function atm (currently the plugin loader does not pass any argument information)
func NewGateway(wsPlugin *RunWebsocketService) (*BaseHttpGateway, error) {
return &BaseHttpGateway{
websocketPlugin: wsPlugin,
corsCache: map[string]map[string]string{},
}, nil
}
2 changes: 2 additions & 0 deletions pkg/run/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ func (r *RunResourcesService) Declare(ctx context.Context, req resource.Resource
resource := req.Resource

switch resource.Type {
case v1.ResourceType_Api:
r.ls.gateway.AddCors(resource.GetName(), req.GetApi().GetCors())
case v1.ResourceType_Bucket:
r.ls.dashboard.AddBucket(resource.GetName())
}
Expand Down