Skip to content

Commit e545ad1

Browse files
committed
feat: add switch http(s) button to error page
1 parent 848ea7e commit e545ad1

File tree

3 files changed

+64
-12
lines changed

3 files changed

+64
-12
lines changed

coderd/tailnet.go

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import (
44
"bufio"
55
"context"
66
"crypto/tls"
7+
"fmt"
78
"net"
89
"net/http"
910
"net/http/httputil"
1011
"net/netip"
1112
"net/url"
13+
"strconv"
14+
"strings"
1215
"sync"
1316
"sync/atomic"
1417
"time"
@@ -23,6 +26,8 @@ import (
2326
"cdr.dev/slog"
2427
"github.com/coder/coder/v2/coderd/tracing"
2528
"github.com/coder/coder/v2/coderd/workspaceapps"
29+
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
30+
"github.com/coder/coder/v2/codersdk"
2631
"github.com/coder/coder/v2/codersdk/workspacesdk"
2732
"github.com/coder/coder/v2/site"
2833
"github.com/coder/coder/v2/tailnet"
@@ -351,13 +356,49 @@ func (s *ServerTailnet) ReverseProxy(targetURL, dashboardURL *url.URL, agentID u
351356
tgt.Host = net.JoinHostPort(tailnet.IPFromUUID(agentID).String(), port)
352357

353358
proxy := httputil.NewSingleHostReverseProxy(&tgt)
354-
proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
359+
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()
390+
if strings.Contains(theErr.Error(), "tls:") {
391+
desc = fmt.Sprintf("This error seems to be due to a protocol mistake, please try switching to %s. \n%s", switchProtoScheme, theErr.Error())
392+
}
393+
355394
site.RenderStaticErrorPage(w, r, site.ErrorPageData{
356-
Status: http.StatusBadGateway,
357-
Title: "Bad Gateway",
358-
Description: "Failed to proxy request to application: " + err.Error(),
359-
RetryEnabled: true,
360-
DashboardURL: dashboardURL.String(),
395+
Status: http.StatusBadGateway,
396+
Title: "Bad Gateway",
397+
Description: desc,
398+
RetryEnabled: true,
399+
DashboardURL: dashboardURL.String(),
400+
SwitchProtocolLink: switchProtoLink,
401+
SwitchProtocolTarget: switchProtoScheme,
361402
})
362403
}
363404
proxy.Director = s.director(agentID, proxy.Director)

site/site.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -786,12 +786,14 @@ func extractBin(dest string, r io.Reader) (numExtracted int, err error) {
786786
type ErrorPageData struct {
787787
Status int
788788
// HideStatus will remove the status code from the page.
789-
HideStatus bool
790-
Title string
791-
Description string
792-
RetryEnabled bool
793-
DashboardURL string
794-
Warnings []string
789+
HideStatus bool
790+
Title string
791+
Description string
792+
RetryEnabled bool
793+
DashboardURL string
794+
Warnings []string
795+
SwitchProtocolLink string
796+
SwitchProtocolTarget codersdk.WorkspaceAgentPortShareProtocol
795797

796798
RenderDescriptionMarkdown bool
797799
}

site/static/error.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ <h1>
167167
{{- if not .Error.HideStatus }}{{ .Error.Status }} - {{end}}{{
168168
.Error.Title }}
169169
</h1>
170+
{{- if .Error.SwitchProtocolLink }}
171+
<p>It looks like the error was due to a protocol mismatch. Do you want to try using {{ .Error.SwitchProtocolTarget }}?</p>
172+
<div class="button-group">
173+
<a href="{{ .Error.SwitchProtocolLink }}">Use {{ .Error.SwitchProtocolTarget }}</a>
174+
</div>
175+
{{ end }}
170176
{{- if .Error.RenderDescriptionMarkdown }} {{ .ErrorDescriptionHTML }} {{
171177
else }}
172178
<p>{{ .Error.Description }}</p>
@@ -198,6 +204,9 @@ <h3>Warnings</h3>
198204
{{- if .Error.RetryEnabled }}
199205
<button onclick="window.location.reload()">Retry</button>
200206
{{ end }}
207+
{{- if .Error.SwitchProtocolLink }}
208+
<a href="{{ .Error.SwitchProtocolLink }}">Switch to {{ .Error.SwitchProtocolTarget }}</a>
209+
{{ end }}
201210
<a href="{{ .Error.DashboardURL }}">Back to site</a>
202211
</div>
203212
</div>

0 commit comments

Comments
 (0)