2022-02-06 07:06:32 +00:00
|
|
|
// Copyright (C) 2017 Michael J. Fromberger. All Rights Reserved.
|
|
|
|
|
2021-12-04 16:42:11 +00:00
|
|
|
// Program server demonstrates how to set up a JSON-RPC 2.0 server using the
|
|
|
|
// github.com/creachadair/jrpc2 package.
|
|
|
|
//
|
|
|
|
// Usage (see also the client example):
|
|
|
|
//
|
|
|
|
// go build github.com/creachadair/jrpc2/tools/examples/server
|
|
|
|
// ./server -address :8080
|
|
|
|
//
|
|
|
|
// See also examples/client/client.go.
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"flag"
|
|
|
|
"log"
|
|
|
|
"net"
|
|
|
|
|
|
|
|
"github.com/creachadair/jrpc2"
|
|
|
|
"github.com/creachadair/jrpc2/channel"
|
|
|
|
"github.com/creachadair/jrpc2/code"
|
|
|
|
"github.com/creachadair/jrpc2/handler"
|
|
|
|
"github.com/creachadair/jrpc2/metrics"
|
|
|
|
"github.com/creachadair/jrpc2/server"
|
|
|
|
)
|
|
|
|
|
|
|
|
// A binop carries a pair of integers for use as parameters.
|
|
|
|
type binop struct {
|
|
|
|
X, Y int
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add returns the sum of vs, or 0 if len(vs) == 0.
|
|
|
|
func Add(ctx context.Context, vs []int) int {
|
|
|
|
sum := 0
|
|
|
|
for _, v := range vs {
|
|
|
|
sum += v
|
|
|
|
}
|
|
|
|
return sum
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sub returns the difference x - y.
|
|
|
|
func Sub(ctx context.Context, x, y int) int { return x - y }
|
|
|
|
|
|
|
|
// Mul returns the product arg.X * arg.Y.
|
|
|
|
func Mul(ctx context.Context, x, y int) int { return x * y }
|
|
|
|
|
|
|
|
// Div converts its arguments to floating point and returns their ratio.
|
|
|
|
func Div(ctx context.Context, arg binop) (float64, error) {
|
|
|
|
if arg.Y == 0 {
|
|
|
|
return 0, jrpc2.Errorf(code.InvalidParams, "zero divisor")
|
|
|
|
}
|
|
|
|
return float64(arg.X) / float64(arg.Y), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Status simulates a health check, reporting "OK" to all callers. It also
|
|
|
|
// demonstrates the use of server-side push.
|
|
|
|
func Status(ctx context.Context) (string, error) {
|
|
|
|
if err := jrpc2.ServerFromContext(ctx).Notify(ctx, "pushback", []string{"hello, friend"}); err != nil {
|
|
|
|
return "BAD", err
|
|
|
|
}
|
|
|
|
return "OK", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Alert implements a notification handler that logs its argument.
|
|
|
|
func Alert(ctx context.Context, a map[string]string) error {
|
|
|
|
log.Printf("[ALERT]: %s", a["message"])
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
address = flag.String("address", "", "Service address")
|
|
|
|
maxTasks = flag.Int("max", 1, "Maximum concurrent tasks")
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
|
|
|
if *address == "" {
|
|
|
|
log.Fatal("You must provide a network -address to listen on")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bind the services to their given names.
|
|
|
|
mux := handler.ServiceMap{
|
|
|
|
"Math": handler.Map{
|
|
|
|
"Add": handler.New(Add),
|
|
|
|
"Sub": handler.NewPos(Sub, "X", "Y"),
|
|
|
|
"Mul": handler.NewPos(Mul, "X", "Y"),
|
|
|
|
"Div": handler.New(Div),
|
|
|
|
"Status": handler.New(Status),
|
|
|
|
},
|
|
|
|
"Post": handler.Map{
|
|
|
|
"Alert": handler.New(Alert),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
lst, err := net.Listen(jrpc2.Network(*address))
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Listen:", err)
|
|
|
|
}
|
|
|
|
log.Printf("Listening at %v...", lst.Addr())
|
|
|
|
acc := server.NetAccepter(lst, channel.Line)
|
2022-02-06 07:06:32 +00:00
|
|
|
ctx := context.Background()
|
|
|
|
server.Loop(ctx, acc, server.Static(mux), &server.LoopOptions{
|
2021-12-04 16:42:11 +00:00
|
|
|
ServerOptions: &jrpc2.ServerOptions{
|
|
|
|
Logger: jrpc2.StdLogger(nil),
|
|
|
|
Concurrency: *maxTasks,
|
|
|
|
Metrics: metrics.New(),
|
|
|
|
AllowPush: true,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|