MCPcopy Index your code
hub / github.com/coder/coder / ReverseProxy

Method ReverseProxy

coderd/tailnet.go:189–251  ·  view source on GitHub ↗
(targetURL, dashboardURL *url.URL, agentID uuid.UUID, app appurl.ApplicationURL, wildcardHostname string)

Source from the content-addressed store, hash-verified

187}
188
189func (s *ServerTailnet) ReverseProxy(targetURL, dashboardURL *url.URL, agentID uuid.UUID, app appurl.ApplicationURL, wildcardHostname string) *httputil.ReverseProxy {
190 // Rewrite the targetURL's Host to point to the agent's IP. This is
191 // necessary because due to TCP connection caching, each agent needs to be
192 // addressed invidivually. Otherwise, all connections get dialed as
193 // "localhost:port", causing connections to be shared across agents.
194 tgt := *targetURL
195 _, port, _ := net.SplitHostPort(tgt.Host)
196 tgt.Host = net.JoinHostPort(tailnet.TailscaleServicePrefix.AddrFromUUID(agentID).String(), port)
197
198 proxy := httputil.NewSingleHostReverseProxy(&tgt)
199 proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, theErr error) {
200 var (
201 desc = "Failed to proxy request to application: " + theErr.Error()
202 additionalInfo = ""
203 actions = []site.Action{}
204 )
205
206 var tlsError tls.RecordHeaderError
207 if (errors.As(theErr, &tlsError) && tlsError.Msg == "first record does not look like a TLS handshake") ||
208 errors.Is(theErr, http.ErrSchemeMismatch) {
209 // If the error is due to an HTTP/HTTPS mismatch, we can provide a
210 // more helpful error message with redirect buttons.
211 switchURL := url.URL{
212 Scheme: dashboardURL.Scheme,
213 }
214 _, protocol, isPort := app.PortInfo()
215 if isPort {
216 targetProtocol := "https"
217 if protocol == "https" {
218 targetProtocol = "http"
219 }
220 app = app.ChangePortProtocol(targetProtocol)
221
222 switchURL.Host = fmt.Sprintf("%s%s", app.String(), strings.TrimPrefix(wildcardHostname, "*"))
223 actions = append(actions, site.Action{
224 URL: switchURL.String(),
225 Text: fmt.Sprintf("Switch to %s", strings.ToUpper(targetProtocol)),
226 })
227 additionalInfo += fmt.Sprintf("This error seems to be due to an app protocol mismatch, try switching to %s.", strings.ToUpper(targetProtocol))
228 }
229 }
230
231 site.RenderStaticErrorPage(w, r, site.ErrorPageData{
232 Status: http.StatusBadGateway,
233 Title: "Bad Gateway",
234 Description: desc,
235 Actions: append(actions, []site.Action{
236 {
237 Text: "Retry",
238 },
239 {
240 URL: dashboardURL.String(),
241 Text: "Back to site",
242 },
243 }...),
244 AdditionalInfo: additionalInfo,
245 })
246 }

Callers

nothing calls this directly

Calls 9

directorMethod · 0.95
RenderStaticErrorPageFunction · 0.92
AddrFromUUIDMethod · 0.80
AsMethod · 0.80
PortInfoMethod · 0.80
ChangePortProtocolMethod · 0.80
StringMethod · 0.45
ErrorMethod · 0.45
IsMethod · 0.45

Tested by

no test coverage detected