mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: move app URL parsing to its own package (#11651)
* chore: move app url parsing to it's own package
This commit is contained in:
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/httpmw"
|
||||
"github.com/coder/coder/v2/coderd/tracing"
|
||||
"github.com/coder/coder/v2/coderd/util/slice"
|
||||
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/site"
|
||||
)
|
||||
@@ -96,7 +97,7 @@ type Server struct {
|
||||
// E.g. "*.apps.coder.com" or "*-apps.coder.com".
|
||||
Hostname string
|
||||
// HostnameRegex contains the regex version of Hostname as generated by
|
||||
// httpapi.CompileHostnamePattern(). It MUST be set if Hostname is set.
|
||||
// appurl.CompileHostnamePattern(). It MUST be set if Hostname is set.
|
||||
HostnameRegex *regexp.Regexp
|
||||
RealIPConfig *httpmw.RealIPConfig
|
||||
|
||||
@@ -329,7 +330,7 @@ func (s *Server) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
|
||||
// 3. If the request hostname matches api.AccessURL then we pass on.
|
||||
// 5. We split the subdomain into the subdomain and the "rest". If there are no
|
||||
// periods in the hostname then we pass on.
|
||||
// 5. We parse the subdomain into a httpapi.ApplicationURL struct. If we
|
||||
// 5. We parse the subdomain into a appurl.ApplicationURL struct. If we
|
||||
// encounter an error:
|
||||
// a. If the "rest" does not match api.Hostname then we pass on;
|
||||
// b. Otherwise, we return a 400.
|
||||
@@ -428,43 +429,43 @@ func (s *Server) HandleSubdomain(middlewares ...func(http.Handler) http.Handler)
|
||||
|
||||
// parseHostname will return if a given request is attempting to access a
|
||||
// workspace app via a subdomain. If it is, the hostname of the request is parsed
|
||||
// into an httpapi.ApplicationURL and true is returned. If the request is not
|
||||
// into an appurl.ApplicationURL and true is returned. If the request is not
|
||||
// accessing a workspace app, then the next handler is called and false is
|
||||
// returned.
|
||||
func (s *Server) parseHostname(rw http.ResponseWriter, r *http.Request, next http.Handler, host string) (httpapi.ApplicationURL, bool) {
|
||||
func (s *Server) parseHostname(rw http.ResponseWriter, r *http.Request, next http.Handler, host string) (appurl.ApplicationURL, bool) {
|
||||
// Check if the hostname matches either of the access URLs. If it does, the
|
||||
// user was definitely trying to connect to the dashboard/API or a
|
||||
// path-based app.
|
||||
if httpapi.HostnamesMatch(s.DashboardURL.Hostname(), host) || httpapi.HostnamesMatch(s.AccessURL.Hostname(), host) {
|
||||
if appurl.HostnamesMatch(s.DashboardURL.Hostname(), host) || appurl.HostnamesMatch(s.AccessURL.Hostname(), host) {
|
||||
next.ServeHTTP(rw, r)
|
||||
return httpapi.ApplicationURL{}, false
|
||||
return appurl.ApplicationURL{}, false
|
||||
}
|
||||
|
||||
// If there are no periods in the hostname, then it can't be a valid
|
||||
// application URL.
|
||||
if !strings.Contains(host, ".") {
|
||||
next.ServeHTTP(rw, r)
|
||||
return httpapi.ApplicationURL{}, false
|
||||
return appurl.ApplicationURL{}, false
|
||||
}
|
||||
|
||||
// Split the subdomain so we can parse the application details and verify it
|
||||
// matches the configured app hostname later.
|
||||
subdomain, ok := httpapi.ExecuteHostnamePattern(s.HostnameRegex, host)
|
||||
subdomain, ok := appurl.ExecuteHostnamePattern(s.HostnameRegex, host)
|
||||
if !ok {
|
||||
// Doesn't match the regex, so it's not a valid application URL.
|
||||
next.ServeHTTP(rw, r)
|
||||
return httpapi.ApplicationURL{}, false
|
||||
return appurl.ApplicationURL{}, false
|
||||
}
|
||||
|
||||
// Check if the request is part of the deprecated logout flow. If so, we
|
||||
// just redirect to the main access URL.
|
||||
if subdomain == appLogoutHostname {
|
||||
http.Redirect(rw, r, s.AccessURL.String(), http.StatusSeeOther)
|
||||
return httpapi.ApplicationURL{}, false
|
||||
return appurl.ApplicationURL{}, false
|
||||
}
|
||||
|
||||
// Parse the application URL from the subdomain.
|
||||
app, err := httpapi.ParseSubdomainAppURL(subdomain)
|
||||
app, err := appurl.ParseSubdomainAppURL(subdomain)
|
||||
if err != nil {
|
||||
site.RenderStaticErrorPage(rw, r, site.ErrorPageData{
|
||||
Status: http.StatusBadRequest,
|
||||
@@ -473,7 +474,7 @@ func (s *Server) parseHostname(rw http.ResponseWriter, r *http.Request, next htt
|
||||
RetryEnabled: false,
|
||||
DashboardURL: s.DashboardURL.String(),
|
||||
})
|
||||
return httpapi.ApplicationURL{}, false
|
||||
return appurl.ApplicationURL{}, false
|
||||
}
|
||||
|
||||
return app, true
|
||||
|
||||
Reference in New Issue
Block a user