-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
260 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Go | ||
/vendor/*/ | ||
|
||
# Editor | ||
.*.swp | ||
.*.un~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,8 @@ | ||
# h2o | ||
A web application framework for the golang. | ||
|
||
|
||
## Thanks | ||
- [mux](https://github.com/gorilla/mux) | ||
- [negroni](https://github.com/urfave/negroni) | ||
- [logrus](https://github.com/Sirupsen/logrus) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package h2o | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"encoding/xml" | ||
"net" | ||
"net/http" | ||
"strings" | ||
) | ||
|
||
// K key type | ||
type K string | ||
|
||
// H hash | ||
type H map[string]interface{} | ||
|
||
// Context context | ||
type Context struct { | ||
Writer http.ResponseWriter | ||
Request *http.Request | ||
|
||
vars map[string]string | ||
} | ||
|
||
// Set set | ||
func (p *Context) Set(k string, v interface{}) { | ||
p.Request = p.Request.WithContext( | ||
context.WithValue(p.Request.Context(), K(k), v), | ||
) | ||
} | ||
|
||
// Get get | ||
func (p *Context) Get(k string) interface{} { | ||
return p.Request.Context().Value(K(k)) | ||
} | ||
|
||
// Redirect redirect | ||
func (p *Context) Redirect(code int, url string) { | ||
http.Redirect(p.Writer, p.Request, url, code) | ||
} | ||
|
||
// Header get header | ||
func (p *Context) Header(k string) string { | ||
return p.Request.Header.Get(k) | ||
} | ||
|
||
// Param the value of the URL param. | ||
func (p *Context) Param(k string) string { | ||
return p.vars[k] | ||
} | ||
|
||
// ClientIP client ip | ||
func (p *Context) ClientIP() string { | ||
// ------------- | ||
if ip := strings.TrimSpace(p.Header("X-Real-Ip")); ip != "" { | ||
return ip | ||
} | ||
// ------------- | ||
ip := p.Header("X-Forwarded-For") | ||
if idx := strings.IndexByte(ip, ','); idx >= 0 { | ||
ip = ip[0:idx] | ||
} | ||
ip = strings.TrimSpace(ip) | ||
if ip != "" { | ||
return ip | ||
} | ||
// ------------- | ||
if ip, _, err := net.SplitHostPort(strings.TrimSpace(p.Request.RemoteAddr)); err == nil { | ||
return ip | ||
} | ||
// ----------- | ||
return "" | ||
} | ||
|
||
// JSON write json | ||
func (p *Context) JSON(s int, v interface{}) error { | ||
enc := json.NewEncoder(p.Writer) | ||
return enc.Encode(v) | ||
} | ||
|
||
// XML write xml | ||
func (p *Context) XML(s int, v interface{}) error { | ||
enc := xml.NewEncoder(p.Writer) | ||
return enc.Encode(v) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package h2o | ||
|
||
// HTTPError http error | ||
type HTTPError struct { | ||
Message string | ||
Status int | ||
} | ||
|
||
func (p *HTTPError) Error() string { | ||
return p.Message | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package h2o | ||
|
||
type route struct { | ||
path string | ||
methods []string | ||
handlers []HandlerFunc | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package h2o | ||
|
||
import ( | ||
"net/http" | ||
"reflect" | ||
"runtime" | ||
"time" | ||
|
||
log "github.com/Sirupsen/logrus" | ||
"github.com/gorilla/mux" | ||
) | ||
|
||
// HandlerFunc an adapter to allow the use of ordinary functions as HTTP handler | ||
type HandlerFunc func(*Context) error | ||
|
||
// New new blank Engine instance without any middleware attached. | ||
func New() *Router { | ||
return &Router{ | ||
handlers: make([]HandlerFunc, 0), | ||
routes: make([]*route, 0), | ||
} | ||
} | ||
|
||
// Router associated with a prefix and an array of handlers | ||
type Router struct { | ||
path string | ||
handlers []HandlerFunc | ||
routes []*route | ||
} | ||
|
||
// Group creates a new router group | ||
func (p *Router) Group(group func(*Router), path string, handlers ...HandlerFunc) { | ||
rt := &Router{ | ||
path: p.path + path, | ||
handlers: append(p.handlers, handlers...), | ||
routes: make([]*route, 0), | ||
} | ||
group(rt) | ||
p.routes = append(p.routes, rt.routes...) | ||
} | ||
|
||
// GET http get | ||
func (p *Router) GET(path string, handlers ...HandlerFunc) { | ||
p.Handle([]string{http.MethodGet}, path, handlers...) | ||
} | ||
|
||
// POST http post | ||
func (p *Router) POST(path string, handlers ...HandlerFunc) { | ||
p.Handle([]string{http.MethodPost}, path, handlers...) | ||
} | ||
|
||
// PUT http put | ||
func (p *Router) PUT(path string, handlers ...HandlerFunc) { | ||
p.Handle([]string{http.MethodPut}, path, handlers...) | ||
} | ||
|
||
// PATCH http patch | ||
func (p *Router) PATCH(path string, handlers ...HandlerFunc) { | ||
p.Handle([]string{http.MethodPatch}, path, handlers...) | ||
} | ||
|
||
// DELETE http delete | ||
func (p *Router) DELETE(path string, handlers ...HandlerFunc) { | ||
p.Handle([]string{http.MethodDelete}, path, handlers...) | ||
} | ||
|
||
// Handle registers a new request handle and middleware with the given path and method. | ||
func (p *Router) Handle(methods []string, path string, handlers ...HandlerFunc) { | ||
p.routes = append( | ||
p.routes, | ||
&route{ | ||
methods: methods, | ||
path: p.path + path, | ||
handlers: append(p.handlers, handlers...), | ||
}, | ||
) | ||
} | ||
|
||
// Run attaches the router to a http.Server and starts listening and serving HTTP requests. | ||
func (p *Router) Run(port int, grace bool) error { | ||
rt := mux.NewRouter() | ||
for _, r := range p.routes { | ||
rt.HandleFunc(r.path, func(w http.ResponseWriter, r *http.Request) { | ||
begin := time.Now() | ||
ctx := Context{ | ||
Request: r, | ||
Writer: w, | ||
vars: mux.Vars(r), | ||
} | ||
log.Infof("%s %s %s %s", r.Proto, r.Method, r.RequestURI, ctx.ClientIP()) | ||
for _, h := range p.handlers { | ||
log.Debugf("call %s", runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name()) | ||
if e := h(&ctx); e != nil { | ||
log.Error(e) | ||
s := http.StatusInternalServerError | ||
if he, ok := e.(*HTTPError); ok { | ||
s = he.Status | ||
} | ||
http.Error(w, e.Error(), s) | ||
} | ||
} | ||
log.Infof("done %s", time.Now().Sub(begin)) | ||
}).Methods(r.methods...) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"comment": "", | ||
"ignore": "test", | ||
"package": [ | ||
{ | ||
"checksumSHA1": "m+iiamnbukzE8kFPfBche6D0FmQ=", | ||
"path": "github.com/Sirupsen/logrus", | ||
"revision": "5b60b3d3ee017ed00bcd0225fcca7acab767844b", | ||
"revisionTime": "2017-05-04T07:10:19Z" | ||
}, | ||
{ | ||
"checksumSHA1": "g/V4qrXjUGG9B+e3hB+4NAYJ5Gs=", | ||
"path": "github.com/gorilla/context", | ||
"revision": "08b5f424b9271eedf6f9f0ce86cb9396ed337a42", | ||
"revisionTime": "2016-08-17T18:46:32Z" | ||
}, | ||
{ | ||
"checksumSHA1": "zmCk+lgIeiOf0Ng9aFP9aFy8ksE=", | ||
"path": "github.com/gorilla/mux", | ||
"revision": "4c1c3952b7d9d0a061a3fa7b36fd373ba0398ebc", | ||
"revisionTime": "2017-04-27T04:12:50Z" | ||
}, | ||
{ | ||
"checksumSHA1": "x1AhvSvgDWiTnAc57jsoFKeKLsI=", | ||
"path": "github.com/urfave/negroni", | ||
"revision": "1d8981a52d6bda4467a9faacf3fdddd38222dfc4", | ||
"revisionTime": "2017-05-06T02:27:41Z" | ||
}, | ||
{ | ||
"checksumSHA1": "oS0UZOGWVVsVciOQ8nZJ582mFF8=", | ||
"path": "golang.org/x/sys/unix", | ||
"revision": "9ccfe848b9db8435a24c424abbc07a921adf1df5", | ||
"revisionTime": "2017-04-27T03:54:25Z" | ||
} | ||
], | ||
"rootPath": "github.com/kapmahc/h2o" | ||
} |