Files
ucan/toolkit/_example/service/service.go

89 lines
2.1 KiB
Go
Raw Normal View History

package main
import (
"context"
"errors"
"log"
"net/http"
"os"
"os/signal"
"syscall"
2025-08-05 12:11:20 +02:00
"github.com/MetaMask/go-did-it"
2025-08-05 12:11:20 +02:00
example "github.com/ucan-wg/go-ucan/toolkit/_example"
"github.com/ucan-wg/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()
}()
2025-02-06 14:19:30 +01:00
err := run(ctx, example.ServiceUrl, example.ServiceDid)
if err != nil {
log.Println(err)
os.Exit(1)
}
}
2025-02-06 14:19:30 +01:00
func run(ctx context.Context, serviceUrl string, serviceDID did.DID) error {
log.Printf("service DID is %s\n", serviceDID.String())
// 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":
2025-02-06 14:19:30 +01:00
log.Printf("handled command %v at %v for %v", ucanCtx.Command(), r.URL.Path, ucanCtx.Invocation().Issuer())
log.Printf("proof is %v", ucanCtx.Invocation().Proof())
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{
2025-02-06 14:19:30 +01:00
Addr: serviceUrl,
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
}