A lightweight MVC framework for Go(Golang)

utron logo

utron

GoDoc Coverage Status Build Status Join the chat at https://gitter.im/gernest/utron Go Report Card

utron is a lightweight MVC framework in Go (Golang) for building fast, scalable and robust database-driven web applications.

Features

  • Postgres, MySQL, SQLite and Foundation database support
  • Modular (you can choose which components to use)
  • Middleware support. All alice compatible Middleware works out of the box
  • Gopher spirit (write golang, use all the golang libraries you like)
  • Lightweight. Only MVC
  • Multiple configuration files support (currently json, yaml, toml and hcl)

Overview

utron is a lightweight MVC framework. It is based on the principles of simplicity, relevance and elegance.

  • Simplicity. The design is simple, easy to understand, and doesn't introduce many layers between you and the standard library. It is a goal of the project that users should be able to understand the whole framework in a single day.

  • Relevance. utron doesn't assume anything. We focus on things that matter, this way we are able to ensure easy maintenance and keep the system well-organized, well-planned and sweet.

  • Elegance. utron uses golang best practises. We are not afraid of heights, it's just that we need a parachute in our backpack. The source code is heavily documented, any functionality should be well explained and well tested.

Motivation

After two years of playing with golang, I have looked on some of my projects and asked myself: "How golang is that?"

So, utron is my reimagining of lightweight MVC, that maintains the golang spirit, and works seamlessly with the current libraries.

Installation

utron works with Go 1.4+

 go get github.com/gernest/utron

For the Old API use

go get gopkg.in/gernest/utron.v1

Tutorials

Sample application

Contributing

Start with clicking the star button to make the author and his neighbors happy. Then fork the repository and submit a pull request for whatever change you want to be added to this project.

If you have any questions, just open an issue.

Author

Geofrey Ernest

Twitter : @gernesti

Acknowledgements

These amazing projects have made utron possible:

Licence

This project is released under the MIT licence. See LICENCE for more details.

Owner
Geofrey Ernest
hello, world.
Geofrey Ernest
Comments
  • Environment configuration

    Environment configuration

    @gernest What do you think about reading some config values from the ENV before reading from the config.{ json | yaml | toml } file?

    I'm thinking that in some cases utron will need different values for the database connection and other configuration elements like the port depending on the environment we're running the app, for example our Production database url will be different than our development/testing URL.

    Maybe utron could make the app read ENV variables and if these are not satisfied then read from the config file.

    Other alternative we could do it provide environment specific configuration in the config.{json | yaml | toml} file, but in some cases reading from the ENV would be needed as well.

    Again and as usual, once you agree with one of the alternatives i would be very happy to help.

  • add sqlite3 support

    add sqlite3 support

    I was just kicking the tires a bit with utron and didn't have a mysql or postgres environment to play around in, so I hacked in GORM's sqlite3 support.

    I could be (probably) missing something here, but I figured it wouldn't hurt.

  • Session store

    Session store

    I`m start learning golang. I want to change sessionStore to redis and I found this code. Is it right? May be should be "return ctx.SessionStore.Get" ?

    //GetSession retrieves session with a given name.
    func (ctx *Context) GetSession(name string) (*sessions.Session, error) {
    	if ctx.SessionStore != nil {
    		return ctx.SessionStore.New(ctx.Request(), name)
    	}
    	return nil, errNoStore
    }
    
  • Highload bug

    Highload bug

    Hi!

    I write the code:

    type info struct {
        c http.ResponseWriter
    }
    
    type Test struct {
        *utron.BaseController
    }
    
    func (t *Test) Index() {
        fmt.Println(info{t.Ctx.Response()})
        t.Ctx.Redirect("http://123123123.12", http.StatusFound)
    }
    
    func NewTest() *Test {
        return &Test{}
    }
    

    send many concurent requests to /test:

    siege -f urls.txt -c 10 -t30s -i

    and have error:

    {0xc420691ee0}
    {0xc4207ca000}
    {0xc4207ca0d0}
    {0xc4207ca1a0}
    {0xc4207ca270}
    {0xc4207ca340}
    {0xc4206a4d00}
    {0xc4206a4d00}
    fatal error: concurrent map writes
    
    goroutine 794 [running]:
    runtime.throw(0x9ef0e2, 0x15)
        /usr/lib/go/src/runtime/panic.go:566 +0x95 fp=0xc420505220 sp=0xc420505200
    runtime.mapassign1(0x98f7a0, 0xc4207b8c00, 0xc420505330, 0xc420505340)
        /usr/lib/go/src/runtime/hashmap.go:458 +0x8ef fp=0xc420505308 sp=0xc420505220
    net/textproto.MIMEHeader.Set(0xc4207b8c00, 0x9e551b, 0x8, 0x9edaf9, 0x13)
        /usr/lib/go/src/net/textproto/header.go:22 +0xca fp=0xc420505368 sp=0xc420505308
    net/http.Header.Set(0xc4207b8c00, 0x9e551b, 0x8, 0x9edaf9, 0x13)
        /usr/lib/go/src/net/http/header.go:31 +0x53 fp=0xc4205053a0 sp=0xc420505368
    net/http.Redirect(0xe63320, 0xc4206a4d00, 0xc4207b3680, 0x9edaf9, 0x13, 0x12e)
        /usr/lib/go/src/net/http/server.go:1819 +0xd7 fp=0xc420505488 sp=0xc4205053a0
    github.com/gernest/utron.(*Context).Redirect(0xc420174e70, 0x9edaf9, 0x13, 0x12e)
        /home/coder/go/src/github.com/gernest/utron/context.go:189 +0x5f fp=0xc4205054c8 sp=0xc420505488
    
    ...
    

    Two parallel routines get the same context. Maybe action signature should be

    func (c *SomeController) Action(ctx *utron.Context) {}

    instead to save the context into the controller??

  • Secure config

    Secure config

    In context.go you send config to view (by default). Users can save passwords and tokens in config file. I think it`s not secure. If user will want to have config in view then he put it himself.

    if c.Cfg != nil {
    	c.Data["Config"] = c.Cfg // add configuration to the view data context
    }
    

    What do you think?

  • Split databaseconnection string into multiple environment variables

    Split databaseconnection string into multiple environment variables

    To use this very nice framwork, I tried to setup docker-compose. RubyOnRails and co use a much easier way to connect to databases, namely environment variables shipped by postgresl:latest container.

    I setup you example inside the docker environment: https://github.com/PatWie/ultron-webapp-container

    However, your library refuses the connection. A dump of available variables are:

    DB_ENV_POSTGRES_USERNAME=databaseuser
    DB_PORT_5432_TCP_ADDR=172.17.0.3
    DB_PORT_5403_TCP=tcp://172.17.0.3:5403
    DB_PORT=tcp://172.17.0.3:5403
    DB_ENV_POSTGRES_PASSWORD=c9aca452d8b439b1e484855a0d4ed105
    DB_ENV_LANG=en_US.utf8
    DB_ENV_GOSU_VERSION=1.7
    DB_PORT_5432_TCP=tcp://172.17.0.3:5432
    DB_ENV_PG_MAJOR=9.5
    DB_ENV_affinity:container==19e9f7ed42720d5a332c3402fb784276cb2c579e78fc304a28aef7dd1cb1fb72
    DB_PORT_5403_TCP_PORT=5403
    DB_ENV_POSTGRES_DBNAME=database
    DB_PORT_5432_TCP_PROTO=tcp
    DB_ENV_PG_VERSION=9.5.4-1.pgdg80+1
    DB_PORT_5403_TCP_PROTO=tcp
    DB_PORT_5403_TCP_ADDR=172.17.0.3
    

    These should be automatically already there. So why not rely on these?

    If your framework can be run inside these dockers, it would be an additional argument for using the framework.

    The error-message comes from:

    + exec app
    `` is not officially supported, running under compatibility mode.
    2016/09/12 17:23:54 sql: unknown driver "" (forgotten import?)
    hipanic: runtime error: invalid memory address or nil pointer dereference
    [signal SIGSEGV: segmentation violation code=0x1 addr=0x70 pc=0x46a68a]
    
    goroutine 1 [running]:
    panic(0x8c7ec0, 0xc42000c0a0)
        /usr/local/go/src/runtime/panic.go:500 +0x1a1
    github.com/gernest/utron.Run()
        /go/src/github.com/gernest/utron/utron.go:240 +0x3a
    main.main()
        /go/src/app/main.go:12 +0xa4
    
    

    which basically belongs to this line https://github.com/gernest/utron/blob/master/utron.go#L240

  • A more complex example

    A more complex example

    I will create a more complex example and would like help. It would be great if we had more examples.

    Who can help ...

    https://github.com/OsvaldoTCF/order2go

  • Use of sessions

    Use of sessions

    There was I, just browsing some code at Github, when I decided to read Utron's wiki. Then I stumbled upon the middlewares' page, and a doubt was spawned in my head: how the heck I would use this?Do I just have to follow the Gorilla tutorial, or make use of some gimmick to achieve that?

  • Embedded config structs are now scanned from envvars

    Embedded config structs are now scanned from envvars

    This commit adds recursive scanning of Config struct fields from environment variables. Embedded fields are separated by underscore. Example:

    type Config struct {
      Database struct {
        Kind string
        URI string
      }
    }
    

    now reads DATABASE_KIND and DATABASE_URI environment variables.

  • Make app config more verbose, and enable full addr on ListenAndServe

    Make app config more verbose, and enable full addr on ListenAndServe

    This enables the ability to be more flexible with app configuration. You can now configure scheme and host in addition to port.

    I noticed currently the server will let you configure your port in the base_url and the port in the config differently, and will tell you the base_url port is being used when it is not. This change looks for mismatches and fails instead of telling you something that isn't the case or assuming you want one over the other.

    Currently you can say "localhost" but you'll actually bind to public addresses. This change in conjunction with the configuration changes will allow you to actually bind to the address you intend to via http.ListenAndServe().

    I left a TODO in here to enable TLS listen, but I didn't want to implement that before checking on the rest first. If this merges I would be happy to implement the TLS listen configuration after talking through what is wanted there on gitter or issues.

  • Empty environment variables are ignored

    Empty environment variables are ignored

    In some environments I want to use the environment variables to override the default values that are set in a config file. For example, in a test environment I may want to use an empty db user (e.g. pass DB_USER="" to a particular command) .

    Right now, config.go cannot distinguish between a zero-length environment variable and a environment variable that is not present.

  • Does (*context.Context) GetSession return new session intentionally?

    Does (*context.Context) GetSession return new session intentionally?

    I found the code below in session.go and I wonder this because gorilla/sessions has a method (Store) Get to retrieve a session with a given name.

    //GetSession retrieves session with a given name.
    func (ctx *Context) GetSession(name string) (*sessions.Session, error) {
    	if ctx.SessionStore != nil {
    		return ctx.SessionStore.New(ctx.Request(), name)
    	}
    	return nil, errNoStore
    }
    
  • Consider putting Utron on OpenCollectives

    Consider putting Utron on OpenCollectives

    This is a wonderful project that has grown in leaps and bounds over time (as i have watched it for some time) and the fact that it was started by a Tanzanian is super awesome! I would suggest that a collective be opened here to enable it raise money to make more contributors give more time to work on the project and turn out releases faster the development of utron.

  • Feature/view factory

    Feature/view factory

    I've added in a change to allow the default SimpleView implementation to be replaced by a custom View implementation. Because all templates are parsed when NewMVC is called, there is no way to have templates that rely on other templates in the views directory. This change allows us to define supporting templates and add functions also.

    Example usage:

    utronView.SetViewFactory(func(viewDir string)(utronView.View, error){ return view.NewComplexView("fragments", viewDir, views.FuncMap) })

    app, err := utron.NewMVC("config")
    

    `

  • adding a caching abstraction layer to the Utron framework.

    adding a caching abstraction layer to the Utron framework.

    Hi there,

    This PR is to provide caching functionality out of the box (a cache package). As it stands at the moment the supported stores are Redis, Memcache, and map (local). This would allow for using any store interchangeably without having to change code. The api is very simple to use and rather complete, it allows for the use of tags and it also provides the ability to cache any given type of struct. In addition the code is rather extendible, if we were to add more stores we would just need to comply with the given interfaces and make the tests pass for the given store. I believe the framework could benefit of something like this given to the fact that caching is a major component for any type of application and it keeps the framework lightweight (I would say it makes it even more lightweight, decreasing calls to the db). I appreciate you taking the time to review this PR and I think what you are doing with utron is great. Please let me know your thoughts and have a nice day.

    Alejandro

  • Mapping in controllers

    Mapping in controllers

    All public methods in controllers are mapped to url path by default.

    Maybe will be better if only methods with suffix or prefix "Action" will mapped by default. Some people can`t knew that their methods open for public.

    Example:

    // this will be parsed to /todo/home by default. Method for routing
    func (t *Todo) ActionHome() {
    	todos := []models.Todo{}
    	....
    	t.HTML(http.StatusOK)
    }
    
    // this won`t be parsed by default. Simple public method
    func (t *Todo) Home2() {
    	todos := []models.Todo{}
    	....
    	t.HTML(http.StatusOK)
    }
    

    if user want to set path manual then he can set

    func NewTodo() controller.Controller {
    	return &Todo{
    		Routes: []string{
    			"get;/;Home",			
    		},
    	}
    }
    

    Or maybe add some flexible settings for do it.

    default parsing here https://github.com/gernest/utron/blob/master/router/routes.go#L230

Golanger Web Framework is a lightweight framework for writing web applications in Go.

/* Copyright 2013 Golanger.com. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except

Nov 14, 2022
Eudore is the core of a golang lightweight web framework.

Eudore eudore是一个golang轻量级web框架核心,可以轻松扩展成一个技术栈专用框架,具有完整框架设计体系。 反馈和交流请加群组:QQ群373278915。 Features 易扩展:主要设计目标、核心全部解耦,接口即为逻辑。 简单:对象语义明确,框架代码量少复杂度低,无依赖库。 易用

Nov 7, 2022
A lightweight RESTful web framework for Go
A lightweight RESTful web framework for Go

Goweb A lightweight RESTful web framework for Go. For examples and usage, please read the Goweb API Documentation Read our Articles Who uses Goweb? "U

Dec 12, 2022
Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.
Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.

Flamingo Framework Flamingo is a web framework based on Go. It is designed to build pluggable and maintainable web projects. It is production ready, f

Jan 5, 2023
A lightweight and fast http router from outer space

Alien Alien is a lightweight http router( multiplexer) for Go( Golang ), made for humans who don't like magic. Documentation docs Features fast ( see

Nov 13, 2022
Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.
Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

Gin Web Framework Gin is a web framework written in Go (Golang). It features a martini-like API with performance that is up to 40 times faster thanks

Jan 2, 2023
🍐 Elegant Golang REST API Framework
🍐 Elegant Golang REST API Framework

An Elegant Golang Web Framework Goyave is a progressive and accessible web application framework focused on REST APIs, aimed at making backend develop

Jan 4, 2023
Fast and Reliable Golang Web Framework
Fast and Reliable Golang Web Framework

Gramework The Good Framework Gramework long-term testing stand metrics screenshot made with Gramework Stats Dashboard and metrics middleware What is i

Dec 18, 2022
The web framework for Golang
The web framework for Golang

uAdmin the Golang Web Framework Easy to use, blazing fast and secure. Originally open source by IntegrityNet Solutions and Services For Documentation:

Dec 24, 2022
Golang CTF framework and exploit development module

Golang CTF framework and exploit development module

Dec 18, 2022
An ideally refined web framework for Go.

Air An ideally refined web framework for Go. High-performance? Fastest? Almost all web frameworks are using these words to tell people that they are t

Dec 15, 2022
Web framework for creating apps using Go in Google AppEngine

Welcome to app.go v3.0 app.go is a simple web framework for use in Google AppEngine. Just copy the app folder to your working folder and import it fro

Mar 21, 2021
Goal is a toolkit for high productivity web development in Go language in the spirit of Revel Framework that is built around the concept of code generation.

Goal Goal is a set of tools for high productivity web development in Go language. Goal, being mostly inspired by Revel Framework and its discussions,

Sep 27, 2021
A simple blog framework built with GO. Uses HTML files and a JSON dict to give you more control over your content.

Go-Blog A simple template based blog framework. Instructions Built for GO version: 1 See the Documentation or Getting Started pages in the wiki. Notes

Sep 10, 2022
Goldorak GO is a mini framework for the Go programming language. (unfinished dead code)

Goldorak Go =========== > Goldorak GO ! Rétrolaser en action > Goldorak GO !! Va accomplir ta mission > Dans l'infini > Des galaxies > Poursuis ta lu

Apr 29, 2021
A small and evil REST framework for Go

go-rest A small and evil REST framework for Go Reflection, Go structs, and JSON marshalling FTW! go get github.com/ungerik/go-rest import "github.com/

Dec 6, 2022
A high level web-framework for Go

go-start is a high level web-framework for Go, like Django for Python or Rails for Ruby. Installation: go get github.com/ungerik/go-start Documentatio

Dec 24, 2022
Mango is a modular web-application framework for Go, inspired by Rack, and PEP333.

Mango Mango is a modular web-application framework for Go, inspired by Rack and PEP333. Note: Not actively maintained. Overview Mango is most of all a

Nov 17, 2022
Classy web framework for Go

Martini NOTE: The martini framework is no longer maintained. Martini is a powerful package for quickly writing modular web applications/services in Go

Dec 29, 2022