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() { |