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

Allow cors in HTTPServerSettings #1211

Merged
merged 1 commit into from
Jun 26, 2020
Merged
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
12 changes: 12 additions & 0 deletions config/confighttp/confighttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"net/http"
"time"

"github.com/rs/cors"

"go.opentelemetry.io/collector/config/configtls"
)

Expand Down Expand Up @@ -55,6 +57,12 @@ type HTTPServerSettings struct {

// TLSSetting struct exposes TLS client configuration.
TLSSetting *configtls.TLSServerSetting `mapstructure:"tls_settings, omitempty"`

// CorsOrigins are the allowed CORS origins for HTTP/JSON requests to grpc-gateway adapter
// for the OTLP receiver. See github.com/rs/cors
// An empty list means that CORS is not enabled at all. A wildcard (*) can be
// used to match any origin or one or more characters of an origin.
CorsOrigins []string `mapstructure:"cors_allowed_origins"`
}

func (hss *HTTPServerSettings) ToListener() (net.Listener, error) {
Expand All @@ -75,6 +83,10 @@ func (hss *HTTPServerSettings) ToListener() (net.Listener, error) {
}

func (hss *HTTPServerSettings) ToServer(handler http.Handler) *http.Server {
if len(hss.CorsOrigins) > 0 {
co := cors.Options{AllowedOrigins: hss.CorsOrigins}
handler = cors.New(co).Handler(handler)
}
return &http.Server{
Handler: handler,
}
Expand Down
58 changes: 58 additions & 0 deletions config/confighttp/confighttp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"net/http"
"path"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -259,6 +260,63 @@ func TestHttpReception(t *testing.T) {
}
}

func TestHttpCors(t *testing.T) {
hss := &HTTPServerSettings{
Endpoint: "localhost:0",
CorsOrigins: []string{"allowed-*.com"},
}

ln, err := hss.ToListener()
assert.NoError(t, err)
s := hss.ToServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
go func() {
_ = s.Serve(ln)
}()

// TODO: make starting server deterministic
// Wait for the servers to start
<-time.After(10 * time.Millisecond)

url := fmt.Sprintf("http://%s", ln.Addr().String())

// Verify allowed domain gets responses that allow CORS.
verifyCorsResp(t, url, "allowed-origin.com", 200, true)

// Verify disallowed domain gets responses that disallow CORS.
verifyCorsResp(t, url, "disallowed-origin.com", 200, false)

require.NoError(t, s.Close())
}

func verifyCorsResp(t *testing.T, url string, origin string, wantStatus int, wantAllowed bool) {
req, err := http.NewRequest("OPTIONS", url, nil)
require.NoError(t, err, "Error creating trace OPTIONS request: %v", err)
req.Header.Set("Origin", origin)
req.Header.Set("Access-Control-Request-Method", "POST")

resp, err := http.DefaultClient.Do(req)
require.NoError(t, err, "Error sending OPTIONS to http server: %v", err)

err = resp.Body.Close()
if err != nil {
t.Errorf("Error closing OPTIONS response body, %v", err)
}

assert.Equal(t, wantStatus, resp.StatusCode)

gotAllowOrigin := resp.Header.Get("Access-Control-Allow-Origin")
gotAllowMethods := resp.Header.Get("Access-Control-Allow-Methods")

wantAllowOrigin := ""
wantAllowMethods := ""
if wantAllowed {
wantAllowOrigin = origin
wantAllowMethods = "POST"
}
assert.Equal(t, wantAllowOrigin, gotAllowOrigin)
assert.Equal(t, wantAllowMethods, gotAllowMethods)
}

func ExampleHTTPServerSettings() {
settings := HTTPServerSettings{
Endpoint: ":443",
Expand Down
18 changes: 5 additions & 13 deletions receiver/otlpreceiver/otlp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,18 +396,15 @@ func verifyCorsResp(t *testing.T, url string, origin string, wantStatus int, wan
req.Header.Set("Origin", origin)
req.Header.Set("Access-Control-Request-Method", "POST")

client := &http.Client{}
resp, err := client.Do(req)
require.NoError(t, err, "Error sending OPTIONS to grpc-gateway server: %v", err)
resp, err := http.DefaultClient.Do(req)
require.NoError(t, err, "Error sending OPTIONS to http server: %v", err)

err = resp.Body.Close()
if err != nil {
t.Errorf("Error closing OPTIONS response body, %v", err)
}

if resp.StatusCode != wantStatus {
t.Errorf("Unexpected status from OPTIONS: %v", resp.StatusCode)
}
assert.Equal(t, wantStatus, resp.StatusCode)

gotAllowOrigin := resp.Header.Get("Access-Control-Allow-Origin")
gotAllowMethods := resp.Header.Get("Access-Control-Allow-Methods")
Expand All @@ -418,13 +415,8 @@ func verifyCorsResp(t *testing.T, url string, origin string, wantStatus int, wan
wantAllowOrigin = origin
wantAllowMethods = "POST"
}

if gotAllowOrigin != wantAllowOrigin {
t.Errorf("Unexpected Access-Control-Allow-Origin: %v", gotAllowOrigin)
}
if gotAllowMethods != wantAllowMethods {
t.Errorf("Unexpected Access-Control-Allow-Methods: %v", gotAllowMethods)
}
assert.Equal(t, wantAllowOrigin, gotAllowOrigin)
assert.Equal(t, wantAllowMethods, gotAllowMethods)
}

func TestStopWithoutStartNeverCrashes(t *testing.T) {
Expand Down