A lightweight MVC framework for Go(Golang)

Overview

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.

Issues
  • 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.

    opened by paganotoni 17
  • 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.

    opened by unreal 16
  • 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
    }
    
    opened by nicola-spb 11
  • 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??

    bug help wanted 
    opened by co11ter 11
  • 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?

    opened by nicola-spb 9
  • 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

    opened by PatWie 8
  • 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

    opened by OsvaldoTCF 8
  • 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?

    opened by eullerpereira94 6
  • 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.

    opened by utrack 6
  • 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.

    opened by shaneutt 5
  • 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.

    opened by kojustin 5
  • 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
    }
    
    opened by tomocy 0
  • 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.

    opened by isocroft 0
  • 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")
    

    `

    opened by joesteel2010 0
  • 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

    opened by alejandro-carstens 2
  • 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

    help wanted ideas 
    opened by nicola-spb 2
Releases(v2.1)
  • v2.0(Dec 4, 2016)

    This marks a very big milestone for the utron framework a lot has happened since the last release I think It is better to reflect on the journey to 2.0.

    v1.0

    First I should apologize for even releasing this version.I had zero knowledge about semantic versioning( I'm still wraping my head around it).

    But what is done, is already done. This version wasnt stable, and It was extremely experimental. I felt like I had this magical hammer back then, and I could hammer the hell out of every problem.

    I should take this chance to highlight some of the short comings of the v1 release

    • race conditions: I'm refering to issue #67 . The way context was handled was deeply flawed. The handlers were sharing the same context not in a safe way.
    • Globals and the limitation of composition : The App struct implements http.Handler interface, which means you can compose applications which can benefit from utron features and yet utilize other libraries/frameworks that the Go eco system offers.
      I thought, making it easy run the application with utron.Run() was a good choice, but It was not. This assumes the application is solely a utron application, behind the hood the library had a global utron application.
      This came at a greater cost, it was hard to compose the application. For instance, you might only want to use utron Controllers, and use your own models ORM . This also made the API duplicate functions which were wrappers that helped manipulate the global utron application.
    • Not being modular : This reddit comment explains more about this

    These are just some of the things , but there are lots of smaller problems with this version that I will a whole blog post to cover.

    Why v2.0?

    • Well this is a fresh start.
    • The API has changed beyond recognition
    • You can use only the parts you like
    • More serious
    • Fixed all the mistakes of v1
    • More examples on how to use

    Does this look interesting to you?

    If you find this interesting, any ideas to improve this framework are welcome !

    Source code(tar.gz)
    Source code(zip)
  • v1.1(Oct 31, 2016)

    • Features
      • Add hcl configs support #66
      • Add mssql support
    • Fixed a race condition bug #68
    • Fixed syncing environmental variables
    • Added a utron logo
    • More test coverage
    • Cleanup and more documentation
    Source code(tar.gz)
    Source code(zip)
  • v1.0(May 8, 2016)

Owner
Geofrey Ernest
hello, world.
Geofrey Ernest
Gerasimos (Makis) Maropoulos 22.7k Aug 7, 2022
基于Golang的框架Gin开发,项目结构和理念参考Laravel。现支持:MySQL、Redis、MVC、拦截器、助手函数、fresh热更、swagger-UI、tpl模版输出、安全的Api。

GinLaravel的构建和运行周期与Beego、Vue、React、Laravel、ThinkPHP、Django等都会有类似的引导思路、参数设置、插件扩展、服务部署、代码统一性、生态护城河等。

方圆 43 Jul 14, 2022
Mvc+go+mysqlのrest API テンプレートリポジトリ

rest-api-temp リポジトリ概要 アドベントカレンダー用に作成 https://qiita.com/advent-calendar/2021/hcb-2021 用途 迅速にrest apiを作らなきゃいけない場合のテンプレート 注意 テンプレートAPIの使用はdocs/api.mdに記載

Takematsu 0 Dec 15, 2021
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

golanger 299 Mar 3, 2022
Eudore is the core of a golang lightweight web framework.

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

null 72 Jul 30, 2022
Lightweight web framework based on net/http.

Goweb Light weight web framework based on net/http. Includes routing middleware logging easy CORS (experimental) Goweb aims to rely only on the standa

Travis Harmon 31 Jul 14, 2022
Simple and lightweight Go web framework inspired by koa

VOX A golang web framework for humans, inspired by Koa heavily. Getting started Installation Using the go get power: $ go get -u github.com/aisk/vox B

An Long 78 Aug 2, 2022
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

Stretchr, Inc. 630 May 10, 2022
Dragon 🐲 🐲 🐲 is a lightweight high performance web framework with Go for the feature and comfortable develop.

Dragon project new link start dragon ab performance Dragon ?? ?? ?? is a lightweight high performance web framework with Go for the feature and comfor

azerothyang 13 Apr 6, 2022
skr: The lightweight and powerful web framework using the new way for Go.Another go the way.

skr Overview Introduction Documents Features Install Quickstart Releases Todo Pull Request Issues Thanks Introduction The lightweight and powerful web

go-the-way 1 Jan 11, 2022
laravel for golang,goal,fullstack framework,api framework

laravel for golang,goal,fullstack framework,api framework

桥边红药 17 Feb 24, 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 Flamingo is a web framework based on Go. It is designed to build pluggable and maintainable web projects. It is production ready, f

Flamingo 305 Aug 4, 2022
The jin is a simplified version of the gin web framework that can help you quickly understand the core principles of a web framework.

jin About The jin is a simplified version of the gin web framework that can help you quickly understand the core principles of a web framework. If thi

null 8 Jul 14, 2022
Best simple, lightweight, powerful and really fast Api with Golang (Fiber, REL, Dbmate) PostgreSqL Database and Clean Architecture

GOLANG FIBER API (CLEAN ARCHITECTURE) Best simple, lightweight, powerful and really fast Api with Golang (Fiber, REL, Dbmate) PostgreSqLDatabase using

Elias Champi 2 May 20, 2022
lightweight, idiomatic and composable router for building Go HTTP services

chi is a lightweight, idiomatic and composable router for building Go HTTP services. It's especially good at helping you write large REST API services

go-chi 11.9k Aug 9, 2022
Couper is a lightweight API gateway designed to support developers in building and operating API-driven Web projects

Couper Couper is a lightweight API gateway designed to support developers in building and operating API-driven Web projects. Getting started The quick

Avenga 70 Jul 31, 2022
Lightweight KubeVela that runs as Daemon in single node with high availability.

VelaD Lightweight KubeVela that runs as Daemon in single node with k3s English | 简体中文 Introduction VelaD helps to set up KubeVela in one step. With th

KubeVela 25 Aug 5, 2022
Gin is a HTTP web framework written in Go (Golang).

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-Gonic 61.7k Aug 7, 2022