RES service package
A Go package implementing the RES-Service protocol for Resgate - Real-time API Gateway.
When you want to create stateless REST API services but need to have all your resources updated in real time on your reactive web clients.
All resources and methods served by RES services are made accessible through Resgate in two ways:
- Ordinary HTTP requests
- Over WebSocket using ResClient
With ResClient, all resources will be updated in real time, without having to write a single line of client code to handle specific events. It just works.
Installation
go get github.com/jirenius/go-resExamples
- Hello World - Single model updated in real time
- Book Collection - List of books, added, edited, and updated in real time
As easy as
package main
import res "github.com/jirenius/go-res"
func main() {
s := res.NewService("hello")
s.Handle("world",
res.Access(res.AccessGranted),
res.GetModel(func(w res.GetModelResponse, r *res.Request) {
w.Model(map[string]string{"greeting": "welcome"})
}),
)
s.ListenAndServe("nats://localhost:4222")
}Usage
While a RES service communicates over a message broker (NATS Server), instead of listening to HTTP request, the pattern of requests and responses are similar.
Create a new service
serv := res.NewService("myservice")
Add model handlers
mymodel := map[string]interface{}{"name": "foo", "value": 42}
s.Handle("mymodel",
res.Access(res.AccessGranted),
res.GetModel(func(w res.GetModelResponse, r *res.Request) {
w.Model(mymodel)
}),
)Add collection handlers
mycollection := []string{"first", "second", "third"}
s.Handle("mycollection",
res.Access(res.AccessGranted),
res.GetCollection(func(w res.GetCollectionResponse, r *res.Request) {
w.Collection(mycollection)
}),
)Add handlers for parameterized resources
s.Handle("article.$id",
res.Access(res.AccessGranted),
res.GetModel(func(w res.GetModelResponse, r *res.Request) {
article := getArticle(r.PathParams["id"])
if article == nil {
w.NotFound()
} else {
w.Model(article)
}
}),
)Add handlers for method calls
s.Handle("math",
res.Access(res.AccessGranted),
res.Call("double", func(w res.CallResponse, r *res.Request) {
var p struct {
Value int `json:"value"`
}
r.UnmarshalParams(&p)
w.OK(p.Value * 2)
}),
)Send change event on model update
A change event will update the model on all subscribing clients.
s.Get("myservice.mymodel", func(r *res.Resource) {
mymodel["name"] = "bar"
r.ChangeEvent(map[string]interface{}{"name": "bar"})
})Send add event on collection update:
An add event will update the collection on all subscribing clients.
s.Get("myservice.mycollection", func(r *res.Resource) {
mycollection = append(mycollection, "fourth")
r.AddEvent("fourth", len(mycollection)-1)
})Start service
s.ListenAndServe("nats://localhost:4222")Credits
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.
Contributing
The go-res package is still under development, and commits may still contain breaking changes. It should only be used for educational purpose. Any feedback on the package API or its implementation is highly appreciated!
If you find any issues, feel free to report them as an Issue.