ledisdb/server/http/handler.go

106 lines
2.3 KiB
Go

package http
import (
"net/http"
//"github.com/siddontang/go-websocket/websocket"
"encoding/json"
"fmt"
"github.com/siddontang/go-log/log"
"github.com/siddontang/ledisdb/ledis"
"strconv"
"strings"
)
type CmdHandler struct {
Ldb *ledis.Ledis
}
func (h *CmdHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
w.WriteHeader(http.StatusForbidden)
return
}
idx, cmd, args := h.parseReqPath(r.URL.Path)
cmdFunc := lookup(cmd)
if cmdFunc == nil {
h.cmdNotFound(cmd, w)
return
}
var db *ledis.DB
var err error
if db, err = h.Ldb.Select(idx); err != nil {
h.serverError(cmd, err, w)
return
}
result, err := cmdFunc(db, args...)
if err != nil {
h.serverError(cmd, err, w)
return
}
h.write(cmd, result, w)
}
func (h *CmdHandler) parseReqPath(path string) (db int, cmd string, args []string) {
/*
this function extracts `db`, `cmd` and `args` from `path`
the proper format of `path` is /cmd/arg1/arg2/../argN or /db/cmd/arg1/arg2/../argN
if `path` is the first kind, `db` will be 0
*/
substrings := strings.Split(strings.TrimLeft(path, "/"), "/")
if len(substrings) == 1 {
return 0, substrings[0], substrings[1:]
}
db, err := strconv.Atoi(substrings[0])
if err != nil {
cmd = substrings[0]
args = substrings[1:]
} else {
cmd = substrings[1]
args = substrings[2:]
}
return
}
func (h *CmdHandler) cmdNotFound(cmd string, w http.ResponseWriter) {
result := [2]interface{}{
false,
fmt.Sprintf("ERR unknown command '%s'", cmd),
}
h.write(cmd, result, w)
}
func (h *CmdHandler) write(cmd string, result interface{}, w http.ResponseWriter) {
m := map[string]interface{}{
cmd: result,
}
buf, err := json.Marshal(&m)
if err != nil {
log.Error(err.Error())
return
}
w.Header().Set("Content-type", "application/json; charset=utf-8")
w.Header().Set("Content-Length", strconv.Itoa(len(buf)))
_, err = w.Write(buf)
if err != nil {
log.Error(err.Error())
}
}
func (h *CmdHandler) serverError(cmd string, err error, w http.ResponseWriter) {
result := [2]interface{}{
false,
fmt.Sprintf("ERR %s", err.Error()),
}
h.write(cmd, result, w)
}
type WsHandler struct {
Ldb *ledis.Ledis
}
func (h *WsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ws handler"))
}