Move server configuration into a config package

- All test variations pass.
parent d13e4c34
......@@ -11,14 +11,17 @@ RFLAG = -race
export GORACE = halt_on_error=1
endif
build:
build: get
go build $(PIE) -ldflags "-X main.vercommit=$(COMMIT) \
-X main.vergo=$(VERGO)" $(RFLAG)
go get -u honnef.co/go/tools/cmd/megacheck
megacheck -simple.exit-non-zero -unused.exported ./...
get:
go get -d -u ./...
# -count 1 is the idiomatic way to disable test caching in package list mode
test:
test: get
go test -count 1 -cover $(RFLAG) ./...
clean:
......
# go-resteasy
### A REST API boilerplate in Go with no external dependencies
### REST API boilerplate in Go with no external dependencies
[![GoDoc](https://godoc.org/gitlab.com/bconway/go-resteasy?status.svg)](https://godoc.org/gitlab.com/bconway/go-resteasy)
[![Go Report Card](https://goreportcard.com/badge/gitlab.com/bconway/go-resteasy)](https://goreportcard.com/report/gitlab.com/bconway/go-resteasy)
Go-resteasy is a JSON- and XML-driven RESTful API boilerplate, written in Go (golang), with no external dependencies (beyond a sample data store - PostgreSQL with contrib modules). It can be used to quickly build back-end services with a REST API as its face. Go-resteasy was written from scratch, with the aid of an inordinate number of [GoDoc](https://godoc.org/) pages.
Go-resteasy is a JSON- and XML-driven RESTful API boilerplate, written in Go (golang), with no external dependencies (beyond a sample data store - PostgreSQL). It can be used to quickly build backend services with a REST API as its face. Go-resteasy was written from scratch, with the aid of an inordinate number of [GoDoc](https://godoc.org/) pages.
## Features
- Routing
- Controllers with complete resource life cycles (POST/GET/PUT/PATCH/DELETE)
- Controllers with complete resource lifecycles (POST/GET/PUT/PATCH/DELETE)
- Extensible middleware for authentication, logging, and more
- Models and Store (using a PostgreSQL data store)
- Models and a Store (using a PostgreSQL database)
- JSON- and XML-driven ResponseWriters
- HATEOAS links on resources
- API Key-based authentication with users, roles, and resource ownership
- Logging, including request performance
- Configuration parser
- Comprehensive integration tests using Ruby minitest, see [integration/README.md](./integration/README.md)
- Binaries versioned by Git tag/commit and Go version
......@@ -36,18 +37,16 @@ Note: Some commands may be OS-specific.
## Building
$ go get -d -u ./...
$ make test
$ make
Note: `make` runs `go build` with link flags for versioning.
## Usage
Usage is available via `./go-resteasy -h`. All flags are also available as similar environmental variables. For example, the following are synonymous:
All configuration is available as environmental variables, with defaults defined in `config/config.go`. For example, the following are synonymous:
$ PGHOST=localhost PGDATABASE=go-resteasy PGUSER=<dbuser> PGPASSWORD=<dbpass> ./go-resteasy
$ ./go-resteasy
$ ./go-resteasy -port 8088 -pgHost localhost -pgDb go-resteasy -pgUser <dbuser> -pgPass <dbpass>
$ RE_PGURI=postgres://<dbuser>:<dbpass>@localhost/go-resteasy ./go-resteasy
## API
......
package config
// Config holds settings used for service configuration.
type Config struct {
PgURI string `env:"RE_PGURI,postgres://postgres:postgres@localhost/go-resteasy"`
}
// New instantiates a Config, parses the environment, and returns it.
func New() *Config {
cfg := &Config{}
parse(cfg)
return cfg
}
package config
import (
"os"
"reflect"
"strings"
)
// tagName is used to annotate Config struct fields.
const tagName = "env"
// parse sets Config fields based on environmental variables and defaults.
// TODO: Only strings are currently supported, additional type casting needed.
func parse(cfg *Config) {
cv := reflect.ValueOf(cfg).Elem()
ct := cv.Type()
for i := 0; i < ct.NumField(); i++ {
f := ct.Field(i)
if tag, ok := f.Tag.Lookup(tagName); ok {
def := strings.Split(tag, ",")
env := os.Getenv(def[0])
if len(def) > 1 && env == "" {
cv.FieldByName(f.Name).Set(reflect.ValueOf(def[1]))
} else {
cv.FieldByName(f.Name).Set(reflect.ValueOf(env))
}
}
}
}
......@@ -6,6 +6,7 @@ import (
"log"
"os"
"gitlab.com/bconway/go-resteasy/config"
"gitlab.com/bconway/go-resteasy/server"
)
......@@ -15,10 +16,6 @@ var (
)
func main() {
pgHost := flag.String("pgHost", os.Getenv("PGHOST"), "PostgreSQL host")
pgDb := flag.String("pgDb", os.Getenv("PGDATABASE"), "PostgreSQL database")
pgUser := flag.String("pgUser", os.Getenv("PGUSER"), "PostgreSQL user")
pgPass := flag.String("pgPass", os.Getenv("PGPASSWORD"), "PostgreSQL password")
ver := flag.Bool("v", false, "Display the version number and exit.")
flag.Parse()
......@@ -27,7 +24,8 @@ func main() {
os.Exit(0)
}
s := server.New(pgHost, pgDb, pgUser, pgPass)
c := config.New()
s := server.New(c)
log.Print(fmt.Sprintf("Listening on %s", s.Addr))
log.Fatal(s.ListenAndServe())
}
......@@ -2,10 +2,10 @@ package server
import (
"database/sql"
"fmt"
"log"
"net/http"
"gitlab.com/bconway/go-resteasy/config"
"gitlab.com/bconway/go-resteasy/controller"
"gitlab.com/bconway/go-resteasy/store"
......@@ -14,10 +14,9 @@ import (
)
// New instantiates a store, controllers, and HTTP server.
func New(pgHost, pgDb, pgUser, pgPass *string) *http.Server {
func New(cfg *config.Config) *http.Server {
// Instantiate and test the database connection.
pg, err := sql.Open("pgx", fmt.Sprintf("host=%s dbname=%s user=%s password=%s",
*pgHost, *pgDb, *pgUser, *pgPass))
pg, err := sql.Open("pgx", cfg.PgURI)
if err != nil {
log.Fatalf("main sql.Open: %v", err)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment