Files
goforever/http.go
2015-11-09 23:11:30 -02:00

160 lines
3.7 KiB
Go

// goforever - processes management
// Copyright (c) 2013 Garrett Woodworth (https://github.com/gwoo).
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"strings"
)
func HttpServer() {
http.HandleFunc("/favicon.ico", http.NotFound)
http.HandleFunc("/", AuthHandler(Handler))
fmt.Printf("goforever serving port %s\n", config.Port)
fmt.Printf("goforever serving IP %s\n", config.IP)
bindAddress := fmt.Sprintf("%s:%s", config.IP, config.Port)
if isHttps() == false {
if err := http.ListenAndServe(bindAddress, nil); err != nil {
log.Fatal("ListenAndServe: ", err)
}
return
}
log.Printf("SSL enabled.\n")
if err := http.ListenAndServeTLS(bindAddress, "cert.pem", "key.pem", nil); err != nil {
log.Fatal("ListenAndServeTLS: ", err)
}
}
func isHttps() bool {
_, cerr := os.Open("cert.pem")
_, kerr := os.Open("key.pem")
if os.IsNotExist(cerr) || os.IsNotExist(kerr) {
return false
}
return true
}
func Handler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "DELETE":
DeleteHandler(w, r)
return
case "POST":
PostHandler(w, r)
return
case "PUT":
PutHandler(w, r)
return
case "GET":
GetHandler(w, r)
return
}
}
func GetHandler(w http.ResponseWriter, r *http.Request) {
var output []byte
var err error
switch r.URL.Path[1:] {
case "":
output, err = json.Marshal(daemon.children.keys())
default:
output, err = json.Marshal(daemon.children.get(r.URL.Path[1:]))
}
if err != nil {
log.Printf("Get Error: %#v", err)
return
}
fmt.Fprintf(w, "%s", output)
}
func PostHandler(w http.ResponseWriter, r *http.Request) {
name := r.URL.Path[1:]
p := daemon.children.get(name)
if p == nil {
fmt.Fprintf(w, "%s does not exist.", name)
return
}
cp, _, _ := p.find()
if cp != nil {
fmt.Fprintf(w, "%s already running.", name)
return
}
ch := RunProcess(name, p)
fmt.Fprintf(w, "%s", <-ch)
}
func PutHandler(w http.ResponseWriter, r *http.Request) {
name := r.URL.Path[1:]
p := daemon.children.get(name)
if p == nil {
fmt.Fprintf(w, "%s does not exist.", name)
return
}
p.find()
ch, _ := p.restart()
fmt.Fprintf(w, "%s", <-ch)
}
func DeleteHandler(w http.ResponseWriter, r *http.Request) {
name := r.URL.Path[1:]
p := daemon.children.get(name)
if p == nil {
fmt.Fprintf(w, "%s does not exist.", name)
return
}
p.find()
p.stop()
fmt.Fprintf(w, "%s stopped.", name)
}
func AuthHandler(fn func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
url := r.URL
for k, v := range r.Header {
fmt.Printf(" %s = %s\n", k, v[0])
}
auth, ok := r.Header["Authorization"]
if !ok {
log.Printf("Unauthorized access to %s", url)
w.Header().Add("WWW-Authenticate", "basic realm=\"host\"")
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintf(w, "Not Authorized.")
return
}
encoded := strings.Split(auth[0], " ")
if len(encoded) != 2 || encoded[0] != "Basic" {
log.Printf("Strange Authorization %q", auth)
w.WriteHeader(http.StatusBadRequest)
return
}
decoded, err := base64.StdEncoding.DecodeString(encoded[1])
if err != nil {
log.Printf("Cannot decode %q: %s", auth, err)
w.WriteHeader(http.StatusBadRequest)
return
}
parts := strings.Split(string(decoded), ":")
if len(parts) != 2 {
log.Printf("Unknown format for credentials %q", decoded)
w.WriteHeader(http.StatusBadRequest)
return
}
if parts[0] == config.Username && parts[1] == config.Password {
fn(w, r)
return
}
log.Printf("Unauthorized access to %s", url)
w.Header().Add("WWW-Authenticate", "basic realm=\"host\"")
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintf(w, "Not Authorized.")
return
}
}