2020-05-26 19:53:10 +01:00
|
|
|
package upstream
|
|
|
|
|
2020-05-27 23:58:57 +01:00
|
|
|
import (
|
|
|
|
"net/http"
|
2023-09-21 17:34:51 +01:00
|
|
|
"net/url"
|
2020-05-27 23:58:57 +01:00
|
|
|
"runtime"
|
|
|
|
"strings"
|
2021-03-06 09:27:16 -08:00
|
|
|
|
2023-09-21 17:34:51 +01:00
|
|
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
|
|
|
|
|
2021-03-06 09:27:16 -08:00
|
|
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
|
2020-05-27 23:58:57 +01:00
|
|
|
)
|
2020-05-26 19:53:10 +01:00
|
|
|
|
|
|
|
const fileScheme = "file"
|
|
|
|
|
|
|
|
// newFileServer creates a new fileServer that can serve requests
|
|
|
|
// to a file system location.
|
2023-09-21 17:34:51 +01:00
|
|
|
func newFileServer(upstream options.Upstream, fileSystemPath string) http.Handler {
|
|
|
|
handler := newFileServerForPath(fileSystemPath)
|
|
|
|
|
|
|
|
if upstream.RewriteTarget == "" {
|
|
|
|
// if the upstream does not have a rewrite target, strip off the Path prefix
|
|
|
|
// (so e.g. a request for /static/some-file.html looks for some-file.html
|
|
|
|
// relative to the fileSystemPath rather than static/some-file.html).
|
|
|
|
handler = http.StripPrefix(upstream.Path, handler)
|
|
|
|
} else {
|
|
|
|
// if the upstream *does* have a rewrite target then that means the target
|
|
|
|
// path relative to the fileSystemPath will be the one in the (rewritten)
|
|
|
|
// RequestURI.
|
|
|
|
handler = requestURIToURL(handler)
|
|
|
|
}
|
2020-05-26 19:53:10 +01:00
|
|
|
return &fileServer{
|
2023-09-21 17:34:51 +01:00
|
|
|
upstream: upstream.ID,
|
|
|
|
handler: handler,
|
2020-05-26 19:53:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// newFileServerForPath creates a http.Handler to serve files from the filesystem
|
2023-09-21 17:34:51 +01:00
|
|
|
func newFileServerForPath(filesystemPath string) http.Handler {
|
2020-05-27 23:58:57 +01:00
|
|
|
// Windows fileSSystemPath will be be prefixed with `/`, eg`/C:/...,
|
|
|
|
// if they were parsed by url.Parse`
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
filesystemPath = strings.TrimPrefix(filesystemPath, "/")
|
|
|
|
}
|
|
|
|
|
2023-09-21 17:34:51 +01:00
|
|
|
return http.FileServer(http.Dir(filesystemPath))
|
|
|
|
}
|
|
|
|
|
|
|
|
// requestURIToURL returns a Handler that replaces the URL in its request with
|
|
|
|
// the result of parsing req.RequestURI. This is necessary for file handlers
|
|
|
|
// that have a rewrite target, since http.FileServer uses req.URL.Path when
|
|
|
|
// looking for the target file, but the rewrite handler only updates the
|
|
|
|
// RequestURI, leaving the original path in the URL.
|
|
|
|
func requestURIToURL(handler http.Handler) http.Handler {
|
|
|
|
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
|
|
|
reqURL, err := url.ParseRequestURI(req.RequestURI)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(rw, "500 Internal Server Error", http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
req.URL = reqURL
|
|
|
|
handler.ServeHTTP(rw, req)
|
|
|
|
})
|
2020-05-26 19:53:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// fileServer represents a single filesystem upstream proxy
|
|
|
|
type fileServer struct {
|
|
|
|
upstream string
|
|
|
|
handler http.Handler
|
|
|
|
}
|
|
|
|
|
|
|
|
// ServeHTTP proxies requests to the upstream provider while signing the
|
|
|
|
// request headers
|
|
|
|
func (u *fileServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
2021-03-06 09:27:16 -08:00
|
|
|
scope := middleware.GetRequestScope(req)
|
|
|
|
// If scope is nil, this will panic.
|
|
|
|
// A scope should always be injected before this handler is called.
|
|
|
|
scope.Upstream = u.upstream
|
|
|
|
|
2020-05-26 19:53:10 +01:00
|
|
|
u.handler.ServeHTTP(rw, req)
|
|
|
|
}
|