Thanks for coming here, I hope you are enjoying learning here, I have also written some books in case you want to learn a bit more :)
If you need my help with Drupal, Linux, Jira, Scripting, Automation or want to contact me then raise a ticket for me please :) and I will get back to you, promise. At Sparxsys we provide Atlassian consultancy services, reach out to me at ravi at sparxsys dot com

Exposing shell over API is reminiscence of CGI and old college days

Ravi in college
Ravi in college

This morning I was going to Reading when I thought of exposing the shell script that I wrote yesterday to read the CSV file where I am storing my GPS location and sending it to my website. I though of this idea where I can simply query my database of flat files. I thought of creating a bash script where I can pass the date and time argument and it will return my GPS coordinates of that day by looking in the CSV files. I also thought of exposing this script using API.

So when I was searching on the net for some libraries I am actually found one called goexpose that might do the job but I was interested in doing something very simple and quick. I also found one link where I found this code.

  1. // This tool exposes any binary (shell command/script) as an HTTP service.
  2. // A remote client can trigger the execution of the command by sending
  3. // a simple HTTP request. The output of the command execution is sent
  4. // back to the client in plain text format.
  5. package main
  7. import (
  8.  "flag"
  9.  "fmt"
  10.  "io/ioutil"
  11.  "log"
  12.  "net/http"
  13.  "os"
  14.  "os/exec"
  15.  "strings"
  16. )
  18. func main() {
  19.  binary := flag.String("b", "", "Path to the executable binary")
  20.  port := flag.Int("p", 8080, "HTTP port to listen on")
  21.  flag.Parse()
  23.  if *binary == "" {
  24.   fmt.Println("Path to binary not specified.")
  25.   return
  26.  }
  28.  l := log.New(os.Stdout, "", log.Ldate|log.Ltime)
  29.  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  30.   var argString string
  31.   if r.Body != nil {
  32.    data, err := ioutil.ReadAll(r.Body)
  33.    if err != nil {
  34.     l.Print(err)
  35.     http.Error(w, err.Error(), http.StatusInternalServerError)
  36.     return
  37.    }
  38.    argString = string(data)
  39.   }
  41.   fields := strings.Fields(*binary)
  42.   args := append(fields[1:], strings.Fields(argString)...)
  43.   l.Printf("Command: [%s %s]", fields[0], strings.Join(args, " "))
  45.   output, err := exec.Command(fields[0], args...).Output()
  46.   if err != nil {
  47.    http.Error(w, err.Error(), http.StatusInternalServerError)
  48.    return
  49.   }
  50.   w.Header().Set("Content-Type", "text/plain")
  51.   w.Write(output)
  52.  })
  54.  l.Printf("Listening on port %d...", *port)
  55.  l.Printf("Exposed binary: %s", *binary)
  56.  http.ListenAndServe(fmt.Sprintf("", *port), nil)
  57. }

The code above actually works perfectly. To expose the "date" command as a web API. You can simply run the tool as follows:

./bash2http -b date

Check the link for more details.

However I was not entirely convinced with the approach of this code. There is no security and that is why I will spend more time on goexpose code on github to understand how secure it is. It supports SSL which is assuring. Let us see if I can spend some more time this week. I really want to find a solution. Most likely I will try to make the above code slightly secure and reusable. I just don't understand Go that well yet. I wish if we can simply feed our brain with knowledge while we are sleeping.

I also came to know that the approach of exposing shell using API method so that it can be invoked over the internet is exactly what CGI used to do. It reminded me of the days when we used to work on C++ during our college days. Internet was still quite new in late 1990s and create a web page using C++ was so much fun. All the memories of floppy disk filled with hundreds of CPP files that we used to compile with Alt+F9 and then run with Ctrl+F9 by smashing the keys on TVS gold keyboard. So many amazing memories of college.

I made couple of projects with Chinar in college using graphics in C++ and mouse programming and working with interrupts. I wish if I get find the code again. It is a shame there was no Github back then. I am sure I must have the code somewhere in floppy disks but how will I read them?

Pic 1:Me in my college.

Pic 2: This is my class (Check the bag I still have the same bag here with my in London and I take it to work everyday).

Going to work after ages tomorrow. I am actually missing "Mind the gap" voice. Excited!

Similar posts

Ravi Sagar Newsletter

Honestly I hardly send out mails but I guess there is no harm in at least having a newsletter. I will only send newsletter when I have something important to share or an update. People are busy and no one has time to read emails these days. If you really like my content then I guess you will remember my site and come back for more.

Want to contact me?