| cwd = ctx.Args()[0] | cwd = ctx.Args()[0] | ||||
| } | } | ||||
| if abspath, err := filepath.Abs(cwd); err == nil { | if abspath, err := filepath.Abs(cwd); err == nil { | ||||
| env.Set(internal.ROOT, abspath) | |||||
| env.Set(internal.BaseDir, abspath) | |||||
| } else { | } else { | ||||
| log.Fatalf("Failed to retrieve the directory: %v", err) | log.Fatalf("Failed to retrieve the directory: %v", err) | ||||
| } | } |
| package rex | |||||
| import ( | |||||
| "flag" | |||||
| "runtime" | |||||
| ) | |||||
| var ( | |||||
| debug bool | |||||
| port int | |||||
| maxprocs int | |||||
| ) | |||||
| func configure() { | |||||
| flag.BoolVar(&debug, "debug", Env.Bool("DEBUG", true), "flag to toggle debug mode") | |||||
| flag.IntVar(&port, "port", Env.Int("PORT", 5000), "port to run the application server") | |||||
| flag.IntVar(&maxprocs, "maxprocs", Env.Int("MAXPROCS", runtime.NumCPU()), "maximum cpu processes to run the server") | |||||
| flag.Parse() | |||||
| } |
| "net/http" | "net/http" | ||||
| "path/filepath" | "path/filepath" | ||||
| "github.com/goanywhere/env" | |||||
| "github.com/goanywhere/rex" | "github.com/goanywhere/rex" | ||||
| "github.com/goanywhere/rex/livereload" | "github.com/goanywhere/rex/livereload" | ||||
| ) | ) | ||||
| http.Error(w, err.Error(), http.StatusInternalServerError) | http.Error(w, err.Error(), http.StatusInternalServerError) | ||||
| } else { | } else { | ||||
| w.Header().Set("Content-Type", "text/html") | w.Header().Set("Content-Type", "text/html") | ||||
| var user = User{Username: rex.Env.String("USER", "guest")} | |||||
| var user = User{Username: env.String("USER", "guest")} | |||||
| html.Execute(w, user) | html.Execute(w, user) | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| func main() { | func main() { | ||||
| rex.Use(livereload.Middleware) | |||||
| rex.Get("/", Index) | |||||
| app := rex.New() | |||||
| app.Use(livereload.Middleware) | |||||
| app.Get("/", Index) | |||||
| api := rex.Group("/v1/") | |||||
| api := app.Group("/v1/") | |||||
| api.Use(JSON) | api.Use(JSON) | ||||
| api.Get("/", fetch) | api.Get("/", fetch) | ||||
| api.Post("/", create) | api.Post("/", create) | ||||
| api.Put("/", update) | api.Put("/", update) | ||||
| api.Delete("/", remove) | api.Delete("/", remove) | ||||
| rex.Run() | |||||
| app.Run() | |||||
| } | } |
| package internal | package internal | ||||
| const ROOT = "rex.root" | |||||
| const BaseDir string = "rex.root" |
| package internal | |||||
| import ( | |||||
| "path" | |||||
| "github.com/goanywhere/env" | |||||
| ) | |||||
| type Env struct { | |||||
| Base string | |||||
| } | |||||
| func New(dotenv string) *Env { | |||||
| env.Load(dotenv) | |||||
| return &Env{Base: path.Base(dotenv)} | |||||
| } | |||||
| func (self *Env) Get(key string) (string, bool) { | |||||
| return env.Get(key) | |||||
| } | |||||
| func (self *Env) Set(key string, value interface{}) error { | |||||
| return env.Set(key, value) | |||||
| } | |||||
| func (self *Env) String(key string, fallback ...string) string { | |||||
| return env.String(key, fallback...) | |||||
| } | |||||
| func (self *Env) Strings(key string, fallback ...[]string) []string { | |||||
| return env.Strings(key, fallback...) | |||||
| } | |||||
| func (self *Env) Int(key string, fallback ...int) int { | |||||
| return env.Int(key, fallback...) | |||||
| } | |||||
| func (self *Env) Int64(key string, fallback ...int64) int64 { | |||||
| return env.Int64(key, fallback...) | |||||
| } | |||||
| func (self *Env) Uint(key string, fallback ...uint) uint { | |||||
| return env.Uint(key, fallback...) | |||||
| } | |||||
| func (self *Env) Uint64(key string, fallback ...uint64) uint64 { | |||||
| return env.Uint64(key, fallback...) | |||||
| } | |||||
| func (self *Env) Bool(key string, fallback ...bool) bool { | |||||
| return env.Bool(key, fallback...) | |||||
| } | |||||
| func (self *Env) Float(key string, fallback ...float64) float64 { | |||||
| return env.Float(key, fallback...) | |||||
| } | |||||
| func (self *Env) Map(spec interface{}) error { | |||||
| return env.Map(spec) | |||||
| } |
| package rex | package rex | ||||
| import ( | import ( | ||||
| "net/http" | |||||
| "path/filepath" | |||||
| "path" | |||||
| "github.com/goanywhere/env" | |||||
| "github.com/goanywhere/fs" | "github.com/goanywhere/fs" | ||||
| "github.com/goanywhere/rex/internal" | |||||
| . "github.com/goanywhere/rex/middleware" | |||||
| ) | ) | ||||
| var ( | |||||
| Default = New() | |||||
| Env *internal.Env | |||||
| ) | |||||
| // Get is a shortcut for mux.HandleFunc(pattern, handler).Methods("GET"), | |||||
| // it also fetch the full function name of the handler (with package) to name the route. | |||||
| func Get(pattern string, handler interface{}) { | |||||
| Default.Get(pattern, handler) | |||||
| } | |||||
| // Head is a shortcut for mux.HandleFunc(pattern, handler).Methods("HEAD") | |||||
| // it also fetch the full function name of the handler (with package) to name the route. | |||||
| func Head(pattern string, handler interface{}) { | |||||
| Default.Head(pattern, handler) | |||||
| } | |||||
| // Options is a shortcut for mux.HandleFunc(pattern, handler).Methods("OPTIONS") | |||||
| // it also fetch the full function name of the handler (with package) to name the route. | |||||
| // NOTE method OPTIONS is **NOT** cachable, beware of what you are going to do. | |||||
| func Options(pattern string, handler interface{}) { | |||||
| Default.Options(pattern, handler) | |||||
| } | |||||
| // Post is a shortcut for mux.HandleFunc(pattern, handler).Methods("POST") | |||||
| // it also fetch the full function name of the handler (with package) to name the route. | |||||
| func Post(pattern string, handler interface{}) { | |||||
| Default.Post(pattern, handler) | |||||
| } | |||||
| // Put is a shortcut for mux.HandleFunc(pattern, handler).Methods("PUT") | |||||
| // it also fetch the full function name of the handler (with package) to name the route. | |||||
| func Put(pattern string, handler interface{}) { | |||||
| Default.Put(pattern, handler) | |||||
| } | |||||
| // Delete is a shortcut for mux.HandleFunc(pattern, handler).Methods("DELETE") | |||||
| // it also fetch the full function name of the handler (with package) to name the route. | |||||
| func Delete(pattern string, handler interface{}) { | |||||
| Default.Delete(pattern, handler) | |||||
| } | |||||
| // Group creates a new application group under the given path. | |||||
| func Group(path string) *Server { | |||||
| return Default.Group(path) | |||||
| } | |||||
| // FileServer registers a handler to serve HTTP (GET|HEAD) requests | |||||
| // with the contents of file system under the given directory. | |||||
| func FileServer(prefix, dir string) { | |||||
| Default.FileServer(prefix, dir) | |||||
| } | |||||
| // Use appends middleware module into the serving list, modules will be served in FIFO order. | |||||
| func Use(module func(http.Handler) http.Handler) { | |||||
| Default.Use(module) | |||||
| } | |||||
| func Run() { | |||||
| Default.Use(Logger) | |||||
| Default.Run() | |||||
| } | |||||
| func init() { | func init() { | ||||
| var basedir = fs.Getcd(2) | var basedir = fs.Getcd(2) | ||||
| Env = internal.New(filepath.Join(basedir, ".env")) | |||||
| env.Set("basedir", basedir) | |||||
| env.Load(path.Join(basedir, ".env")) | |||||
| } | } |
| package rex | package rex | ||||
| import ( | import ( | ||||
| "flag" | |||||
| "fmt" | "fmt" | ||||
| "log" | "log" | ||||
| "net/http" | "net/http" | ||||
| "path/filepath" | "path/filepath" | ||||
| "reflect" | "reflect" | ||||
| "runtime" | "runtime" | ||||
| "sync" | |||||
| "time" | "time" | ||||
| "github.com/goanywhere/env" | |||||
| "github.com/gorilla/mux" | "github.com/gorilla/mux" | ||||
| ) | ) | ||||
| var ( | |||||
| debug bool | |||||
| port int | |||||
| maxprocs int | |||||
| once sync.Once | |||||
| ) | |||||
| type Server struct { | type Server struct { | ||||
| middleware *middleware | middleware *middleware | ||||
| mux *mux.Router | mux *mux.Router | ||||
| middleware: new(middleware), | middleware: new(middleware), | ||||
| mux: mux.NewRouter().StrictSlash(true), | mux: mux.NewRouter().StrictSlash(true), | ||||
| } | } | ||||
| self.configure() | |||||
| return self | return self | ||||
| } | } | ||||
| func (self *Server) configure() { | |||||
| once.Do(func() { | |||||
| flag.BoolVar(&debug, "debug", env.Bool("DEBUG", true), "flag to toggle debug mode") | |||||
| flag.IntVar(&port, "port", env.Int("PORT", 5000), "port to run the application server") | |||||
| flag.IntVar(&maxprocs, "maxprocs", env.Int("MAXPROCS", runtime.NumCPU()), "maximum cpu processes to run the server") | |||||
| flag.Parse() | |||||
| }) | |||||
| } | |||||
| // build constructs all server/subservers along with their middleware modules chain. | // build constructs all server/subservers along with their middleware modules chain. | ||||
| func (self *Server) build() http.Handler { | func (self *Server) build() http.Handler { | ||||
| if !self.ready { | if !self.ready { | ||||
| // Run starts the application server to serve incoming requests at the given address. | // Run starts the application server to serve incoming requests at the given address. | ||||
| func (self *Server) Run() { | func (self *Server) Run() { | ||||
| configure() | |||||
| runtime.GOMAXPROCS(maxprocs) | runtime.GOMAXPROCS(maxprocs) | ||||
| go func() { | go func() { |