Search code examples
gohttp-redirectenvironment-variablesglobal-variables

how to use the output of a bash script in a Golang function


This might not even be possible but I've been researching for the past hour and come up blank. I have a bash script that gives me a certain output and I want to add that output to Golang in order to redirect a website based on the output of the bash script. Sorry if this makes no sense, im new to Go

Here is what I have to run the bash script and output the value

 func main() {
    out, err := exec.Command("/bin/sh", "script.sh").Output()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf(string(out))
}

I then want to use the value that was output there in another function and to redirect a URL heres how I would redirect to a url and I wanted the $variable to be added. This is just an example I copied off the internet but its what I want to replicate.

func redirect(w http.ResponseWriter, r *http.Request) {

    http.Redirect(w, r, "**$variable**", 301)
}
 func main() {
     http.HandleFunc("/", redirect)
     err := http.ListenAndServe(":8080", nil)
     if err != nil {
         log.Fatal("ListenAndServe: ", err)
     }
 }

Solution

  • Assuming your script must be only run once at startup, then this should do the trick:

    var redirectTo string
    
    func redirect(w http.ResponseWriter, r *http.Request) {
        http.Redirect(w, r, redirectTo, 301)
    }
    
    func main() {
        out, err := exec.Command("/bin/sh", "script.sh").Output()
        if err != nil {
           log.Fatal(err)
        }
        redirectTo = string(out)
        http.HandleFunc("/", redirect)
        err = http.ListenAndServe(":8080", nil)
        if err != nil {
            log.Fatal("ListenAndServe: ", err)
        }
    }
    

    Or if you don't want to have a global variable you can generate the redirect function at runtime:

    func main() {
        out, err := exec.Command("/bin/sh", "script.sh").Output()
        if err != nil {
           log.Fatal(err)
        }
        http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
            http.Redirect(w, r, string(out), 301)
        })
        err = http.ListenAndServe(":8080", nil)
        if err != nil {
            log.Fatal("ListenAndServe: ", err)
        }
    }
    

    if you want to handle when out is empty, you can do:

    func redirect(w http.ResponseWriter, r *http.Request) {
        if len(redirectTo) == 0 {
            http.Error(w, "No URL parsed!", 500)
            return
        }
        http.Redirect(w, r, redirectTo, 301)
    }
    

    This will return an HTTP error 500 in that case.

    You can also simply exit the program instead of serving:

    out, err := exec.Command("/bin/sh", "script.sh").Output()
    if err != nil {
       log.Fatal(err)
    }
    if len(out) == 0 {
       log.Fatal("no output was returned from script")
    }
    

    You can also add more verifications to out here if you wish, like if it is a correct URL, using net/url package for instance.