Skip to content

Commit 4ff2b20

Browse files
committed
testing error cases
1 parent 1c3af6e commit 4ff2b20

File tree

3 files changed

+39
-47
lines changed

3 files changed

+39
-47
lines changed

coderd/tailnet.go

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bufio"
55
"context"
66
"crypto/tls"
7-
"fmt"
87
"net"
98
"net/http"
109
"net/http/httputil"
@@ -27,7 +26,6 @@ import (
2726
"github.com/coder/coder/v2/coderd/tracing"
2827
"github.com/coder/coder/v2/coderd/workspaceapps"
2928
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
30-
"github.com/coder/coder/v2/codersdk"
3129
"github.com/coder/coder/v2/codersdk/workspacesdk"
3230
"github.com/coder/coder/v2/site"
3331
"github.com/coder/coder/v2/tailnet"
@@ -346,7 +344,7 @@ type ServerTailnet struct {
346344
totalConns *prometheus.CounterVec
347345
}
348346

349-
func (s *ServerTailnet) ReverseProxy(targetURL, dashboardURL *url.URL, agentID uuid.UUID) *httputil.ReverseProxy {
347+
func (s *ServerTailnet) ReverseProxy(targetURL, dashboardURL *url.URL, agentID uuid.UUID, app appurl.ApplicationURL) *httputil.ReverseProxy {
350348
// Rewrite the targetURL's Host to point to the agent's IP. This is
351349
// necessary because due to TCP connection caching, each agent needs to be
352350
// addressed invidivually. Otherwise, all connections get dialed as
@@ -357,48 +355,34 @@ func (s *ServerTailnet) ReverseProxy(targetURL, dashboardURL *url.URL, agentID u
357355

358356
proxy := httputil.NewSingleHostReverseProxy(&tgt)
359357
proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, theErr error) {
360-
var (
361-
switchProtoScheme codersdk.WorkspaceAgentPortShareProtocol
362-
switchProtoLink = ""
363-
)
364-
au, err := appurl.ParseSubdomainAppURL(tgt.String())
365-
if err != nil {
366-
site.RenderStaticErrorPage(w, r, site.ErrorPageData{
367-
Status: http.StatusBadGateway,
368-
Title: "Bad Gateway",
369-
Description: "Failed to proxy request to application: " + err.Error(),
370-
RetryEnabled: true,
371-
DashboardURL: dashboardURL.String(),
372-
})
373-
return
374-
}
375-
if strings.HasSuffix(au.AppSlugOrPort, "s") {
376-
p := strings.TrimSuffix(au.AppSlugOrPort, "s")
377-
_, err = strconv.ParseInt(p, 10, 64)
378-
if err == nil {
379-
au.AppSlugOrPort = p
380-
switchProtoLink = au.String()
381-
switchProtoScheme = codersdk.WorkspaceAgentPortShareProtocolHTTP
382-
}
383-
} else {
384-
au.AppSlugOrPort += "s"
385-
switchProtoLink = au.String()
386-
switchProtoScheme = codersdk.WorkspaceAgentPortShareProtocolHTTPS
387-
}
388-
389-
desc := "Failed to proxy request to application: " + theErr.Error()
358+
desc := "Failed to proxy request to application: \n\n" + theErr.Error()
359+
descAddition := ""
390360
if strings.Contains(theErr.Error(), "tls:") {
391-
desc = fmt.Sprintf("This error seems to be due to a protocol mismatch, please try switching to %s. \n%s", switchProtoScheme, theErr.Error())
361+
// If the error is due to an HTTP/HTTPS mismatch, we can provide a
362+
// more helpful error message with redirect buttons.
363+
if strings.HasSuffix(app.AppSlugOrPort, "s") {
364+
_, err := strconv.ParseInt(app.AppSlugOrPort, 10, 64)
365+
if err == nil {
366+
app.AppSlugOrPort = strings.TrimSuffix(app.AppSlugOrPort, "s")
367+
descAddition += "This error seems to be due to an HTTPS mismatch, please try switching to HTTP."
368+
}
369+
} else {
370+
_, err := strconv.ParseInt(app.AppSlugOrPort, 10, 64)
371+
if err == nil {
372+
app.AppSlugOrPort += "s"
373+
descAddition += "This error seems to be due to an HTTP mismatch, please try switching to HTTPS."
374+
}
375+
}
392376
}
377+
desc += descAddition
393378

394379
site.RenderStaticErrorPage(w, r, site.ErrorPageData{
395-
Status: http.StatusBadGateway,
396-
Title: "Bad Gateway",
397-
Description: desc,
398-
RetryEnabled: true,
399-
DashboardURL: dashboardURL.String(),
400-
SwitchProtocolLink: switchProtoLink,
401-
SwitchProtocolTarget: switchProtoScheme,
380+
Status: http.StatusBadGateway,
381+
Title: "Bad Gateway Dood",
382+
Description: desc,
383+
RetryEnabled: true,
384+
DashboardURL: dashboardURL.String(),
385+
SwitchProtocolLink: app.String(),
402386
})
403387
}
404388
proxy.Director = s.director(agentID, proxy.Director)

coderd/workspaceapps/proxy.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ var nonCanonicalHeaders = map[string]string{
6666
type AgentProvider interface {
6767
// ReverseProxy returns an httputil.ReverseProxy for proxying HTTP requests
6868
// to the specified agent.
69-
ReverseProxy(targetURL, dashboardURL *url.URL, agentID uuid.UUID) *httputil.ReverseProxy
69+
ReverseProxy(targetURL, dashboardURL *url.URL, agentID uuid.UUID, app appurl.ApplicationURL) *httputil.ReverseProxy
7070

7171
// AgentConn returns a new connection to the specified agent.
7272
AgentConn(ctx context.Context, agentID uuid.UUID) (_ *workspacesdk.AgentConn, release func(), _ error)
@@ -314,7 +314,7 @@ func (s *Server) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
314314
return
315315
}
316316

317-
s.proxyWorkspaceApp(rw, r, *token, chiPath)
317+
s.proxyWorkspaceApp(rw, r, *token, chiPath, appurl.ApplicationURL{})
318318
}
319319

320320
// HandleSubdomain handles subdomain-based application proxy requests (aka.
@@ -417,7 +417,7 @@ func (s *Server) HandleSubdomain(middlewares ...func(http.Handler) http.Handler)
417417
if !ok {
418418
return
419419
}
420-
s.proxyWorkspaceApp(rw, r, *token, r.URL.Path)
420+
s.proxyWorkspaceApp(rw, r, *token, r.URL.Path, app)
421421
})).ServeHTTP(rw, r.WithContext(ctx))
422422
})
423423
}
@@ -476,7 +476,7 @@ func (s *Server) parseHostname(rw http.ResponseWriter, r *http.Request, next htt
476476
return app, true
477477
}
478478

479-
func (s *Server) proxyWorkspaceApp(rw http.ResponseWriter, r *http.Request, appToken SignedToken, path string) {
479+
func (s *Server) proxyWorkspaceApp(rw http.ResponseWriter, r *http.Request, appToken SignedToken, path string, app appurl.ApplicationURL) {
480480
ctx := r.Context()
481481

482482
// Filter IP headers from untrusted origins.
@@ -546,7 +546,15 @@ func (s *Server) proxyWorkspaceApp(rw http.ResponseWriter, r *http.Request, appT
546546
r.URL.Path = path
547547
appURL.RawQuery = ""
548548

549-
proxy := s.AgentProvider.ReverseProxy(appURL, s.DashboardURL, appToken.AgentID)
549+
appURL.Scheme = "http"
550+
if strings.HasSuffix(app.AppSlugOrPort, "s") {
551+
_, err = strconv.ParseInt(strings.TrimSuffix(app.AppSlugOrPort, "s"), 10, 64)
552+
if err == nil {
553+
appURL.Scheme = "https"
554+
}
555+
}
556+
557+
proxy := s.AgentProvider.ReverseProxy(appURL, s.DashboardURL, appToken.AgentID, app)
550558

551559
proxy.ModifyResponse = func(r *http.Response) error {
552560
r.Header.Del(httpmw.AccessControlAllowOriginHeader)

site/static/error.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ <h3>Warnings</h3>
199199
<button onclick="window.location.reload()">Retry</button>
200200
{{ end }}
201201
{{- if .Error.SwitchProtocolLink }}
202-
<a href="{{ .Error.SwitchProtocolLink }}">Switch to {{ .Error.SwitchProtocolTarget }}</a>
202+
<a href="{{ .Error.SwitchProtocolLink }}">Switch to HTTPX</a>
203203
{{ end }}
204204
<a href="{{ .Error.DashboardURL }}">Back to site</a>
205205
</div>

0 commit comments

Comments
 (0)