Skip to content
This repository was archived by the owner on Sep 21, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* [x] Middleware support. All [alice](https://github.com/justinas/alice) compatible Middleware works out of the box
* [x] Gopher spirit (write golang, use all the golang libraries you like)
* [x] Lightweight. Only MVC
* [x] Multiple configuration files support (currently json, yaml and toml)
* [x] Multiple configuration files support (currently json, yaml, toml and hcl)



Expand Down Expand Up @@ -88,7 +88,7 @@ I have included three configuration files to show how they work, but you are bet
## Configurations
utron support yaml, json and toml configurations files. In our todo app, we put the configuration files in the config directory. I have included all three formats for clarity, you can be just fine with either one of them.

`utron` searches for a file named `app.json`, or `app.yml` or `app.toml` in the config directory. The first to be found is the one to be used.
`utron` searches for a file named `app.json`, or `app.yml`, `app.toml`, `app.hcl` in the config directory. The first to be found is the one to be used.

This is the content of `config/app.json` file:

Expand Down
30 changes: 19 additions & 11 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,21 @@ import (

"github.com/BurntSushi/toml"
"github.com/fatih/camelcase"
"github.com/hashicorp/hcl"
"gopkg.in/yaml.v2"
)

// Config stores configurations values
type Config struct {
AppName string `json:"app_name" yaml:"app_name" toml:"app_name"`
BaseURL string `json:"base_url" yaml:"base_url" toml:"base_url"`
Port int `json:"port" yaml:"port" toml:"port"`
Verbose bool `json:"verbose" yaml:"verbose" toml:"verbose"`
StaticDir string `json:"static_dir" yaml:"static_dir" toml:"static_dir"`
ViewsDir string `json:"view_dir" yaml:"view_dir" toml:"view_dir"`
Database string `json:"database" yaml:"database" toml:"database"`
DatabaseConn string `json:"database_conn" yaml:"database_conn" toml:"database_conn"`
Automigrate bool `json:"automigrate" yaml:"automigrate" toml:"automigrate"`
AppName string `json:"app_name" yaml:"app_name" toml:"app_name" hcl:"app_name"`
BaseURL string `json:"base_url" yaml:"base_url" toml:"base_url" hcl:"base_url"`
Port int `json:"port" yaml:"port" toml:"port" hcl:"port"`
Verbose bool `json:"verbose" yaml:"verbose" toml:"verbose" hcl:"verbose"`
StaticDir string `json:"static_dir" yaml:"static_dir" toml:"static_dir" hcl:"static_dir"`
ViewsDir string `json:"view_dir" yaml:"view_dir" toml:"view_dir" hcl:"view_dir"`
Database string `json:"database" yaml:"database" toml:"database" hcl:"database"`
DatabaseConn string `json:"database_conn" yaml:"database_conn" toml:"database_conn" hcl:"database_conn"`
Automigrate bool `json:"automigrate" yaml:"automigrate" toml:"automigrate" hcl:"automigrate"`
}

// DefaultConfig returns the default configuration settings.
Expand All @@ -47,6 +48,7 @@ func DefaultConfig() *Config {
// * .json - is decoded as json
// * .yml - is decoded as yaml
// * .toml - is decoded as toml
// * .hcl - is decoded as hcl
func NewConfig(path string) (*Config, error) {
_, err := os.Stat(path)
if err != nil {
Expand Down Expand Up @@ -75,7 +77,14 @@ func NewConfig(path string) (*Config, error) {
if yerr != nil {
return nil, yerr
}

case ".hcl":
obj, herr := hcl.Parse(string(data))
if herr != nil {
return nil, herr
}
if herr = hcl.DecodeObject(&cfg, obj); herr != nil {
return nil, herr
}
default:
return nil, errors.New("utron: config file format not supported")
}
Expand Down Expand Up @@ -110,7 +119,6 @@ func (c *Config) saveToFile(path string) error {
return err
}
data = b.Bytes()

}
return ioutil.WriteFile(path, data, 0600)
}
Expand Down
1 change: 1 addition & 0 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ func TestConfig(t *testing.T) {
"fixtures/config/app.json",
"fixtures/config/app.yml",
"fixtures/config/app.toml",
"fixtures/config/app.hcl",
}

cfg := DefaultConfig()
Expand Down
9 changes: 9 additions & 0 deletions fixtures/config/app.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
app_name = "utron web app"
base_url = "http://localhost:8090"
port = 8090
verbose = false
static_dir = "fixtures/static"
view_dir = "fixtures/view"
database = ""
database_conn = ""
automigrate = true
4 changes: 4 additions & 0 deletions fixtures/config/routes.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
routes = [
"get,post;/hello;Sample.Hello",
"get,post;/about;Hello.About"
]
14 changes: 12 additions & 2 deletions routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/BurntSushi/toml"
"github.com/gernest/ita"
"github.com/gorilla/mux"
"github.com/hashicorp/hcl"
"github.com/justinas/alice"
"gopkg.in/yaml.v2"
)
Expand Down Expand Up @@ -415,7 +416,7 @@ type routeFile struct {
// ]
// }
//
// supported formats are json,toml and yaml with extension .json, .toml and .yml respectively.
// supported formats are json, toml, yaml and hcl with extension .json, .toml, .yml and .hcl respectively.
//
//TODO refactor the decoding part to a separate function? This part shares the same logic as the
// one found in NewConfig()
Expand All @@ -441,6 +442,14 @@ func (r *Router) LoadRoutesFile(file string) error {
if err != nil {
return err
}
case ".hcl":
obj, err := hcl.Parse(string(data))
if err != nil {
return err
}
if err = hcl.DecodeObject(&rFile, obj); err != nil {
return err
}
default:
return errors.New("utron: unsupported file format")
}
Expand All @@ -461,8 +470,9 @@ func (r *Router) LoadRoutesFile(file string) error {
// * routes.json
// * routes.toml
// * routes.yml
// * routes.hcl
func (r *Router) loadRoutes(cfgPath string) {
exts := []string{".json", ".toml", ".yml"}
exts := []string{".json", ".toml", ".yml", ".hcl"}
rFile := "routes"
for _, ext := range exts {
file := filepath.Join(cfgPath, rFile+ext)
Expand Down
48 changes: 28 additions & 20 deletions routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,31 +92,39 @@ func TestRouteField(t *testing.T) {
}

func TestRoutesFile(t *testing.T) {
file := "fixtures/config/routes.json"
r := NewRouter()

err := r.LoadRoutesFile(file)
if err != nil {
t.Error(err)
routeFiles := []string{
"fixtures/config/routes.json",
"fixtures/config/routes.hcl",
}
if len(r.routes) != 2 {
t.Errorf("expcted 2 got %d", len(r.routes))
}
_ = r.Add(NewSample())

req, err := http.NewRequest("GET", "/hello", nil)
if err != nil {
t.Error(err)
}
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
for _, file := range routeFiles {
r := NewRouter()

if w.Code != http.StatusOK {
t.Errorf("expected %d got %d", http.StatusOK, w.Code)
}
if w.Body.String() != msg {
t.Errorf("expected %s got %s", msg, w.Body.String())
err := r.LoadRoutesFile(file)
if err != nil {
t.Error(err)
}
if len(r.routes) != 2 {
t.Errorf("expcted 2 got %d", len(r.routes))
}
_ = r.Add(NewSample())

req, err := http.NewRequest("GET", "/hello", nil)
if err != nil {
t.Error(err)
}
w := httptest.NewRecorder()
r.ServeHTTP(w, req)

if w.Code != http.StatusOK {
t.Errorf("expected %d got %d", http.StatusOK, w.Code)
}
if w.Body.String() != msg {
t.Errorf("expected %s got %s", msg, w.Body.String())
}
}

}

func TestSplitRoutes(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion utron.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func loadConfig(cfg ...string) (*Config, error) {

// findConfigFile finds the configuration file name in the directory dir.
func findConfigFile(dir string, name string) (file string, err error) {
extensions := []string{".json", ".toml", ".yml"}
extensions := []string{".json", ".toml", ".yml", ".hcl"}

for _, ext := range extensions {
file = filepath.Join(dir, name)
Expand Down