mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-04 02:21:02 +08:00
This PR replaces the usage of `gravitational/oxy.Forwarder` in our codebase with `httputil.ReverseProxy`.
`httputil.ReverseProxy` is part of Go's standard library and thus it is
maintained by the Go team. Converting everything to use the std lib
allows us to drop our `oxy` fork.
There are some operational changes between the two versions:
1. `httputil.ReverseProxy` handles WebSockets upgrades internally and
reuses the `Transport` provided for the initial request. Thus, it does
not require any special dialer or rewriter mechanisms for WebSockets only.
2. `httputil.ReverseProxy` calls the `ErrorHandler` with the request
after it was rewritten and after roundtrip was called. This was a
problem because our `web.transport` deletes Teleport associated
cookies and when the request failed, the request received by the
`ErrorHandler` missed the cookies to generate a new session. This was
fixed by cloning the request at `web.transport` round tripper.
3. `httputil.ReverseProxy` uses std's `log.Logger`. `logrus` exposes a
method `Writer` that allows it to be used with standard lib logger.
The API is similar to what our `oxy` fork has available.
Fixes #27412
63 lines
1.8 KiB
Go
63 lines
1.8 KiB
Go
/*
|
|
Copyright 2023 Gravitational, Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package reverseproxy
|
|
|
|
import (
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
)
|
|
|
|
// ErrorHandler is an interface for handling errors.
|
|
type ErrorHandler interface {
|
|
ServeHTTP(w http.ResponseWriter, req *http.Request, err error)
|
|
}
|
|
|
|
// DefaultHandler is the default error handler.
|
|
var DefaultHandler ErrorHandler = &defaultHandler{}
|
|
|
|
// defaultHandler is the default error handler.
|
|
type defaultHandler struct{}
|
|
|
|
// ServeHTTP writes the error message to the response.
|
|
func (e *defaultHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, err error) {
|
|
statusCode := http.StatusInternalServerError
|
|
switch {
|
|
case err == io.EOF:
|
|
statusCode = http.StatusBadGateway
|
|
default:
|
|
switch e, ok := err.(net.Error); {
|
|
case ok && e.Timeout():
|
|
statusCode = http.StatusGatewayTimeout
|
|
case ok:
|
|
statusCode = http.StatusBadGateway
|
|
}
|
|
}
|
|
w.WriteHeader(statusCode)
|
|
w.Write([]byte(http.StatusText(statusCode)))
|
|
}
|
|
|
|
// ErrorHandlerFunc is an adapter to allow the use of ordinary functions as
|
|
// error handlers. If f is a function with the appropriate signature,
|
|
// ErrorHandlerFunc(f) is a ErrorHandler that calls f.
|
|
type ErrorHandlerFunc func(http.ResponseWriter, *http.Request, error)
|
|
|
|
// ServeHTTP calls f(w, r).
|
|
func (f ErrorHandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request, err error) {
|
|
f(w, r, err)
|
|
}
|