GithubHelp home page GithubHelp logo

go-restapi-boilerplate's Introduction

go-restapi-boilerplate

This is an explanation of how I write "json rest api server" in go. I wrote this to share with my friends who are not familiar with go, but thought it would be great to get feedbacks from the community also. Newbie in go myself, I won't say that this is way to go. But after spending hours to write rest api that is simple, easy to manage, I'm quite satisfied with the result.

This includes extremely simple boilerplate and example for

  • openapi v3 integration(server gen, documents)
  • contextual, structured logging
  • orm
  • access control
  • metrics
  • graceful shutdown
  • configuration through flag, env. (no files, but viper also can load configuration from files)
  • docker image: acadx0/go-restapi-boilerplate
  • kubernetes deploy with kustomize
  • ...

Usage

  • Write spec first (check details below)
  • go generate ./...
  • write your code.
go run cmd/api/main.go

Boilerplate includes CRUD for user as example. Check spec/swagger.yaml

 » http 'localhost:8080/api/v1/user' user_name=aca user_id=acadx0
{
    "id": 1,
    "user_id": "acadx0",
    "user_name": "aca"
}

 » http 'localhost:8080/api/v1/user/acadx0'
{
    "id": 1,
    "user_id": "acadx0",
    "user_name": "aca"
}

Define kubernetes spec with kustomize, check deploy.

kustomize build prod | kubectl apply -f -

Structure

├── api // put all handlers here.
│   ├── api.gen.go
│   ├── api.go 
│   ├── config.go 
│   ├── error.go
│   ├── metrics.go
│   └── user.go // I usually separate file by resource.
├── cmd // put any executable here
│   └── api
├── pkg // library code.
├── ent
│   └── schema // write your ent schema here, I often put other models in here.
└── spec
    └── swagger.yaml

Libraries

Here are the libraries I chose. Some of them are relatively new and may not be mature compared to the competitors. I had to make multiple patches to the listed library to satisfy my use cases. But at least for me, they really helped me to simplify the process. Hope they all have more users and contributors.

  • Openapi integration for documents, client/server codegen. oapi-codegen, kin-openapi
    API service is meaningless without document. But managing documents and code separately gets really messy when your service grows.

    "OpenAPI Specification" defines the standard way to manage your REST API service. Instead of writing code first, write openapi spec(which is extremely simple) with swagger editor first and verify your api. Then, generate code from spec. For client code generation, I recommend openapi-generator. I used it to generate typescript client for my react app. It's just perfect.

    For server code generation, go-swagger seems popular and mature. But It doesn't support openapi spec v3(might not matter that much), and I find it too complicated. oapi-codegen on the otherhand, generates extremely simple go code that you probably won't even have to read the document. It just generates types, and server interface in the name of "OperationID" in your spec.

    In this boilerplate, I generate "openapi components" from ent model. And based on updated swagger.yaml, generate chi-server (but with no types because I just directly use ent generated model).
    So when path.yaml or ent/schema is updated, run go generate ./... to generate code.

  • Web Framework. net/http with chi
    I don't want to learn another framework because I never thought I need it. I believe net/http is enough and complete when writing http service in go. Only thing it lacks is probably router and few helper functions / middlewares. chi has 100% compatibility with net/http. gorilla/mux is more famous for this but, as oapi-codegen only supports chi, I just use chi.

    If you use standard net/http handler, It is extremely simple to integrate with third party middlewares like rs/cors, zerolog.

  • ORM. facebookincubator/ent
    There's lots of ORM in go out there. But If you ever felt that there's something wrong with it, try ent.

      db.Where("name <> ?", "aca").Find(&users) // gorm
      db.User.Query().Where(user.NameEQ("aca")).All(ctx) // ent
    

    Ent generates 100% statically typed go code. With ent, I was able to write code which I felt much more solid. It's amazing project that changed my mind on "orm in go", you should definitely check.

  • Contextual, structured logging. zerolog
    zerolog offers simplest api. It also offers helper library(hlog) that can be used with standard http.Handler, and context.Context integration is amazing.

    ctx := log.With().Str("component", "module").Logger().WithContext(ctx)
    
    // ... somewhere in your function with context
    log.Ctx(ctx).Info().Msg("hello world")
    // Output: {"component":"module","level":"info","message":"hello world"} 
    
  • Configuration. spf13/viper

  • Metrics. - Prometheus
    It is extremely easy to add custom metrics to your server, check api/metrics.go.

  • Access Control. Open Policy Agent
    It is not included in this boilerplate. But I recommend opa. I write rules in REGO, and add opa middlewares between authentication middleware, and handler. It was not easy to learn new "OPA", "REGO" thing. But I use it to define complex rules and control my api without changing my code. The point is to decouple access control with business logic.

go-restapi-boilerplate's People

Contributors

aca avatar hgisinger avatar stevenacoffman avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.