(rw http.ResponseWriter, r *http.Request, appToken SignedToken, path string, app appurl.ApplicationURL)
| 556 | } |
| 557 | |
| 558 | func (s *Server) proxyWorkspaceApp(rw http.ResponseWriter, r *http.Request, appToken SignedToken, path string, app appurl.ApplicationURL) { |
| 559 | ctx := r.Context() |
| 560 | |
| 561 | // Filter IP headers from untrusted origins. |
| 562 | httpmw.FilterUntrustedOriginHeaders(s.RealIPConfig, r) |
| 563 | |
| 564 | // Ensure proper IP headers get sent to the forwarded application. |
| 565 | err := httpmw.EnsureXForwardedForHeader(r) |
| 566 | if err != nil { |
| 567 | httpapi.InternalServerError(rw, err) |
| 568 | return |
| 569 | } |
| 570 | |
| 571 | appURL, err := url.Parse(appToken.AppURL) |
| 572 | if err != nil { |
| 573 | site.RenderStaticErrorPage(rw, r, site.ErrorPageData{ |
| 574 | Status: http.StatusBadRequest, |
| 575 | Title: "Bad Request", |
| 576 | Description: fmt.Sprintf("Application has an invalid URL %q: %s", appToken.AppURL, err.Error()), |
| 577 | Actions: []site.Action{ |
| 578 | { |
| 579 | Text: "Retry", |
| 580 | }, |
| 581 | { |
| 582 | URL: s.DashboardURL.String(), |
| 583 | Text: "Back to site", |
| 584 | }, |
| 585 | }, |
| 586 | }) |
| 587 | return |
| 588 | } |
| 589 | |
| 590 | // Verify that the port is allowed. See the docs above |
| 591 | // `codersdk.MinimumListeningPort` for more details. |
| 592 | port := appURL.Port() |
| 593 | if port != "" { |
| 594 | portInt, err := strconv.Atoi(port) |
| 595 | if err != nil { |
| 596 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 597 | Message: fmt.Sprintf("App URL %q has an invalid port %q.", appToken.AppURL, port), |
| 598 | Detail: err.Error(), |
| 599 | }) |
| 600 | return |
| 601 | } |
| 602 | |
| 603 | if portInt < workspacesdk.AgentMinimumListeningPort { |
| 604 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 605 | Message: fmt.Sprintf("Application port %d is not permitted. Coder reserves ports less than %d for internal use.", |
| 606 | portInt, workspacesdk.AgentMinimumListeningPort, |
| 607 | ), |
| 608 | }) |
| 609 | return |
| 610 | } |
| 611 | } |
| 612 | |
| 613 | // Ensure path and query parameter correctness. |
| 614 | if path == "" { |
| 615 | // Web applications typically request paths relative to the |
no test coverage detected