Merge pull request #26 from mattn/basic-auth

HTTP Basic Authentication support. Close #8
This commit is contained in:
Iwasaki Yudai 2015-08-19 23:44:38 -07:00
commit 47bdae8447
2 changed files with 46 additions and 3 deletions

View File

@ -1,6 +1,7 @@
package app package app
import ( import (
"encoding/base64"
"encoding/json" "encoding/json"
"log" "log"
"net/http" "net/http"
@ -19,18 +20,50 @@ type App struct {
Address string Address string
Port string Port string
PermitWrite bool PermitWrite bool
Credential string
Command []string Command []string
} }
func New(address string, port string, permitWrite bool, command []string) *App { func New(address string, port string, permitWrite bool, cred string, command []string) *App {
return &App{ return &App{
Address: address, Address: address,
Port: port, Port: port,
PermitWrite: permitWrite, PermitWrite: permitWrite,
Credential: cred,
Command: command, Command: command,
} }
} }
func loggerHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s %s", r.Method, r.URL.Path)
h.ServeHTTP(w, r)
})
}
func basicAuthHandler(h http.Handler, cred string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
if len(token) != 2 || strings.ToLower(token[0]) != "basic" {
w.Header().Set("WWW-Authenticate", `Basic realm="GoTTY"`)
http.Error(w, "Bad Request", http.StatusUnauthorized)
return
}
payload, err := base64.StdEncoding.DecodeString(token[1])
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
if cred != string(payload) {
w.Header().Set("WWW-Authenticate", `Basic realm="GoTTY"`)
http.Error(w, "authorization failed", http.StatusUnauthorized)
return
}
h.ServeHTTP(w, r)
})
}
func (app *App) Run() error { func (app *App) Run() error {
http.Handle("/", http.Handle("/",
http.FileServer( http.FileServer(
@ -41,7 +74,12 @@ func (app *App) Run() error {
url := app.Address + ":" + app.Port url := app.Address + ":" + app.Port
log.Printf("Server is running at %s, command: %s", url, strings.Join(app.Command, " ")) log.Printf("Server is running at %s, command: %s", url, strings.Join(app.Command, " "))
err := http.ListenAndServe(url, nil) handler := http.Handler(http.DefaultServeMux)
handler = loggerHandler(handler)
if app.Credential != "" {
handler = basicAuthHandler(handler, app.Credential)
}
err := http.ListenAndServe(url, handler)
if err != nil { if err != nil {
return err return err
} }

View File

@ -32,6 +32,11 @@ func main() {
Usage: "Permit clients to write to the TTY (BE CAREFUL)", Usage: "Permit clients to write to the TTY (BE CAREFUL)",
EnvVar: "GOTTY_PERMIT_WRITE", EnvVar: "GOTTY_PERMIT_WRITE",
}, },
cli.StringFlag{
Name: "credential, c",
Usage: "Credential for Basic Authentication (ex: user:pass)",
EnvVar: "GOTTY_CREDENTIAL",
},
} }
cmd.Action = func(c *cli.Context) { cmd.Action = func(c *cli.Context) {
if len(c.Args()) == 0 { if len(c.Args()) == 0 {
@ -39,7 +44,7 @@ func main() {
cli.ShowAppHelp(c) cli.ShowAppHelp(c)
os.Exit(1) os.Exit(1)
} }
app := app.New(c.String("addr"), c.String("port"), c.Bool("permit-write"), c.Args()) app := app.New(c.String("addr"), c.String("port"), c.Bool("permit-write"), c.String("credential"), c.Args())
err := app.Run() err := app.Run()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)