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 appurl.ApplicationURL and true is returned. If the request is not accessing a workspace app, then the next handler is called and false is retu
(rw http.ResponseWriter, r *http.Request, next http.Handler, host string)
| 504 | // accessing a workspace app, then the next handler is called and false is |
| 505 | // returned. |
| 506 | func (s *Server) parseHostname(rw http.ResponseWriter, r *http.Request, next http.Handler, host string) (appurl.ApplicationURL, bool) { |
| 507 | // Check if the hostname matches either of the access URLs. If it does, the |
| 508 | // user was definitely trying to connect to the dashboard/API or a |
| 509 | // path-based app. |
| 510 | if appurl.HostnamesMatch(s.DashboardURL.Hostname(), host) || appurl.HostnamesMatch(s.AccessURL.Hostname(), host) { |
| 511 | next.ServeHTTP(rw, r) |
| 512 | return appurl.ApplicationURL{}, false |
| 513 | } |
| 514 | |
| 515 | // If there are no periods in the hostname, then it can't be a valid |
| 516 | // application URL. |
| 517 | if !strings.Contains(host, ".") { |
| 518 | next.ServeHTTP(rw, r) |
| 519 | return appurl.ApplicationURL{}, false |
| 520 | } |
| 521 | |
| 522 | // Split the subdomain so we can parse the application details and verify it |
| 523 | // matches the configured app hostname later. |
| 524 | subdomain, ok := appurl.ExecuteHostnamePattern(s.HostnameRegex, host) |
| 525 | if !ok { |
| 526 | // Doesn't match the regex, so it's not a valid application URL. |
| 527 | next.ServeHTTP(rw, r) |
| 528 | return appurl.ApplicationURL{}, false |
| 529 | } |
| 530 | |
| 531 | // Check if the request is part of the deprecated logout flow. If so, we |
| 532 | // just redirect to the main access URL. |
| 533 | if subdomain == appLogoutHostname { |
| 534 | http.Redirect(rw, r, s.AccessURL.String(), http.StatusSeeOther) |
| 535 | return appurl.ApplicationURL{}, false |
| 536 | } |
| 537 | |
| 538 | // Parse the application URL from the subdomain. |
| 539 | app, err := appurl.ParseSubdomainAppURL(subdomain) |
| 540 | if err != nil { |
| 541 | site.RenderStaticErrorPage(rw, r, site.ErrorPageData{ |
| 542 | Status: http.StatusBadRequest, |
| 543 | Title: "Invalid Application URL", |
| 544 | Description: fmt.Sprintf("Could not parse subdomain application URL %q: %s", subdomain, err.Error()), |
| 545 | Actions: []site.Action{ |
| 546 | { |
| 547 | URL: s.DashboardURL.String(), |
| 548 | Text: "Back to site", |
| 549 | }, |
| 550 | }, |
| 551 | }) |
| 552 | return appurl.ApplicationURL{}, false |
| 553 | } |
| 554 | |
| 555 | return app, true |
| 556 | } |
| 557 | |
| 558 | func (s *Server) proxyWorkspaceApp(rw http.ResponseWriter, r *http.Request, appToken SignedToken, path string, app appurl.ApplicationURL) { |
| 559 | ctx := r.Context() |
no test coverage detected