serve.go (91 lines of code) (raw):

// 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 }