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

Dec 28, 2022
基于Golang的框架Gin开发,项目结构和理念参考Laravel。现支持:MySQL、Redis、MVC、拦截器、助手函数、fresh热更、swagger-UI、tpl模版输出、安全的Api。

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

Nov 18, 2022
Mvc+go+mysqlのrest API テンプレートリポジトリ

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

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

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

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

Nov 7, 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

Dec 21, 2022
Simple and lightweight Go web framework inspired by koa
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

Dec 14, 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

Jan 5, 2023
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

Sep 6, 2022
skr: The lightweight and powerful web framework using the new way for Go.Another go the way.
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

Jan 11, 2022
laravel for golang,goal,fullstack framework,api framework
laravel for golang,goal,fullstack framework,api framework

laravel for golang,goal,fullstack framework,api framework

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 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
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

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

Sep 2, 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

Jan 6, 2023
Couper is a lightweight API gateway designed to support developers in building and operating API-driven Web projects
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

Nov 18, 2022
Lightweight KubeVela that runs as Daemon in single node with high availability.
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

Dec 15, 2022
Gin is a HTTP web framework written in Go (Golang).
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.

Jan 3, 2023