github.com/kcmerrill/alfred@v0.0.0-20180727171036-06445dcb5e3d/pkg/alfred/http.task.go (about) 1 package alfred 2 3 import ( 4 "bytes" 5 "fmt" 6 "io/ioutil" 7 "net/http" 8 "os" 9 "os/exec" 10 "strings" 11 "time" 12 13 "github.com/gorilla/mux" 14 ) 15 16 // HTTPTask contains all of our task information 17 type HTTPTask struct { 18 context *Context 19 tasks map[string]Task 20 } 21 22 func (h *HTTPTask) runner(resp http.ResponseWriter, req *http.Request) { 23 vars := mux.Vars(req) 24 25 if vars["task"] == "favicon.ico" { 26 return 27 } 28 29 url, name := TaskParser(vars["task"], "alfred:list") 30 if url != "" || name == "alfred:list" { 31 resp.WriteHeader(http.StatusBadRequest) 32 fmt.Fprintf(resp, "'"+vars["task"]+"' is invalid.") 33 return 34 } 35 36 args := strings.Split(vars["args"], "/") 37 outOK(vars["task"]+" started ["+strings.Join(args, ", ")+"]", "", h.context) 38 stdin, _ := ioutil.ReadAll(req.Body) //trimspace 39 cmd := exec.Command(os.Args[0], "--no-formatting", vars["task"]) 40 cmdOutput, error := cmd.CombinedOutput() 41 cmd.Stdin = bytes.NewBuffer(stdin) 42 43 if error != nil { 44 resp.WriteHeader(http.StatusInternalServerError) 45 fmt.Fprintf(resp, string(cmdOutput)) 46 } else { 47 resp.WriteHeader(http.StatusOK) 48 fmt.Fprintf(resp, string(cmdOutput)) 49 } 50 } 51 52 func httptasks(task Task, context *Context, tasks map[string]Task) { 53 if task.HTTPTasks.Port == "" { 54 return 55 } 56 57 dir, _ := task.dir(context) 58 59 password := translate(evaluate(task.HTTPTasks.Password, dir), context) 60 61 addr := []string{"0.0.0.0", task.HTTPTasks.Port} 62 if strings.Contains(task.HTTPTasks.Port, ":") { 63 addr = strings.Split(task.HTTPTasks.Port, ":") 64 } 65 66 runner := &HTTPTask{ 67 context: context, 68 tasks: tasks, 69 } 70 71 r := mux.NewRouter() 72 r.HandleFunc(`/{task}/{args:[a-zA-Z0-9=\-\/\.]+}`, httptasksAuth(password, runner.runner)).Methods("GET", "POST") 73 r.HandleFunc(`/{task}`, httptasksAuth(password, runner.runner)).Methods("GET", "POST") 74 srv := &http.Server{ 75 Handler: r, 76 Addr: strings.Join(addr, ":"), 77 WriteTimeout: 15 * time.Second, 78 ReadTimeout: 15 * time.Second, 79 } 80 81 outOK("serving "+dir, strings.Join(addr, ":"), context) 82 if err := srv.ListenAndServe(); err != nil { 83 outFail("serve", err.Error(), context) 84 task.Exit(context, tasks) 85 } 86 } 87 88 func httptasksAuth(password string, fn http.HandlerFunc) http.HandlerFunc { 89 return func(w http.ResponseWriter, r *http.Request) { 90 token, _, _ := r.BasicAuth() 91 if password != "" && password != token { 92 http.Error(w, `{"error": "unauthorized"}`, http.StatusUnauthorized) 93 return 94 } 95 fn(w, r) 96 } 97 }