Files
ucan/toolkit/_example/server/server.go
2025-08-05 16:57:19 +02:00

86 lines
2.0 KiB
Go

package main
import (
"context"
"errors"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"github.com/ucan-wg/go-ucan/did"
example "github.com/INFURA/go-ucan-toolkit/_example"
"github.com/INFURA/go-ucan-toolkit/server/exectx"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
// register as handler of the interrupt signal to trigger the teardown
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
go func() {
<-quit
cancel()
}()
err := run(ctx, example.ServerUrl, example.ServiceDid)
if err != nil {
log.Println(err)
os.Exit(1)
}
}
func run(ctx context.Context, serverUrl string, serviceDID did.DID) error {
// we'll make a simple handling pipeline:
// - exectx.ExtractMW to extract and decode the UCAN context, verify the service DID
// - exectx.HttpExtArgsVerify to verify the HTTP policies
// - exectx.EnforceMW to perform the final UCAN checks
// - our handler to execute the commands
var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ucanCtx, ok := exectx.FromContext(r.Context())
if !ok {
http.Error(w, "no ucan-ctx found", http.StatusInternalServerError)
return
}
switch ucanCtx.Command().String() {
case "/foo/bar":
log.Printf("handled command %v for %v", ucanCtx.Command(), ucanCtx.Invocation().Issuer())
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("OK"))
default:
http.Error(w, "unknown UCAN commmand", http.StatusBadRequest)
return
}
})
handler = exectx.EnforceMW(handler)
handler = exectx.HttpExtArgsVerify(handler)
handler = exectx.ExtractMW(handler, serviceDID)
srv := &http.Server{
Addr: serverUrl,
Handler: handler,
}
go func() {
if err := srv.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
log.Fatalf("listen: %s\n", err)
}
}()
log.Printf("listening on %s\n", srv.Addr)
<-ctx.Done()
if err := srv.Shutdown(ctx); err != nil && !errors.Is(err, context.Canceled) {
return err
}
return nil
}