mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-01-24 05:26:55 +02:00
119 lines
3.2 KiB
Go
119 lines
3.2 KiB
Go
package pagewriter
|
|
|
|
import (
|
|
// Import embed to allow importing default page templates
|
|
_ "embed"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
|
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
|
)
|
|
|
|
const (
|
|
robotsTxtName = "robots.txt"
|
|
)
|
|
|
|
//go:embed robots.txt
|
|
var defaultRobotsTxt []byte
|
|
|
|
// staticPageWriter is used to write static pages.
|
|
type staticPageWriter struct {
|
|
pageGetter *pageGetter
|
|
errorPageWriter *errorPageWriter
|
|
}
|
|
|
|
// WriteRobotsTxt writes the robots.txt content to the response writer.
|
|
func (s *staticPageWriter) WriteRobotsTxt(rw http.ResponseWriter, req *http.Request) {
|
|
s.writePage(rw, req, robotsTxtName)
|
|
}
|
|
|
|
// writePage writes the content of the page to the response writer.
|
|
func (s *staticPageWriter) writePage(rw http.ResponseWriter, req *http.Request, pageName string) {
|
|
_, err := rw.Write(s.pageGetter.getPage(pageName))
|
|
if err != nil {
|
|
logger.Printf("Error writing %q: %v", pageName, err)
|
|
scope := middlewareapi.GetRequestScope(req)
|
|
s.errorPageWriter.WriteErrorPage(rw, ErrorPageOpts{
|
|
Status: http.StatusInternalServerError,
|
|
RequestID: scope.RequestID,
|
|
AppError: err.Error(),
|
|
})
|
|
return
|
|
}
|
|
}
|
|
|
|
func newStaticPageWriter(customDir string, errorWriter *errorPageWriter) (*staticPageWriter, error) {
|
|
pageGetter, err := loadStaticPages(customDir)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not load static pages: %v", err)
|
|
}
|
|
|
|
return &staticPageWriter{
|
|
pageGetter: pageGetter,
|
|
errorPageWriter: errorWriter,
|
|
}, nil
|
|
}
|
|
|
|
// loadStaticPages loads static page content from the custom directory provided.
|
|
// If any file is not provided in the custom directory, the default will be used
|
|
// instead.
|
|
// Statis files include:
|
|
// - robots.txt
|
|
func loadStaticPages(customDir string) (*pageGetter, error) {
|
|
pages := newPageGetter(customDir)
|
|
|
|
if err := pages.addPage(robotsTxtName, defaultRobotsTxt); err != nil {
|
|
return nil, fmt.Errorf("could not add robots.txt: %v", err)
|
|
}
|
|
|
|
return pages, nil
|
|
}
|
|
|
|
// pageGetter is used to load and read page content for static pages.
|
|
type pageGetter struct {
|
|
pages map[string][]byte
|
|
dir string
|
|
}
|
|
|
|
// newPageGetter creates a new page getter for the custom directory.
|
|
func newPageGetter(customDir string) *pageGetter {
|
|
return &pageGetter{
|
|
pages: make(map[string][]byte),
|
|
dir: customDir,
|
|
}
|
|
}
|
|
|
|
// addPage loads a new page into the pageGetter.
|
|
// If the given file name does not exist in the custom directory, the default
|
|
// content will be used instead.
|
|
func (p *pageGetter) addPage(fileName string, defaultContent []byte) error {
|
|
filePath := filepath.Join(p.dir, fileName)
|
|
if p.dir != "" && isFile(filePath) {
|
|
content, err := os.ReadFile(filePath)
|
|
if err != nil {
|
|
return fmt.Errorf("could not read file: %v", err)
|
|
}
|
|
|
|
p.pages[fileName] = content
|
|
return nil
|
|
}
|
|
|
|
// No custom content defined, use the default.
|
|
p.pages[fileName] = defaultContent
|
|
return nil
|
|
}
|
|
|
|
// getPage returns the page content for a given page.
|
|
func (p *pageGetter) getPage(name string) []byte {
|
|
content, ok := p.pages[name]
|
|
if !ok {
|
|
// If the page isn't registered, something went wrong and there is a bug.
|
|
// Tests should make sure this code path is never hit.
|
|
panic(fmt.Sprintf("Static page %q not found", name))
|
|
}
|
|
return content
|
|
}
|