Added in gRPC-web support and boilerplate code for a client

This commit is contained in:
mame82 2018-05-13 20:50:55 +00:00
parent 690397468a
commit 0ac4c706e5
15 changed files with 31716 additions and 3 deletions

View File

@ -40,5 +40,5 @@ func main() {
service.InitLed(false) //Set LED to manual trigger
service.InitDefaultLEDSettings()
service.StartRpcServer("", "50051") //start gRPC service
service.StartRpcServerAndWeb("0.0.0.0", "50051") //start gRPC service
}

View File

@ -1,2 +1,7 @@
#!/bin/bash
# golang version
protoc -I proto/ proto/grpc.proto --go_out=plugins=grpc:proto
# gopherjs version
protoc -I proto/ proto/grpc.proto --gopherjs_out=plugins=grpc:proto/gopherjs

View File

@ -144,7 +144,6 @@ func cobraUsbSet(cmd *cobra.Command, args []string) {
}
}
//ToDo: Implement detailed UMS settings
if (cmd.Flags().Lookup("ums").Changed) {
if tmpUseUMS == 0 {
fmt.Println("Disabeling USB Mass Storage")
@ -171,9 +170,9 @@ func cobraUsbSet(cmd *cobra.Command, args []string) {
//Try to set the change config
//ToDo: Adopt parsing of Error Message to other gRPC calls
err = ClientSetGadgetSettings(StrRemoteHost, StrRemotePort, *gs)
if err != nil {
//ToDo: Adopt parsing of Error Message to other gRPC calls
log.Printf("Error setting new gadget settings: %v\n", status.Convert(err).Message())
return
}

View File

@ -6,3 +6,6 @@ export PATH=$PATH:/usr/local/go/bin # put into ~/.profile
echo export PATH=$PATH:/usr/local/go/bin >> ~/.profile
sudo bash -c 'echo export PATH=\$PATH:/usr/local/go/bin >> ~/.profile'
go get google.golang.org/grpc
go get -u github.com/improbable-eng/grpc-web/go/grpcweb
go get -u github.com/gorilla/websocket

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,12 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/improbable-eng/grpc-web/go/grpcweb"
"net/http"
"strings"
"path"
"time"
)
type server struct {}
@ -108,3 +114,101 @@ func StartRpcServer(host string, port string) {
log.Fatalf("Failed to serve: %v", err)
}
}
func folderReader(fn http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
if strings.HasSuffix(req.URL.Path, "/") {
// Use contents of index.html for directory, if present.
req.URL.Path = path.Join(req.URL.Path, "index.html")
}
fn.ServeHTTP(w, req)
}
}
func StartRpcWebServer(host string, port string) {
//Create gRPC Server
s := grpc.NewServer()
pb.RegisterP4WNP1Server(s, &server{})
//grpc_web_srv := grpcweb.WrapServer(s, grpcweb.WithWebsockets(true)) //Wrap server to improbable grpc-web with websockets
grpc_web_srv := grpcweb.WrapServer(s) //Wrap server to improbable grpc-web with websockets
/*
http_handler := func(resp http.ResponseWriter, req *http.Request) {
if req.ProtoMajor == 2 && strings.Contains(req.Header.Get("Content-Type"), "application/grpc") ||
websocket.IsWebSocketUpgrade(req) {
grpc_web_srv.ServeHTTP(resp, req)
} else {
//No gRPC request
folderReader(http.FileServer(http.Dir("/home/pi/P4wnP1_go"))).ServeHTTP(resp, req)
}
}
*/
http_handler := func(resp http.ResponseWriter, req *http.Request) {
grpc_web_srv.ServeHTTP(resp, req)
}
listen_address := host + ":" + port
http_srv := &http.Server{
Addr: listen_address,
Handler: http.HandlerFunc(http_handler),
//ReadHeaderTimeout: 5*time.Second,
//IdleTimeout: 120*time.Second,
}
//Open TCP listener
log.Printf("P4wnP1 gRPC-web server listening on " + listen_address)
log.Fatal(http_srv.ListenAndServe())
}
func StartRpcServerAndWeb(host string, port string) {
listen_address := host + ":" + port
webserver_path := "/home/pi/P4wnP1_go/www" //ToDo: Change this to an absolute path which could be used after installation
//Create gRPC Server
s := grpc.NewServer()
pb.RegisterP4WNP1Server(s, &server{})
//Wrap the server into a gRPC-web server
grpc_web_srv := grpcweb.WrapServer(s) //Wrap server to improbable grpc-web with websockets
//define a handler for a HTTP web server using the gRPC-web proxy
http_gRPC_web_handler := func(resp http.ResponseWriter, req *http.Request) {
if strings.Contains(req.Header.Get("Content-Type"), "application/grpc") || req.Method == "OPTIONS" {
fmt.Printf("gRPC-web req:\n %v\n", req)
grpc_web_srv.ServeHTTP(resp, req) // if content type indicates grpc or REQUEST METHOD IS OPTIONS (pre-flight) serve gRPC-web
} else {
fmt.Printf("legacy web req:\n %v\n", req)
http.FileServer(http.Dir((webserver_path))).ServeHTTP(resp, req)
}
}
//Open TCP listener
log.Printf("P4wnP1 gRPC server listening on " + listen_address)
lis, err := net.Listen("tcp", listen_address)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
// run gRPC server in go routine
go func() {
if err := s.Serve(lis); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}()
//Setup our HTTP server
http_srv := &http.Server{
Addr: host + ":80", //listen on port 80 with webservice
Handler: http.HandlerFunc(http_gRPC_web_handler),
ReadHeaderTimeout: 5*time.Second,
IdleTimeout: 120*time.Second,
}
log.Printf("P4wnP1 gRPC-web server listening on " + http_srv.Addr)
err_http := http_srv.ListenAndServe()
if err_http != nil {
log.Fatal(err)
}
}

4
web_client/build.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
# dependencies for the web app
gopherjs build -o ../www/webapp.js main.go

4
web_client/deps.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
# dependencies for the web app
go get -u honnef.co/go/js/dom

8
web_client/index.html Normal file
View File

@ -0,0 +1,8 @@
<html>
<head>
<title>gRPC test</title>
</head>
<body>
<script src="main.js"></script>
</body>
</html>

9
web_client/install.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
# Install gopherjs-gRPC plugin by Johan Brandhorst
# go and protoc have to be installed already
# $GOPATH/bin has to be in path
go get -u github.com/gopherjs/gopherjs
go get -u github.com/johanbrandhorst/protobuf/protoc-gen-gopherjs

42
web_client/main.go Normal file
View File

@ -0,0 +1,42 @@
package main
import (
"context"
"fmt"
"strings"
"time"
pb "../proto/gopherjs"
dom "honnef.co/go/js/dom"
)
var (
document = dom.GetWindow().Document().(dom.HTMLDocument)
serverAddr = "http://raspberrypi.local"
)
func main() {
fmt.Println("Hello")
client := pb.NewP4WNP1Client(
"http://raspberrypi.local:80",
)
fmt.Printf("Address %v\n", strings.TrimSuffix(document.BaseURI(), "/"))
fmt.Printf("Client %v\n", client)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
gs, err := client.GetDeployedGadgetSetting(ctx, &pb.Empty{})
if err == nil {
str:=fmt.Sprintf("Gs: %v\n", gs)
fmt.Println(str)
div_cont:= dom.GetWindow().Document().GetElementByID("content").(*dom.HTMLDivElement)
new_div := dom.GetWindow().Document().CreateElement("div").(*dom.HTMLDivElement)
new_div.SetTextContent("Result of GetDeployedGadgetSetting gRPC-web call: " + str)
div_cont.AppendChild(new_div)
} else {
fmt.Printf("Error rpc call: %v\n", err)
}
}

2
www/README.md Normal file
View File

@ -0,0 +1,2 @@
The only file in this directory which isn't auto-generated is index.html.

11
www/index.html Normal file
View File

@ -0,0 +1,11 @@
<html>
<head><title>Hello</title></head>
<body>
<script src="webapp.js"></script>
<h1>Testpage for P4wnP1 service</h1>
<p>See Javascript console for details, entry script is webapp.js (generated by gopherjs)</p>
<div id="content"></div>
</body>
</html>

30006
www/webapp.js Normal file

File diff suppressed because one or more lines are too long

1
www/webapp.js.map Normal file

File diff suppressed because one or more lines are too long