Skip to content

ohait/forego

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

254 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

forego

Build Go JSON/WebSocket services with tagged logging, auto-wired APIs, and test-first ergonomics.

Why Forego

  • Tagged JSON logs keep every request’s story without coupling handlers to a logger. Attach tags with ctx.WithTag, and ctx/log takes care of consistently emitting them.
  • The http, api, and test packages form a feedback loop: define a Go struct once, expose it over HTTP/WebSocket, and exercise it in your tests without binding boilerplate.
  • Batteries stay optional. Supporting packages like enc, shutdown, and utils/prom plug in when you need them without locking you into a monolith.

Quickstart

  1. Install the module:
    go get github.com/ohait/forego@latest
  2. Wire an API, HTTP server, and graceful shutdown:
    package main
    
    import (
        "regexp"
    
        fctx "github.com/ohait/forego/ctx"
        flog "github.com/ohait/forego/ctx/log"
        fhttp "github.com/ohait/forego/http"
        "github.com/ohait/forego/shutdown"
    )
    
    type WordFilter struct {
        Blacklist *regexp.Regexp
    
        In  string `api:"in,required"`
        Out string `api:"out"`
    }
    
    func (wf *WordFilter) Do(c fctx.C) error {
        wf.Out = wf.Blacklist.ReplaceAllString(wf.In, "***")
        return nil
    }
    
    func main() {
        c, cf := fctx.Background()
        defer cf(nil)
    
        c = fctx.WithTag(c, "service", "wordfilter")
    
        srv := fhttp.NewServer(c)
        srv.MustRegisterAPI(c, "/api/wordfilter/v1", &WordFilter{
            Blacklist: regexp.MustCompile(`(foo|bar)`),
        })
    
        addr, err := srv.Listen(c, "127.0.0.1:8080")
        if err != nil {
            panic(err)
        }
        flog.Infof(c, "listening on %s", addr.String())
    
        shutdown.WaitForSignal(c, cf)
    }
  3. Call the endpoint; the OpenAPI definition is already available at /openapi.json:
    curl -s -X POST localhost:8080/api/wordfilter/v1 \
      -H 'content-type: application/json' \
      -d '{"in":"foo and friends"}'
  4. Test the same struct without HTTP glue:
    import (
        "regexp"
        "testing"
    
        "github.com/ohait/forego/api"
        "github.com/ohait/forego/test"
     )
    
     func TestWordFilter(t *testing.T) {
         c := test.Context(t)
         out := api.Test(c, &WordFilter{
             Blacklist: regexp.MustCompile(`(foo|bar)`),
             In:        "foo and bar",
         })
    
         test.EqualsStr(t, "*** and ***", out.Out)
     }

Architecture Overview

  • ctx / ctx/log: wrap context.Context so tags, rich errors, and JSON logs travel together; handlers don’t have to know who consumes the logs.
  • http, api, http/ws: map structs to REST and WebSocket endpoints, emit OpenAPI, and reuse the same types in business logic and tests.
  • test: AST-aware assertions that reuse your API structs directly, producing readable success and failure output.
  • enc: an intermediate JSON representation that keeps parsing efficient when you need custom coercion.
  • shutdown, utils/prom, storage: supporting utilities for graceful shutdown, lightweight metrics, and simple storage patterns.

Observability by Default

c = fctx.WithTag(c, "tracking", "a1b2c3")
flog.Infof(c, "completed request")

Produces a JSONL entry similar to:

{"level":"info","message":"completed request","tags":{"service":"wordfilter","tracking":"a1b2c3"}}

Every handler in forego/http automatically enriches tags with user agent, path, remote address, and exposes the same metadata to your own log calls.

Package Tour

  • api — bind Go structs to RPC-style operations, generate OpenAPI, and provide helpers to test them directly.
  • enc — flexible JSON intermediate forms (enc.Node, enc.Map, enc.Pairs) that avoid json.RawMessage gymnastics.
  • http — production-grade HTTP server with automatic request tagging, gzip, OpenAPI serving, and API registration.
  • http/ws — WebSocket RPC bindings that reuse the same struct/tag approach as REST.
  • ctx — context helpers, tagged metadata, structured logging, and rich error wrappers.
  • shutdown — graceful signal handling with hold/release coordination.
  • test — expressive assertions powered by source analysis.
  • utils/prom — lightweight Prometheus-compatible metrics.
  • utils — shared helpers (AST, caches, lists, sync) used across packages.

When to Use / When to Wait

  • Use it when you’re building Go JSON or WebSocket services and want consistent logging, automatic documentation, and tests that stay close to your business logic.
  • Wait if you need a polished, stable framework or non-Go integrations—this project is still evolving and APIs may move.

Further details live in the package READMEs linked above.

About

Go framework

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Go 99.7%
  • Makefile 0.3%