Skip to content

Commit 9bef4dd

Browse files
committed
Initialize project
1 parent 2bbe9a2 commit 9bef4dd

10 files changed

+228
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212

1313
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
1414
.glide/
15+
vendor/

glide.lock

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

glide.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package: base-golang-api
2+
import:
3+
- package: github.com/gorilla/mux
4+
version: v1.6.1
5+
- package: github.com/gorilla/handlers
6+
version: v1.3.0

handler/hello-panic.go

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package handler
2+
3+
import "net/http"
4+
5+
func HelloPanic(w http.ResponseWriter, r *http.Request) {
6+
panic("hello panic!")
7+
}

handler/hello-post.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package handler
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
)
7+
8+
func HelloPost(w http.ResponseWriter, r *http.Request) {
9+
w.WriteHeader(http.StatusOK)
10+
fmt.Fprintf(w, "hello world via post")
11+
}

handler/hello.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package handler
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
)
7+
8+
func HelloWorld(w http.ResponseWriter, r *http.Request) {
9+
w.WriteHeader(http.StatusOK)
10+
fmt.Fprintf(w, "hello world")
11+
}

logger.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"log"
7+
)
8+
9+
// Logger used to construct logger proccess
10+
type Logger struct {
11+
IsDebug bool
12+
}
13+
14+
// Info used to log all INFO's messages
15+
func (l *Logger) Info(msg ...interface{}) {
16+
logger, buf := createNew()
17+
18+
msglog := fmt.Sprintf("INFO: %s", msg)
19+
logger.Print(msglog)
20+
fmt.Println(buf)
21+
}
22+
23+
// Error used to catch any error messages
24+
func (l *Logger) Error(msg ...interface{}) {
25+
logger, buf := createNew()
26+
27+
msglog := fmt.Sprintf("Error: %s", msg)
28+
logger.Print(msglog)
29+
fmt.Println(buf)
30+
}
31+
32+
// Debug used to log all DEBUG's message.
33+
// This method should be active only if current process
34+
// started with -debug (true).
35+
func (l *Logger) Debug(msg ...interface{}) {
36+
if l.IsDebug {
37+
logger, buf := createNew()
38+
39+
msglog := fmt.Sprintf("DEBUG: %s", msg)
40+
logger.Print(msglog)
41+
fmt.Println(buf)
42+
}
43+
}
44+
45+
func logBuilder(isDebug bool) *Logger {
46+
builder := new(Logger)
47+
builder.IsDebug = isDebug
48+
return builder
49+
}
50+
51+
func createNew() (*log.Logger, *bytes.Buffer) {
52+
var buf bytes.Buffer
53+
logger := log.New(&buf, "Log: ", log.Ldate|log.Ltime|log.LUTC)
54+
return logger, &buf
55+
}

main.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"log"
7+
"net/http"
8+
"time"
9+
10+
"github.com/gorilla/handlers"
11+
"github.com/gorilla/mux"
12+
)
13+
14+
var (
15+
logger *Logger
16+
isDebug bool
17+
enablePrintRecovery bool
18+
address string
19+
timeout int
20+
)
21+
22+
const (
23+
isDebugDefault = false
24+
isDebugUsage = "Enable debug mode"
25+
enablePrintRecoveryStackDefault = false
26+
enablePrintRecoveryUsage = "Used to print all stack traces when panic happened"
27+
addressDefault = "127.0.0.1:8080"
28+
addressUsage = "Setup your running ip & port"
29+
timeoutDefault = 15
30+
timeoutUsage = "Set your write and timeout limit"
31+
)
32+
33+
func init() {
34+
flag.StringVar(&address, "address", addressDefault, addressUsage)
35+
flag.BoolVar(&isDebug, "debug", isDebugDefault, isDebugUsage)
36+
flag.BoolVar(&enablePrintRecovery, "enablePrintStack", enablePrintRecoveryStackDefault, enablePrintRecoveryUsage)
37+
flag.IntVar(&timeout, "timeout", timeoutDefault, timeoutUsage)
38+
flag.Parse()
39+
40+
logger = logBuilder(isDebug)
41+
logger.Debug(fmt.Sprintf("Enable Print Recovery? %t", enablePrintRecovery))
42+
logger.Debug(fmt.Sprintf("Timeout: %v", timeout))
43+
logger.Info(fmt.Sprintf("Address: %v", address))
44+
}
45+
46+
func main() {
47+
r := mux.NewRouter()
48+
49+
// register routes and their controllers
50+
routers := RegisterRoutes(r)
51+
52+
// register middlewares
53+
routers.Use(AccessLogMiddleware)
54+
routers.Use(ContentNegotiatorMiddleware)
55+
routers.Use(handlers.RecoveryHandler(handlers.PrintRecoveryStack(enablePrintRecovery)))
56+
57+
srv := &http.Server{
58+
Handler: routers,
59+
Addr: address,
60+
WriteTimeout: time.Duration(timeout) * time.Second,
61+
ReadTimeout: time.Duration(timeout) * time.Second,
62+
}
63+
64+
log.Fatal(srv.ListenAndServe())
65+
}

middlewares.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package main
2+
3+
import (
4+
"net/http"
5+
"os"
6+
7+
"github.com/gorilla/handlers"
8+
)
9+
10+
var (
11+
contentTypes = []string{
12+
"application/json",
13+
"application/vnd.api+json",
14+
}
15+
)
16+
17+
func AccessLogMiddleware(next http.Handler) http.Handler {
18+
loggedMiddleware := handlers.LoggingHandler(os.Stdout, next)
19+
return loggedMiddleware
20+
}
21+
22+
func ContentNegotiatorMiddleware(next http.Handler) http.Handler {
23+
contentTypeNegotiatorMiddleware := handlers.ContentTypeHandler(next, contentTypes...)
24+
return contentTypeNegotiatorMiddleware
25+
}

routes.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package main
2+
3+
import (
4+
controller "base-golang-api/handler"
5+
"net/http"
6+
7+
"github.com/gorilla/mux"
8+
)
9+
10+
// AppHandler used as http endpoint controller
11+
type AppHandler func(w http.ResponseWriter, r *http.Request)
12+
13+
// Route used as a dictionary provide an information about
14+
// endpoint path and endpoint handler (AppHandler)
15+
type Route struct {
16+
Method string
17+
Path string
18+
Handler AppHandler
19+
}
20+
21+
var routes []Route
22+
23+
func init() {
24+
routes = append(routes, Route{"GET", "/hello", controller.HelloWorld})
25+
routes = append(routes, Route{"GET", "/hello-panic", controller.HelloPanic})
26+
routes = append(routes, Route{"POST", "/hello-post", controller.HelloPost})
27+
}
28+
29+
// RegisterRoutes used to activate all configured routes register them to
30+
// gorilla/mux routers.
31+
func RegisterRoutes(r *mux.Router) *mux.Router {
32+
if len(routes) >= 1 {
33+
for _, route := range routes {
34+
r.HandleFunc(route.Path, route.Handler).Methods(route.Method)
35+
}
36+
}
37+
38+
return r
39+
}

0 commit comments

Comments
 (0)