Skip to content

Commit

Permalink
test: add examples
Browse files Browse the repository at this point in the history
  • Loading branch information
vizee committed May 6, 2023
1 parent 0da88d2 commit aa1a742
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 0 deletions.
5 changes: 5 additions & 0 deletions examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*.pb.go
*.pd

/gateway/gateway
/helloworld/server/server
137 changes: 137 additions & 0 deletions examples/gateway/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package main

import (
"encoding/json"
"flag"
"log"
"net/http"
"os"

"github.com/vizee/gapi/engine"
"github.com/vizee/gapi/handlers/httpview"
"github.com/vizee/gapi/handlers/jsonapi"
"github.com/vizee/gapi/metadata"
"github.com/vizee/gapi/proto/descriptor"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/descriptorpb"
)

func writeJsonResponse(w http.ResponseWriter, o any) {
w.Header().Set("Content-Type", "application/json")
data, _ := json.Marshal(o)
_, _ = w.Write(data)
}

func newEngine() *engine.Engine {
builder := engine.NewBuilder()

builder.RegisterHandler("httpview", &httpview.Handler{
PassPath: true,
PassQuery: true,
PassParams: true,
CopyHeaders: true,
FilterHeaders: []string{"Content-Type", "User-Agent"},
MaxBodySize: 1 * 1024 * 1024,
})
builder.RegisterHandler("jsonapi", &jsonapi.Handler{})

builder.RegisterMiddleware("sign", func(ctx *engine.Context) error {
sign := ctx.Request().URL.Query().Get("sign")
if sign == "good" {
return ctx.Next()
} else {
http.Error(ctx.Response(), http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return nil
}
})

builder.RegisterMiddleware("auth", func(ctx *engine.Context) error {
uid := ctx.Request().URL.Query().Get("uid")
if uid != "" {
ctx.Set("uid", uid)
return ctx.Next()
} else {
http.Error(ctx.Response(), http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return nil
}
})

builder.Use(func(ctx *engine.Context) error {
log.Printf("<> %s %s", ctx.Request().Method, ctx.Request().URL.String())
return ctx.Next()
})
builder.Use(func(ctx *engine.Context) error {
err := ctx.Next()
if err != nil {
if s, ok := status.FromError(err); ok {
if s.Code() >= 1000 {
writeJsonResponse(ctx.Response(), map[string]any{
"code": s.Code(),
"message": s.Message(),
})
return nil
}
}
log.Printf("ERROR %s %v", ctx.Request().RequestURI, err)
http.Error(ctx.Response(), http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
return nil
})

builder.NotFound(func(ctx *engine.Context) error {
http.NotFound(ctx.Response(), ctx.Request())
return nil
})

return builder.Build()
}

func loadRoutes(fname string) ([]metadata.Route, error) {
data, err := os.ReadFile(fname)
if err != nil {
return nil, err
}

var fds descriptorpb.FileDescriptorSet
err = proto.Unmarshal(data, &fds)
if err != nil {
return nil, err
}
p := descriptor.NewParser()
for _, fd := range fds.File {
err := p.AddFile(fd)
if err != nil {
return nil, err
}
}

return metadata.ResolveRoutes(&metadata.MessageCache{}, p.Services(), false)
}

func main() {
var (
pdFile string
listenAddr string
)
flag.StringVar(&pdFile, "pd", "file.pd", "pd file")
flag.StringVar(&listenAddr, "l", ":8080", "listen address")
flag.Parse()

engine := newEngine()
routes, err := loadRoutes(pdFile)
if err != nil {
log.Fatalf("loadRoutes: %v", err)
}
err = engine.RebuildRouter(routes, false)
if err != nil {
log.Fatalf("RebuildRouter: %v", err)
}

log.Printf("listening: %s", listenAddr)

err = http.ListenAndServe(listenAddr, engine)
if err != nil {
log.Fatalf("srv.ListenAndServe: %v", err)
}
}
6 changes: 6 additions & 0 deletions examples/helloworld/proto/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
GAPI_PROTO ?= .

proto:
@protoc -I . -I $(GAPI_PROTO) --descriptor_set_out=helloworld.pd \
--go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld.proto
31 changes: 31 additions & 0 deletions examples/helloworld/proto/helloworld.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
syntax = "proto3";

package gapi.examples.helloworld.proto;

option go_package = "github.com/vizee/gapi/examples/helloworld/proto";

import "gapi/annotation.proto";

service Greeter {
option (gapi.server) = "localhost:50051";
option (gapi.default_handler) = "jsonapi";
option (gapi.default_timeout) = 5000;
option (gapi.path_prefix) = "/greeter";
option (gapi.use) = "sign";

rpc SayHello (HelloRequest) returns (HelloReply) {
option (gapi.http) = {
post: "/sayHello"
use: "auth"
};
}
}

message HelloRequest {
string name = 1;
string userId = 2 [(gapi.alias) = "uid", (gapi.bind) = FROM_CONTEXT];
}

message HelloReply {
string message = 1;
}
46 changes: 46 additions & 0 deletions examples/helloworld/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package main

import (
"context"
"fmt"
"log"
"net"

"github.com/vizee/gapi/examples/helloworld/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/status"
)

type Greeter struct {
proto.UnimplementedGreeterServer
}

func (*Greeter) SayHello(ctx context.Context, req *proto.HelloRequest) (*proto.HelloReply, error) {
log.Printf("SayHello: %s", req)

if len(req.Name) < 3 {
return nil, status.Errorf(1000, "name too short")
}

return &proto.HelloReply{
Message: fmt.Sprintf("Hello %s(%s)", req.Name, req.UserId),
}, nil
}

func main() {
const listenAddr = ":50051"

srv := grpc.NewServer()
proto.RegisterGreeterServer(srv, &Greeter{})
ln, err := net.Listen("tcp", listenAddr)
if err != nil {
log.Fatalf("listen: %v", err)
}

log.Printf("listening: %s", listenAddr)

err = srv.Serve(ln)
if err != nil {
log.Fatalf("serve: %v", err)
}
}

0 comments on commit aa1a742

Please sign in to comment.