| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you 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 openserverless |
| |
| import ( |
| "flag" |
| "fmt" |
| "log" |
| "net" |
| "net/http" |
| "net/http/httputil" |
| "net/url" |
| "os" |
| |
| "github.com/pkg/browser" |
| ) |
| |
| func Serve(olarisDir string, args []string) error { |
| flag := flag.NewFlagSet("serve", flag.ExitOnError) |
| flag.Usage = func() { |
| fmt.Println(`Serve a local directory on http://localhost:9768. You can change port with the OPS_PORT environment variable. |
| |
| Usage: |
| ops -serve [options] <dir> |
| |
| Options: |
| -h, --help Print help message |
| --no-open Do not open browser automatically |
| --proxy <proxy> Use proxy server |
| `) |
| } |
| // Define command line flags |
| |
| var helpFlag bool |
| var noBrowserFlag bool |
| var proxyFlag string |
| |
| flag.BoolVar(&helpFlag, "h", false, "Print help message") |
| flag.BoolVar(&helpFlag, "help", false, "Print help message") |
| flag.BoolVar(&noBrowserFlag, "no-open", false, "Do not open browser") |
| flag.StringVar(&proxyFlag, "proxy", "", "Use proxy server") |
| |
| // Parse command line flags |
| os.Args = args |
| err := flag.Parse(os.Args[1:]) |
| if err != nil { |
| return err |
| } |
| |
| // Print help message if requested |
| if flag.NArg() != 1 || helpFlag { |
| flag.Usage() |
| return nil |
| } |
| |
| webDir := flag.Arg(0) |
| |
| // run ops server and open browser |
| port := getOpsPort() |
| webDirPath := joinpath(os.Getenv("OPS_PWD"), webDir) |
| log.Println("Serving directory: " + webDirPath) |
| |
| if !noBrowserFlag { |
| if err := browser.OpenURL("http://localhost:" + port); err != nil { |
| return err |
| } |
| } |
| |
| localHandler := webFileServerHandler(webDirPath) |
| |
| var proxy *httputil.ReverseProxy = nil |
| if proxyFlag != "" { |
| remoteUrl, err := url.Parse(proxyFlag) |
| if err != nil { |
| return err |
| } |
| proxy = httputil.NewSingleHostReverseProxy(remoteUrl) |
| } |
| |
| customHandler := func(w http.ResponseWriter, r *http.Request) { |
| // Check if the file exists locally |
| |
| _, err := http.Dir(webDirPath).Open(r.URL.Path) |
| if err == nil { |
| // Serve the file using the file server |
| localHandler.ServeHTTP(w, r) |
| return |
| } |
| |
| // File not found locally, proxy the request to the remote server |
| log.Printf("not found locally %s\n", r.URL.Path) |
| |
| if proxy != nil { |
| log.Printf("Proxying to %s\n", proxyFlag) |
| proxy.ServeHTTP(w, r) |
| } |
| } |
| |
| handler := http.HandlerFunc(customHandler) |
| |
| if checkPortAvailable(port) { |
| log.Println("OpenServerless config server started at http://localhost:" + port) |
| addr := fmt.Sprintf(":%s", port) |
| return http.ListenAndServe(addr, handler) |
| } else { |
| log.Println("OpenServerless config server failed to start. Port already in use?") |
| return nil |
| } |
| } |
| |
| // Handler to serve the olaris/web directory |
| func webFileServerHandler(webDir string) http.Handler { |
| return http.FileServer(http.Dir(webDir)) |
| } |
| |
| func checkPortAvailable(port string) bool { |
| ln, err := net.Listen("tcp", ":"+port) |
| if err != nil { |
| return false |
| } |
| //nolint:errcheck |
| ln.Close() |
| return true |
| } |