Files
teleport/lib/httplib/reverseproxy/handler.go
T
Tiago Silva ebecb59468 Replace graviational/oxy.Forwarder with httputil.ReverseProxy (#27761)
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
2023-06-29 13:50:07 +00:00

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)
}