func (f *FallbackServer) options(w http.ResponseWriter, r *http.Request) {
	log.Println("Incoming OPTIONS for request:", r.RequestURI)
	w.Header().Add("access-control-allow-credentials", "true")
	w.Header().Add("access-control-allow-headers", "*")
	w.Header().Add("access-control-allow-methods", http.MethodPost)
	w.Header().Add("access-control-allow-origin", "*")
	w.Header().Add("access-control-max-age", "3600")
	w.WriteHeader(http.StatusOK)
}
options is a handler for the OPTIONS call that precedes CORS-enabled calls.
package server
import (
	"context"
	"log"
	"net/http"
	"strings"
	"github.com/golang/protobuf/proto"
	"github.com/gorilla/mux"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/status"
)
const fallbackPath = "/$rpc/{service:[.a-zA-Z0-9]+}/{method:[a-zA-Z]+}"
type FallbackServer struct {
	backend string
	server  http.Server
	cc      connection  
}
type connection interface {
	Invoke(ctx context.Context, method string, args, reply interface{}, opts ...grpc.CallOption) error
}
func NewServer(port, backend string) *FallbackServer {
	if !strings.HasPrefix(port, ":") {
		port = ":" + port
	}
	return &FallbackServer{
		backend: backend,
		server: http.Server{
			Addr: port,
		},
	}
}
func (f *FallbackServer) Start() {
	f.preStart()
	log.Println("Fallback server listening on port:", f.server.Addr)
	if err := f.server.ListenAndServe(); err != nil {
		log.Println("Error in fallback server while listening:", err)
	}
}
func (f *FallbackServer) StartBackground() {
	go f.Start()
}
func (f *FallbackServer) preStart() {
	var err error
	f.cc, err = f.dial()
	if err != nil {
		log.Fatal("Error dialing gRPC backend server:", err)
	}
	r := mux.NewRouter()
	r.HandleFunc(fallbackPath, f.options).
		Methods(http.MethodOptions)
	r.HandleFunc(fallbackPath, f.handler).
		Headers("Content-Type", "application/x-protobuf")
	f.server.Handler = r
}
func (f *FallbackServer) Shutdown() {
	if err := f.server.Shutdown(context.Background()); err != nil {
		log.Println("Error shutting down fallback server:", err)
	}
}
func (f *FallbackServer) handler(w http.ResponseWriter, r *http.Request) {
	log.Println("Incoming grpc-fallback request:", r.RequestURI)
	v := mux.Vars(r)
	m := buildMethod(v["service"], v["method"])
	ctx := prepareHeaders(context.Background(), r.Header)
	w.Header().Set("Access-Control-Allow-Origin", "*")
	err := f.cc.Invoke(ctx, m, r.Body, w)
	if err != nil {
		code := 500
		b := []byte(err.Error())
		if st, ok := status.FromError(err); ok {
			code = httpStatusFromCode(st.Code())
			b, _ = proto.Marshal(st.Proto())
		}
		log.Println("Error handling request:", r.RequestURI, "-", err)
		w.WriteHeader(code)
		w.Write(b)
	}
}
func (f *FallbackServer) dial() (connection, error) {
	opts := []grpc.DialOption{
		grpc.WithDefaultCallOptions(grpc.ForceCodec(fallbackCodec{})),
	}
	auth := grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, ""))
	if strings.Contains(f.backend, "localhost") || strings.Contains(f.backend, "127.0.0.1") {
		auth = grpc.WithInsecure()
	}
	opts = append(opts, auth)
	return grpc.Dial(f.backend, opts...)
}