diff --git a/server/server.go b/server/server.go index a7bb7f298e..df19f4cfc4 100644 --- a/server/server.go +++ b/server/server.go @@ -1,13 +1,13 @@ package server import ( - "bufio" "context" "embed" "fmt" + "io/fs" "net" "net/http" - "os" + "path" "regexp" "strings" "time" @@ -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(``) -//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(``) - var temp = re.ReplaceAllString(inputString, "") // 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), ``) + return []byte(temp) } func (s *ArgoRolloutsServer) newHTTPServer(ctx context.Context, port int) *http.Server { @@ -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)