diff --git a/binding.go b/binding.go new file mode 100644 index 0000000..a8cb1f8 --- /dev/null +++ b/binding.go @@ -0,0 +1,16 @@ +package wkwsweb + +// Content-Type MINE of the most common data formats. by Gin +const ( + MIMEJSON = "application/json" + MIMEHTML = "text/html" + MIMEXML = "application/xml" + MIMEXML2 = "text/xml" + MIMEPlain = "text/plain" + MIMEPOSTForm = "application/x-www-form-urlencoded" + MIMEMultipartPOSTForm = "multipart/form-data" + MIMEPROTOBUF = "application/x-protobuf" + MIMEMSGPACK = "application/x-msgpack" + MIMEMSGPACK2 = "application/msgpack" + MIMEYAML = "application/x-yaml" +) diff --git a/console.go b/console.go new file mode 100644 index 0000000..7226878 --- /dev/null +++ b/console.go @@ -0,0 +1,11 @@ +package wkwsweb + +import "fmt" + +const ( + PREFIX = "[WKWS]" +) + +func CLogger(s string, v ...interface{}) { + fmt.Printf(PREFIX+s+"\n", v...) +} diff --git a/context.go b/context.go new file mode 100644 index 0000000..b444ae3 --- /dev/null +++ b/context.go @@ -0,0 +1,70 @@ +package wkwsweb + +import ( + "encoding/json" + "net/http" +) + +type Param struct { + Key string + Value string +} + +type Params []Param + +type Context struct { + Request *http.Request + http.ResponseWriter + Cache map[string]interface{} + Params Params +} + +type Controller func(ctx *Context) + +func NewCtx() *Context { + return &Context{ + nil, + nil, + map[string]interface{}{}, + make(Params, 0, 100), + } +} + +func (ps Params) Get(name string) (string, bool) { + for _, entry := range ps { + if entry.Key == name { + return entry.Value, true + } + } + return "", false +} + +func (ctx *Context) Set(key string, value interface{}) { + ctx.Cache[key] = value +} + +func (ctx *Context) Get(key string) interface{} { + value := ctx.Cache[key] + return value +} + +func (ctx *Context) GetMap() map[string][]string { + return ctx.Request.PostForm +} + +func (ctx *Context) GetRequestContext() string { + return ctx.Request.Header["Content-Type"][0] +} + +func (ctx *Context) ResponseJSON(data interface{}) { + ctx.ResponseWriter.Header().Add("Content-type", "application/json") + marshal, err := json.Marshal(data) + if err != nil { + return + } + _, err = ctx.ResponseWriter.Write(marshal) + if err != nil { + CLogger("Cannot write response json %v", err) + return + } +} diff --git a/router.go b/router.go new file mode 100644 index 0000000..844126f --- /dev/null +++ b/router.go @@ -0,0 +1,29 @@ +package wkwsweb + +import ( + "net/http" +) + +type RouterHandlers []RouterHandler + +type RouterHandler struct { + Path string + Method string + Handler Controller +} + +func (wkws *Wkws) POST(uri string, handler Controller) { + addRouter(http.MethodPost, uri, handler, wkws) +} + +func (wkws *Wkws) GET(uri string, handler Controller) { + addRouter(http.MethodGet, uri, handler, wkws) +} + +func addRouter(method string, path string, handler Controller, core *Wkws) { + core.RouterHandlers = append(core.RouterHandlers, RouterHandler{ + Path: path, + Method: method, + Handler: handler, + }) +} diff --git a/router_test.go b/router_test.go new file mode 100644 index 0000000..7d8e731 --- /dev/null +++ b/router_test.go @@ -0,0 +1 @@ +package wkwsweb diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..c145771 --- /dev/null +++ b/utils.go @@ -0,0 +1,12 @@ +package wkwsweb + +// H is a shortcut for map[string]interface{} +type H map[string]interface{} + +type WkwsError struct { + Msg string +} + +func (e *WkwsError) Error() string { + return e.Msg +} diff --git a/wkws.go b/wkws.go index 51e61e4..a31ed2e 100644 --- a/wkws.go +++ b/wkws.go @@ -1,6 +1,82 @@ package wkwsweb -type wkws struct { - Address string - Port string +import ( + "net/http" +) + +type Error struct { + Err error +} + +type Wkws struct { + RouterHandlers RouterHandlers + HttpServer *http.Server +} + +func Init() (core *Wkws) { + core = &Wkws{ + RouterHandlers: nil, + HttpServer: nil, + } + return +} + +func (wkws *Wkws) Run(add string, port string) (err error) { + addr := add + ":" + port + CLogger("HTTP listen the address , %s \n", addr) + r := http.NewServeMux() + CLogger("Router map:") + // Get new routers, filter router path repeat + registeredRouter := map[string]struct{}{} + + for _, router := range wkws.RouterHandlers { + if _, exist := registeredRouter[router.Path]; !exist { + r.HandleFunc(router.Path, wkws.ServeHTTP) + registeredRouter[router.Path] = struct{}{} + } + CLogger("Router Method is %s , Path in %s , Handler is %s", router.Method, router.Path, router.Handler) + } + wkws.HttpServer = &http.Server{Addr: addr, Handler: r} + err = wkws.HttpServer.ListenAndServe() + return +} + +func (wkws *Wkws) ServeHTTP(rsp http.ResponseWriter, req *http.Request) { + c := NewCtx() + c.Request = req + c.ResponseWriter = rsp + controller, err := wkws.handlerHttpRequest(c) + if err != nil { + return + } + controller(c) +} + +func (wkws *Wkws) handlerHttpRequest(c *Context) (Controller, error) { + handler, verify := wkws.handlerVerifyRouter(c.Request.URL.Path, c.Request.Method) + if !verify { + ServerMethodsNotAllowed(c) + return nil, &WkwsError{Msg: "error"} + } + // TODO Handler Request Params + // for that c.Request.URL.Query() , key is value value is key. + return handler, nil +} + +func (wkws *Wkws) handlerVerifyRouter(path string, method string) (Controller, bool) { + for _, r := range wkws.RouterHandlers { + if r.Path == path && r.Method == method { + return r.Handler, true + } + } + return nil, false +} + +func ServerMethodsNotAllowed(c *Context) { + c.ResponseWriter.WriteHeader(405) + _, err := c.ResponseWriter.Write([]byte("405 method not allowed")) + if err != nil { + CLogger("cannot write message %v", err) + } + return } diff --git a/wkws_test.go b/wkws_test.go new file mode 100644 index 0000000..cd29bd1 --- /dev/null +++ b/wkws_test.go @@ -0,0 +1,44 @@ +package wkwsweb + +import ( + "log" + "net/http/httptest" + "testing" +) + +func PostController(ctx *Context) { + log.Println(ctx.GetMap()) + log.Println(ctx.Request.Method) + log.Println(ctx.Request.Header["Content-Type"]) + log.Println(ctx.GetRequestContext()) + ctx.ResponseWriter.Write([]byte("This is Post Controller")) +} + +func GetController(ctx *Context) { + ctx.ResponseWriter.Write([]byte("This is Get Controller")) +} + +func CacheController(ctx *Context) { + ctx.Set("Hello", "World") + bytes := []byte("Cache : " + ctx.Get("Hello").(string)) + ctx.ResponseWriter.Write(bytes) +} + +func ResponseController(ctx *Context) { + ctx.ResponseJSON(H{ + "HelloWorld": "Millyn", + }) +} + +func TestWkws_HttpRun(t *testing.T) { + core := Init() + core.GET("/cache", CacheController) + core.GET("/response", ResponseController) + core.POST("/response", ResponseController) + + var ts *httptest.Server + + ts = httptest.NewServer(core) + + defer ts.Close() +}