AJ ONeal
4 년 전
9개의 변경된 파일과 205개의 추가작업 그리고 0개의 파일을 삭제
@ -1,3 +1,14 @@ |
|||
# goserv |
|||
|
|||
> Boilerplate for how I like to write a backend web service |
|||
|
|||
```bash |
|||
go mod tidy |
|||
go mod vendor |
|||
go generate -mod=vendor ./... |
|||
go build -mod=vendor . |
|||
``` |
|||
|
|||
```bash |
|||
./goserv run --listen :3000 --serve-path ./overrides |
|||
``` |
|||
|
@ -0,0 +1,4 @@ |
|||
// +build !dev
|
|||
//go:generate go run -mod vendor github.com/shurcooL/vfsgen/cmd/vfsgendev -source="git.coolaj86.com/coolaj86/goserv/assets".Assets
|
|||
|
|||
package assets |
@ -0,0 +1,8 @@ |
|||
// +build dev
|
|||
|
|||
package assets |
|||
|
|||
import "net/http" |
|||
|
|||
// Assets is the public file system which should be served by http
|
|||
var Assets http.FileSystem = http.Dir("../public") |
@ -0,0 +1,10 @@ |
|||
module git.coolaj86.com/coolaj86/goserv |
|||
|
|||
go 1.15 |
|||
|
|||
require ( |
|||
github.com/go-chi/chi v4.1.2+incompatible |
|||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect |
|||
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 |
|||
golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346 // indirect |
|||
) |
@ -0,0 +1,28 @@ |
|||
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= |
|||
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= |
|||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk= |
|||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= |
|||
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU= |
|||
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= |
|||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= |
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
|||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= |
|||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= |
|||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= |
|||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= |
|||
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= |
|||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= |
|||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
|||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
|||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
|||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
|||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
|||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= |
|||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
|||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= |
|||
golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346 h1:hzJjkvxUIF3bSt+v8N5tBQNx/605vszZJ+3XsIamzZo= |
|||
golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= |
|||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
|||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
|||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
@ -0,0 +1,131 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"compress/flate" |
|||
"flag" |
|||
"fmt" |
|||
"net/http" |
|||
"os" |
|||
|
|||
"git.coolaj86.com/coolaj86/goserv/assets" |
|||
"github.com/go-chi/chi" |
|||
"github.com/go-chi/chi/middleware" |
|||
) |
|||
|
|||
var ( |
|||
name = "goserv" |
|||
version = "0.0.0" |
|||
date = "0001-01-01T00:00:00Z" |
|||
commit = "0000000" |
|||
) |
|||
|
|||
func usage() { |
|||
ver() |
|||
fmt.Println("") |
|||
fmt.Println("Use 'help <command>'") |
|||
fmt.Println(" help") |
|||
fmt.Println(" init") |
|||
fmt.Println(" run") |
|||
} |
|||
|
|||
func ver() { |
|||
fmt.Printf("%s v%s %s (%s)\n", name, version, commit[:7], date) |
|||
} |
|||
|
|||
type runOptions struct { |
|||
listen string |
|||
trustProxy bool |
|||
compress bool |
|||
static string |
|||
} |
|||
|
|||
var runFlags *flag.FlagSet |
|||
var runOpts runOptions |
|||
var initFlags *flag.FlagSet |
|||
|
|||
func init() { |
|||
runOpts = runOptions{} |
|||
runFlags = flag.NewFlagSet("run", flag.ExitOnError) |
|||
runFlags.StringVar(&runOpts.listen, "listen", ":3000", "the address and port on which to listen") |
|||
runFlags.BoolVar(&runOpts.trustProxy, "trust-proxy", false, "trust X-Forwarded-For header") |
|||
runFlags.BoolVar(&runOpts.compress, "compress", true, "enable compression for text,html,js,css,etc") |
|||
runFlags.StringVar(&runOpts.static, "serve-path", "", "path to serve, falls back to built-in web app") |
|||
} |
|||
|
|||
func main() { |
|||
args := os.Args[:] |
|||
if 1 == len(args) { |
|||
// "run" should be the default
|
|||
args = append(args, "run") |
|||
} |
|||
|
|||
if "help" == args[1] { |
|||
// top-level help
|
|||
if 2 == len(args) { |
|||
usage() |
|||
os.Exit(0) |
|||
return |
|||
} |
|||
// move help to subcommand argument
|
|||
self := args[0] |
|||
args = append([]string{self}, args[2:]...) |
|||
args = append(args, "--help") |
|||
} |
|||
|
|||
switch args[1] { |
|||
case "version": |
|||
ver() |
|||
os.Exit(0) |
|||
return |
|||
case "init": |
|||
initFlags.Parse(args[2:]) |
|||
case "run": |
|||
runFlags.Parse(args[2:]) |
|||
serve() |
|||
default: |
|||
usage() |
|||
os.Exit(1) |
|||
return |
|||
} |
|||
} |
|||
|
|||
func serve() { |
|||
r := chi.NewRouter() |
|||
|
|||
// A good base middleware stack
|
|||
if runOpts.trustProxy { |
|||
r.Use(middleware.RealIP) |
|||
} |
|||
if runOpts.compress { |
|||
r.Use(middleware.Compress(flate.DefaultCompression)) |
|||
} |
|||
r.Use(middleware.Logger) |
|||
r.Use(middleware.Recoverer) |
|||
|
|||
pub := http.FileServer(assets.Assets) |
|||
|
|||
var dev http.Handler |
|||
var devFS http.FileSystem |
|||
if len(runOpts.static) > 0 { |
|||
devFS = http.Dir(runOpts.static) |
|||
dev = http.FileServer(devFS) |
|||
r.Get("/*", func(w http.ResponseWriter, r *http.Request) { |
|||
if _, err := devFS.Open(r.URL.Path); nil != err { |
|||
pub.ServeHTTP(w, r) |
|||
return |
|||
} |
|||
dev.ServeHTTP(w, r) |
|||
}) |
|||
} else { |
|||
r.Get("/*", func(w http.ResponseWriter, r *http.Request) { |
|||
pub.ServeHTTP(w, r) |
|||
}) |
|||
} |
|||
|
|||
fmt.Println("Listening for http on", runOpts.listen) |
|||
if err := http.ListenAndServe(runOpts.listen, r); nil != err { |
|||
fmt.Fprintf(os.Stderr, "%s", err) |
|||
os.Exit(1) |
|||
return |
|||
} |
|||
} |
@ -0,0 +1 @@ |
|||
Hello, World! |
@ -0,0 +1,10 @@ |
|||
// +build tools
|
|||
|
|||
// Package tools is a faux package for tracking dependencies that don't make it into the code
|
|||
package tools |
|||
|
|||
import ( |
|||
// these are 'go generate' tooling dependencies, not including in the binary
|
|||
_ "github.com/shurcooL/vfsgen" |
|||
_ "github.com/shurcooL/vfsgen/cmd/vfsgendev" |
|||
) |
불러오는 중...
Reference in new issue