Mirror

Volodymyr Tkach 698ec9cfd6 StrToInt, IntToStr 1 year ago
.github 70e99a53d4 Create go.yml 2 years ago
utils 698ec9cfd6 StrToInt, IntToStr 1 year ago
LICENSE 103713c3df Initial commit 2 years ago
Makefile c75a16b8b9 Update Makefile 2 years ago
README.md 698ec9cfd6 StrToInt, IntToStr 1 year ago
go.mod ebb3219d5c go 1.19 2 years ago
go.sum 313f558c84 Add RollBar error reporting 2 years ago

README.md

golang-utils

Different kind of functions for second reusage

utils/http/apiserv

Web server, which can use regular expressions in path. Designed to be simple for projects with API

package base

import (
    "net/http"
    ...
)

type Handler struct {
    Ctx      context.Context
    DB       *database.DataBase
    Shutdown context.CancelFunc
}

type ServerData struct {
    ...
}

func (h Handler) FuncMap(w http.ResponseWriter, r *http.Request) template.FuncMap {
    return template.FuncMap{}
}
package page_index

import (
    "net/http"
    ...
)

type Handler struct {
    base.Handler
}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    sess := h.SessionStart(w, r)
    if sess == nil {
        return
    }
    defer sess.Close()

    // /api/v1/aliases/{i}
    // apiserv.GetParams(r)[1].Integer()

    // /api/v1/aliases/{s}
    // apiserv.GetParams(r)[1].String()

    ...

    data := &base.ServerData{}

    if !render.HTML(w, r, h.FuncMap(w, r), data, web.IndexHtml, http.StatusOK) {
        return
    }
}
package server

import (
    "net/http"
    ...
)

func NewMux(ctx context.Context, shutdown context.CancelFunc, db *database.DataBase) *apiserv.ServeMux {
    mux := apiserv.NewServeMux()

    handler := base.Handler{
        Ctx:      ctx,
        DB:       db,
        Shutdown: shutdown,
    }

    // Pages
    mux.Get("/", page_index.Handler{Handler: handler})
    mux.Get("/about", page_about.Handler{Handler: handler})

    // API
    mux.Get("/api/v1/app/health", v1_app_health.Handler{Handler: handler})
    mux.Handle("/api/v1/aliases", apiserv.Methods().Get().Post(), v1_aliases.Handler{Handler: handler})  
    mux.Handle("/api/v1/aliases/{i}", apiserv.Methods().Get().Put().Delete(), v1_aliases.Handler{Handler: handler})

    // Assets
    mux.Get("/favicon.png", helpers.HandleImagePng(web.FaviconPng))
    mux.Get("/robots.txt", helpers.HandleTextPlain(web.RobotsTxt))
    mux.Get("/sitemap.xml", helpers.HandleTextXml(web.SitemapXml))

    // 404
    mux.NotFound(page_404.Handler{Handler: handler})

    return mux
}

func New(ctx context.Context, shutdown context.CancelFunc, db *database.DataBase) (*http.Server, error) {
    mux := NewMux(ctx, shutdown, db)
    srv := &http.Server{
        Addr:    consts.Config.Host + ":" + consts.Config.Port,
        Handler: mux,
    }
    go func() {
        fmt.Printf("Web server: http://%s:%s/\n", consts.Config.Host, consts.Config.Port)
        if err := srv.ListenAndServe(); err != nil {
            if err != http.ErrServerClosed {
                fmt.Printf("Web server startup error: %s\n", err.Error())
                shutdown()
                return
            }
        }
    }()
    return srv, nil
}

utils/http/helpers

type CurlGetOpts struct {
    ExpectStatusCode int
    Headers          map[string][]string
    Timeout          time.Duration
}

func CurlDownload(ctx context.Context, url string, opts *CurlGetOpts, fileName string, filePath ...string) error
func CurlGet(ctx context.Context, url string, opts *CurlGetOpts) ([]byte, error)
func ClientIP(r *http.Request) string
func ClientIPs(r *http.Request) []string
func HandleAppStatus() http.Handler
func HandleFile(data, contentType string) http.Handler
func HandleImageGif(data string) http.Handler
func HandleImageJpeg(data string) http.Handler
func HandleImagePng(data string) http.Handler
func HandleTextCss(data string) http.Handler
func HandleTextJavaScript(data string) http.Handler
func HandleTextPlain(data string) http.Handler
func HandleTextXml(data string) http.Handler
func IntToStr(value int) string
func IntToStr64(value int64) string
func Md5Hash(str []byte) string
func MinifyHtmlCode(str string) string
func MinifyHtmlJsCode(str string) string
func RespondAsBadRequest(w http.ResponseWriter, r *http.Request, err error)
func RespondAsInternalServerError(w http.ResponseWriter, r *http.Request)
func RespondAsMethodNotAllowed(w http.ResponseWriter, r *http.Request)
func SessionStart(w http.ResponseWriter, r *http.Request) (*session.Session, error)
func SetLanguageCookie(w http.ResponseWriter, r *http.Request) error
func StrToInt(value string) int
func StrToInt64(value string) int64

utils/http/logger

Used for write logs, LogRequests can be used in handlers chain

func LogError(format string, a ...any)
func LogInfo(format string, a ...any)
func LogInternalError(err error)
func LogRequests(handler http.Handler) http.Handler

// Write logs to file:
func main() {
    logger.AccessLogFile = consts.Config.AccessLogFile
    logger.ErrorLogFile = consts.Config.ErrorLogFile
    ...
}

RollBar supports from box:

func main() {
    logger.RollBarEnabled = (consts.Config.Deployment == "production")

    logger.RollBarSkipErrors = []string{
        "context canceled",
    }

    rollbar.SetToken("token")
    rollbar.SetEnvironment(consts.Config.Deployment)
    rollbar.SetCodeVersion(consts.AppVersion)

    ...

    rollbar.Wait()
}

utils/http/redirect

HTTP request redirect helper:

func Handler(url string) http.Handler
// Example:
mux.Get("/old", redirect.Handler("/new"))

utils/http/render

Used for rendering HTML pages and for JSON API responses

func HTML(w http.ResponseWriter, r *http.Request, f template.FuncMap, d interface{}, s string, httpStatusCode int) bool
func JSON(w http.ResponseWriter, r *http.Request, o interface{}) bool

utils/http/servauth

Used for adding basic authentication for any HTTP handler

func BasicAuth(handler http.Handler, username, password, realm string) http.Handler

utils/http/servlimit

Used for limiting count of requests per second for client IP

func ReqPerSecond(handler http.Handler, requests int) http.Handler

utils/http/servtools

HTTP handler, universal template and renderer for config

func ConfigVars(config any) http.Handler
package consts

var Config struct {
    Host string `default:"127.0.0.1" description:"Web server IP"`
    Port string `default:"8080" description:"Web server port"`
}

// Example:
mux.Get("/config", servtools.ConfigVars(&consts.Config))

utils/pagination

Pagination helper for build SQL query and HTML template

func New(currentPage, resultsCount, resultsPerPage int64) *Data
func (d *Data) CurrentPage() int64
func (d *Data) MaxPages() int64
func (d *Data) ResultsCount() int64
func (d *Data) ResultsPerPage() int64
func (d *Data) Limit() (int64, int64)
// Example:
currentPage := int64(1)
params := apiserv.GetParams(r)
if len(params) == 2 {
    currentPage = params[1].Integer()
}

resultsCount := int64(0)
if err := h.DB.QueryRow(r.Context(), "SELECT COUNT(*) FROM logs").Scan(&resultsCount); err != nil {
    ...
}

pagination = pagination.New(currentPage, resultsCount, consts.PaginationRowsPerPage)
limit, offset := pagination.Limit()

// SELECT * FROM logs ORDER BY id ASC LIMIT $1 OFFSET $3

utils/penv

Auto-config for parameters and ENV variables

var Config struct {
    Host string `default:"127.0.0.1" description:"Web server IP"`
    Port string `default:"8080" description:"Web server port"`
}

// Example:
func init() {
    if err := penv.ProcessConfig(&Config); err != nil {
        panic(err)
    }
}

func main() {
    fmt.Printf("%s\n", Config.Host)
    fmt.Printf("%s\n", Config.Port)
}

// Auto generated params and ENVs:
// Params will be readed: host, port
// ENV will be readed too: ENV_HOST, ENV_PORT

utils

func RandomString(length int) string