mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
feat: allow cross-origin requests between users' own apps (#7688)
This commit is contained in:
130
coderd/httpmw/cors_test.go
Normal file
130
coderd/httpmw/cors_test.go
Normal file
@ -0,0 +1,130 @@
|
||||
package httpmw_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
"github.com/coder/coder/coderd/httpmw"
|
||||
)
|
||||
|
||||
func TestWorkspaceAppCors(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
regex, err := httpapi.CompileHostnamePattern("*--apps.dev.coder.com")
|
||||
require.NoError(t, err)
|
||||
|
||||
methods := []string{
|
||||
http.MethodOptions,
|
||||
http.MethodHead,
|
||||
http.MethodGet,
|
||||
http.MethodPost,
|
||||
http.MethodPut,
|
||||
http.MethodPatch,
|
||||
http.MethodDelete,
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
origin string
|
||||
app httpapi.ApplicationURL
|
||||
allowed bool
|
||||
}{
|
||||
{
|
||||
name: "Self",
|
||||
origin: "https://3000--agent--ws--user--apps.dev.coder.com",
|
||||
app: httpapi.ApplicationURL{
|
||||
AppSlugOrPort: "3000",
|
||||
AgentName: "agent",
|
||||
WorkspaceName: "ws",
|
||||
Username: "user",
|
||||
},
|
||||
allowed: true,
|
||||
},
|
||||
{
|
||||
name: "SameWorkspace",
|
||||
origin: "https://8000--agent--ws--user--apps.dev.coder.com",
|
||||
app: httpapi.ApplicationURL{
|
||||
AppSlugOrPort: "3000",
|
||||
AgentName: "agent",
|
||||
WorkspaceName: "ws",
|
||||
Username: "user",
|
||||
},
|
||||
allowed: true,
|
||||
},
|
||||
{
|
||||
name: "SameUser",
|
||||
origin: "https://8000--agent2--ws2--user--apps.dev.coder.com",
|
||||
app: httpapi.ApplicationURL{
|
||||
AppSlugOrPort: "3000",
|
||||
AgentName: "agent",
|
||||
WorkspaceName: "ws",
|
||||
Username: "user",
|
||||
},
|
||||
allowed: true,
|
||||
},
|
||||
{
|
||||
name: "DifferentOriginOwner",
|
||||
origin: "https://3000--agent--ws--user2--apps.dev.coder.com",
|
||||
app: httpapi.ApplicationURL{
|
||||
AppSlugOrPort: "3000",
|
||||
AgentName: "agent",
|
||||
WorkspaceName: "ws",
|
||||
Username: "user",
|
||||
},
|
||||
allowed: false,
|
||||
},
|
||||
{
|
||||
name: "DifferentHostOwner",
|
||||
origin: "https://3000--agent--ws--user--apps.dev.coder.com",
|
||||
app: httpapi.ApplicationURL{
|
||||
AppSlugOrPort: "3000",
|
||||
AgentName: "agent",
|
||||
WorkspaceName: "ws",
|
||||
Username: "user2",
|
||||
},
|
||||
allowed: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, method := range methods {
|
||||
r := httptest.NewRequest(method, "http://localhost", nil)
|
||||
r.Header.Set("Origin", test.origin)
|
||||
rw := httptest.NewRecorder()
|
||||
|
||||
// Preflight requests need to know what method will be requested.
|
||||
if method == http.MethodOptions {
|
||||
r.Header.Set("Access-Control-Request-Method", method)
|
||||
}
|
||||
|
||||
handler := httpmw.WorkspaceAppCors(regex, test.app)(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(http.StatusNoContent)
|
||||
}))
|
||||
|
||||
handler.ServeHTTP(rw, r)
|
||||
|
||||
if test.allowed {
|
||||
require.Equal(t, test.origin, rw.Header().Get("Access-Control-Allow-Origin"))
|
||||
} else {
|
||||
require.Equal(t, "", rw.Header().Get("Access-Control-Allow-Origin"))
|
||||
}
|
||||
|
||||
// For options we should never get to our handler as the middleware
|
||||
// short-circuits with a 200.
|
||||
if method == http.MethodOptions {
|
||||
require.Equal(t, http.StatusOK, rw.Code)
|
||||
} else {
|
||||
require.Equal(t, http.StatusNoContent, rw.Code)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user