rest.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package api
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strings"
  6. "github.com/Sirupsen/logrus"
  7. "github.com/asaskevich/govalidator"
  8. "github.com/cad/ovpm/api/pb"
  9. "github.com/cad/ovpm/bindata"
  10. "github.com/go-openapi/runtime/middleware"
  11. "github.com/grpc-ecosystem/grpc-gateway/runtime"
  12. "golang.org/x/net/context"
  13. "google.golang.org/grpc"
  14. )
  15. // NewRESTServer returns a new REST server.
  16. func NewRESTServer(grpcPort string) (http.Handler, context.CancelFunc, error) {
  17. mux := http.NewServeMux()
  18. ctx := context.Background()
  19. ctx, cancel := context.WithCancel(ctx)
  20. if !govalidator.IsNumeric(grpcPort) {
  21. return nil, cancel, fmt.Errorf("grpcPort should be numeric")
  22. }
  23. endPoint := fmt.Sprintf("localhost:%s", grpcPort)
  24. ctx = NewOriginTypeContext(ctx, OriginTypeREST)
  25. gmux := runtime.NewServeMux(runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true}))
  26. opts := []grpc.DialOption{grpc.WithInsecure()}
  27. err := pb.RegisterVPNServiceHandlerFromEndpoint(ctx, gmux, endPoint, opts)
  28. if err != nil {
  29. return nil, cancel, err
  30. }
  31. err = pb.RegisterUserServiceHandlerFromEndpoint(ctx, gmux, endPoint, opts)
  32. if err != nil {
  33. return nil, cancel, err
  34. }
  35. err = pb.RegisterNetworkServiceHandlerFromEndpoint(ctx, gmux, endPoint, opts)
  36. if err != nil {
  37. return nil, cancel, err
  38. }
  39. err = pb.RegisterAuthServiceHandlerFromEndpoint(ctx, gmux, endPoint, opts)
  40. if err != nil {
  41. return nil, cancel, err
  42. }
  43. mux.HandleFunc("/specs/", specsHandler)
  44. mware := middleware.Redoc(middleware.RedocOpts{
  45. BasePath: "/docs/",
  46. SpecURL: "/specs/user.swagger.json",
  47. Path: "user",
  48. }, gmux)
  49. mware = middleware.Redoc(middleware.RedocOpts{
  50. BasePath: "/docs/",
  51. SpecURL: "/specs/vpn.swagger.json",
  52. Path: "vpn",
  53. }, mware)
  54. mware = middleware.Redoc(middleware.RedocOpts{
  55. BasePath: "/docs/",
  56. SpecURL: "/specs/network.swagger.json",
  57. Path: "network",
  58. }, mware)
  59. mware = middleware.Redoc(middleware.RedocOpts{
  60. BasePath: "/docs/",
  61. SpecURL: "/specs/auth.swagger.json",
  62. Path: "auth",
  63. }, mware)
  64. mux.Handle("/", mware)
  65. return allowCORS(mux), cancel, nil
  66. }
  67. func specsHandler(w http.ResponseWriter, r *http.Request) {
  68. w.Header().Set("Content-Type", "application/json")
  69. switch r.URL.Path {
  70. case "/specs/user.swagger.json":
  71. userData, err := bindata.Asset("template/user.swagger.json")
  72. if err != nil {
  73. logrus.Warn(err)
  74. }
  75. w.Write(userData)
  76. case "/specs/network.swagger.json":
  77. networkData, err := bindata.Asset("template/network.swagger.json")
  78. if err != nil {
  79. logrus.Warn(err)
  80. }
  81. w.Write(networkData)
  82. case "/specs/vpn.swagger.json":
  83. vpnData, err := bindata.Asset("template/vpn.swagger.json")
  84. if err != nil {
  85. logrus.Warn(err)
  86. }
  87. w.Write(vpnData)
  88. case "/specs/auth.swagger.json":
  89. vpnData, err := bindata.Asset("template/auth.swagger.json")
  90. if err != nil {
  91. logrus.Warn(err)
  92. }
  93. w.Write(vpnData)
  94. }
  95. }
  96. func preflightHandler(w http.ResponseWriter, r *http.Request) {
  97. headers := []string{"Content-Type", "Accept", "Authorization"}
  98. w.Header().Set("Access-Control-Allow-Headers", strings.Join(headers, ","))
  99. methods := []string{"GET", "HEAD", "POST", "PUT", "DELETE"}
  100. w.Header().Set("Access-Control-Allow-Methods", strings.Join(methods, ","))
  101. logrus.Debugf("rest: preflight request for %s", r.URL.Path)
  102. return
  103. }
  104. func allowCORS(h http.Handler) http.Handler {
  105. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  106. if origin := r.Header.Get("Origin"); origin != "" {
  107. w.Header().Set("Access-Control-Allow-Origin", origin)
  108. if r.Method == "OPTIONS" && r.Header.Get("Access-Control-Request-Method") != "" {
  109. preflightHandler(w, r)
  110. return
  111. }
  112. }
  113. h.ServeHTTP(w, r)
  114. })
  115. }