Skip to content

Commit

Permalink
fix: rootPath support so that it uses the embedded files system (#2198)
Browse files Browse the repository at this point in the history
* fix: rootPath support so that it uses the embeded files system

Signed-off-by: zachaller <zachaller@hotmail.com>

* Catch edge cases and make sure we always server index.html on not found

Signed-off-by: zachaller <zachaller@hotmail.com>

* turn path.Clean into var

Signed-off-by: zachaller <zachaller@hotmail.com>

Signed-off-by: zachaller <zachaller@hotmail.com>
  • Loading branch information
zachaller authored and leoluz committed Aug 17, 2022
1 parent 0ec5ac1 commit 53f4105
Showing 1 changed file with 95 additions and 43 deletions.
138 changes: 95 additions & 43 deletions server/server.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package server

import (
"bufio"
"context"
"embed"
"fmt"
"io/fs"
"net"
"net/http"
"os"
"path"
"regexp"
"strings"
"time"
Expand Down Expand Up @@ -81,45 +81,11 @@ func NewServer(o ServerOptions) *ArgoRolloutsServer {
return &ArgoRolloutsServer{Options: o}
}

type spaFileSystem struct {
root http.FileSystem
}

func (fs *spaFileSystem) Open(name string) (http.File, error) {
f, err := fs.root.Open(name)
if os.IsNotExist(err) {
return fs.root.Open("index.html")
}
return f, err
}
var re = regexp.MustCompile(`<base href=".*".*/>`)

//This function helps in changing base href to point to rootpath as basepath, we are making modification in only server/static/index.html file
func withRootPath(rootpath string) {
inputFile, inputError := os.Open("./server/static/index.html")
if inputError != nil {
log.Error("An error occurred on opening the inputfile\n" +
"Does the file exist?\n" +
"Have you got access to it?\n")
panic(inputError) // exit on error
}
defer inputFile.Close()
inputReader := bufio.NewReader(inputFile)
inputString, _ := inputReader.ReadString('\n')
re := regexp.MustCompile(`<base href="/[^/]*/*"/>`)
var temp = re.ReplaceAllString(inputString, "<base href=\"/"+rootpath+"/\"/>") // href="/root/"

outputFile, _ := os.OpenFile("./server/static/index.html", os.O_TRUNC|os.O_WRONLY, 0666)
defer outputFile.Close()
outputWriter := bufio.NewWriter(outputFile)
outputWriter.WriteString(temp)
outputWriter.Flush()

//To make ui/dist/index.html file consistent with server/static/index.html
outputFileDist, _ := os.OpenFile("./ui/dist/app/index.html", os.O_TRUNC|os.O_WRONLY, 0666)
defer outputFileDist.Close()
outputWriterDist := bufio.NewWriter(outputFileDist)
outputWriterDist.WriteString(temp)
outputWriterDist.Flush()
func withRootPath(fileContent []byte, rootpath string) []byte {
var temp = re.ReplaceAllString(string(fileContent), `<base href="`+path.Clean("/"+rootpath)+`/" />`)
return []byte(temp)
}

func (s *ArgoRolloutsServer) newHTTPServer(ctx context.Context, port int) *http.Server {
Expand Down Expand Up @@ -153,15 +119,101 @@ func (s *ArgoRolloutsServer) newHTTPServer(ctx context.Context, port int) *http.

var handler http.Handler = gwmux

withRootPath(s.Options.RootPath)

mux.Handle("/api/", handler)

mux.Handle("/"+s.Options.RootPath+"/", http.StripPrefix("/"+s.Options.RootPath+"/", http.FileServer(http.Dir("./server/static"))))
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
requestedURI := path.Clean(r.RequestURI)
rootPath := path.Clean("/" + s.Options.RootPath)
//If the rootPath is not in the prefix 404
if !strings.HasPrefix(requestedURI, rootPath) {
http.NotFound(w, r)
return
}
//If the rootPath is the requestedURI, serve index.html
if requestedURI == rootPath {
fileBytes, openErr := s.readIndexHtml()
if openErr != nil {
log.Errorf("Error opening file index.html: %v", openErr)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(fileBytes)
return
}

embedPath := path.Join("static", strings.TrimPrefix(requestedURI, rootPath))
file, openErr := static.Open(embedPath)
if openErr != nil {
fErr := openErr.(*fs.PathError)
//If the file is not found, serve index.html
if fErr.Err == fs.ErrNotExist {
fileBytes, openErr := s.readIndexHtml()
if openErr != nil {
log.Errorf("Error opening file index.html: %v", openErr)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(fileBytes)
return
} else {
log.Errorf("Error opening file %s: %v", embedPath, openErr)
w.WriteHeader(http.StatusInternalServerError)
return
}
}
defer file.Close()

stat, statErr := file.Stat()
if statErr != nil {
log.Errorf("Failed to stat file or dir %s: %v", embedPath, err)
w.WriteHeader(http.StatusInternalServerError)
return
}

fileBytes := make([]byte, stat.Size())
_, err = file.Read(fileBytes)
if err != nil {
log.Errorf("Failed to read file %s: %v", embedPath, err)
w.WriteHeader(http.StatusInternalServerError)
return
}

w.Write(fileBytes)
})

return &httpS
}

func (s *ArgoRolloutsServer) readIndexHtml() ([]byte, error) {
file, err := static.Open("static/index.html")
if err != nil {
log.Errorf("Failed to open file %s: %v", "static/index.html", err)
return nil, err
}
defer func() {
if file != nil {
if err := file.Close(); err != nil {
log.Errorf("Error closing file: %v", err)
}
}
}()

stat, err := file.Stat()
if err != nil {
log.Errorf("Failed to stat file or dir %s: %v", "static/index.html", err)
return nil, err
}

fileBytes := make([]byte, stat.Size())
_, err = file.Read(fileBytes)
if err != nil {
log.Errorf("Failed to read file %s: %v", "static/index.html", err)
return nil, err
}

return withRootPath(fileBytes, s.Options.RootPath), nil
}

func (s *ArgoRolloutsServer) newGRPCServer() *grpc.Server {
grpcS := grpc.NewServer()
var rolloutsServer rollout.RolloutServiceServer = NewServer(s.Options)
Expand Down

0 comments on commit 53f4105

Please sign in to comment.