github.com/riyadhalnur/godi

'Godi' - pillow in Bengali, is a simple but highly opinionated Go server template that you can use to bootstrap your Go web applications and/or use as use the modules in your project as you see fit.


Keywords
api, application, go, golang, opinionated, server, template, template-project, web
License
MIT
Install
go get github.com/riyadhalnur/godi

Documentation

Godi

Go

'Godi' - pillow in Bengali, is a simple but highly opinionated Go server template that you can use to bootstrap your Go web applications and/or use as use the modules in your project as you see fit.

Requirements

  1. Go >= 1.13
  2. Docker (optional)
  3. Kubernetes (optional)
  4. Kustomize (optional)
  5. Direnv (optional)

Structure

.
|-- cmd
|   `-- api
|       `-- main.go
|-- deploy
|   |-- base
|   |   |-- deployment.yml
|   |   |-- kustomization.yml
|   |   `-- service.yml
|   `-- overlays
|       `-- dev
|           |-- config-map.yml
|           `-- kustomization.yml
|-- Dockerfile
|-- go.mod
|-- go.sum
|-- Makefile
|-- pkg
|   |-- godierr
|   |   |-- error.go
|   |   |-- error_test.go
|   |   |-- sentinel.go
|   |   `-- sentinel_test.go
|   |-- logger
|   |   |-- logger.go
|   |   `-- logger_test.go
|   |-- middleware
|   |   |-- request.go
|   |   `-- request_test.go
|   `-- server
|       |-- config.go
|       |-- server.go
|       |-- server_test.go
|       `-- util
|           |-- event.go
|           |-- response.go
|           |-- response_test.go
|           |-- route.go
|           |-- type.go
|           `-- type_test.go
|-- README.md
`-- static
    |-- css
    |   `-- main.css
    `-- index.html

Installing

go get -u github.com/riyadhalnur/godi/v2

Developing

Run tests using

make test

To run the server, in cmd/api/,

make run

Build a binary in cmd/api using

make build

Build a Docker image

docker build -t godi .  

Deploy to Kubernetes

kubectl apply -k deploy/overlay/dev  

Healthcheck

The server package exposes a health endpoint by default at /health.

Logging

The logger package is modeled after the standard log package in Go to expose a global logger that is configured to provide a uniform logging experience across the application. It wraps zap with custom configuration that plays nice with Docker, Kubernetes and Stackdriver.

Methods not ending with f are aliases for zap.<LEVEL>w methods that accept loosely typed key-value pairs, e.g.

logger.Info("Failed to fetch URL.",
    "url", url,
)

If DEBUG mode is true in the environment, debug level messages are logged to stdout. Otherwise, everything less than error level but not debug level is routed to stdout. The benefits of this are being able to turn on debug mode without having to redeploy your application or having to worry about leaving debug logs in your code. Just a simple restart will do.

Errors and anything above are routed to stderr by default.

Adding new services and middlewares

Middlewares
By default, the default server will mount a request ID middleware that adds an X-Request-ID header to all incoming requests. To define new middlewares, define it inside pkg/middleware and then mount/register it with the server instance,

srv := &Server{}
srv.AddMiddlewares(middleware.MyMiddlewareFunc)
...

P.S. Middleware order matters. Additionally, you can use any middleware that matches the http.HandlerFunc signature.

Services
To add and register a service, create a new folder under pkg/service/<service-name> or pkg/api/<api-name> or api/<api-name>. How you wish to structure your routes and their respective controllers is upto you. Make sure to export the list of routes and then register them with the server instance to mount them when it starts.

// in ../user/routes.go
Routes := []util.Route{
  util.Route{
    "createUser",
    http.MethodPost,
    "/user",
    CreateUser,
  },
}

// then in your main.go
srv := &Server{}
srv.AddRoutes(user.Routes...)
...

Static files

The boilerplate comes with a basic HTML page and a rudimentary stylesheet inside the /static folder. By default, the server will not serve any static files. You have to explicitly pass in the path to the folder when configuring the server instance. The static files though are always served at the /static path of the listening server.

Environment variables

Environment variables are never read directly by the pkg/server package (to make sure there are no surprises); it uses the Configuration struct passed in when creating a new *Server. Use environment variables when implementing it. Refer to cmd/api/main.go for usage.

PORT=<port-server-listens-on> // defaults to 3001
STATIC_DIR=<static-file-directory>
TIMEOUT=<server-timeout-in-seconds> // write/read/idle timeouts
DEBUG=<true-or-false>

Contributing

Read the CONTRIBUTING guide for information.

License

Licensed under MIT. See LICENSE for more information.

Issues

Report a bug in issues.

Made with love in Kuala Lumpur, Malaysia by Riyadh Al Nur