Go package used to create REST, real time, and RPC APIs, where all your reactive web clients are synchronized seamlessly through Resgate.
Visit Resgate.io for more information.
go get github.com/jirenius/go-res
package main
import res "github.com/jirenius/go-res"
func main() {
s := res.NewService("example")
s.Handle("model",
res.Access(res.AccessGranted),
res.GetModel(func(r res.ModelRequest) {
r.Model(struct {
Message string `json:"message"`
}{"Hello, World!"})
}),
)
s.ListenAndServe("nats://localhost:4222")
}
Prerequisite
Install NATS Server and Resgate. Can be done with 3 docker commands:
docker network create res docker run -d --name nats -p 4222:4222 --net res nats docker run --name resgate -p 8080:8080 --net res resgateio/resgate --nats nats://nats:4222
Example | Description |
---|---|
Hello World | Smallest of services serving a static message. |
Edit Text | Single text field that is updated in real time. |
Book Collection | List of book titles & authors that can be edited by many. |
Book Collection Store | Book Collection example persisting changes using BadgerBD store. |
Search Query | Make live queries against a large customer database. |
Note
Above examples are complete with both service and client.
s := res.NewService("myservice")
mymodel := map[string]interface{}{"name": "foo", "value": 42}
s.Handle("mymodel",
res.Access(res.AccessGranted),
res.GetModel(func(r res.ModelRequest) {
r.Model(mymodel)
}),
)
mycollection := []string{"first", "second", "third"}
s.Handle("mycollection",
res.Access(res.AccessGranted),
res.GetCollection(func(r res.CollectionRequest) {
r.Collection(mycollection)
}),
)
s.Handle("article.$id",
res.Access(res.AccessGranted),
res.GetModel(func(r res.ModelRequest) {
article := getArticle(r.PathParam("id"))
if article == nil {
r.NotFound()
} else {
r.Model(article)
}
}),
)
s.Handle("math",
res.Access(res.AccessGranted),
res.Call("double", func(r res.CallRequest) {
var p struct {
Value int `json:"value"`
}
r.ParseParams(&p)
r.OK(p.Value * 2)
}),
)
A change event will update the model on all subscribing clients.
s.With("myservice.mymodel", func(r res.Resource) {
mymodel["name"] = "bar"
r.ChangeEvent(map[string]interface{}{"name": "bar"})
})
An add event will update the collection on all subscribing clients.
s.With("myservice.mycollection", func(r res.Resource) {
mycollection = append(mycollection, "fourth")
r.AddEvent("fourth", len(mycollection)-1)
})
s.Handle("myauth",
res.Auth("login", func(r res.AuthRequest) {
var p struct {
Password string `json:"password"`
}
r.ParseParams(&p)
if p.Password != "mysecret" {
r.InvalidParams("Wrong password")
} else {
r.TokenEvent(map[string]string{"user": "admin"})
r.OK(nil)
}
}),
)
s.Handle("mymodel",
res.Access(func(r res.AccessRequest) {
var t struct {
User string `json:"user"`
}
r.ParseToken(&t)
if t.User == "admin" {
r.AccessGranted()
} else {
r.AccessDenied()
}
}),
res.GetModel(func(r res.ModelRequest) {
r.Model(mymodel)
}),
)
s.Route("v2", func(m *res.Mux) {
m.Handle("mymodel",
/* ... */
)
})
s.ListenAndServe("nats://localhost:4222")
The restest subpackage is used for testing services and validate responses.
The resprot subpackage provides low level structs and methods for communicating with other services over NATS server.
The store subpackage contains handlers and interfaces for working with database storage.
Name | Description | Documentation |
---|---|---|
mockstore | Mock store implementation for testing | |
badgerstore | BadgerDB store implementation |
Inspiration on the go-res API has been taken from github.com/go-chi/chi, a great package when writing ordinary HTTP services, and will continue to do so when it is time to implement Middleware, sub-handlers, and mounting.
The go-res package is still under development, but the API is mostly settled. Any feedback on the package API or its implementation is highly appreciated!
Once the API is fully settled, the package will be moved to the resgateio GitHub organization.
If you find any issues, feel free to report them as an issue.