rest.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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("/api/specs/", specsHandler)
  44. mware := middleware.Redoc(middleware.RedocOpts{
  45. BasePath: "/api/docs/",
  46. SpecURL: "/api/specs/user.swagger.json",
  47. Path: "user",
  48. }, gmux)
  49. mware = middleware.Redoc(middleware.RedocOpts{
  50. BasePath: "/api/docs/",
  51. SpecURL: "/api/specs/vpn.swagger.json",
  52. Path: "vpn",
  53. }, mware)
  54. mware = middleware.Redoc(middleware.RedocOpts{
  55. BasePath: "/api/docs/",
  56. SpecURL: "/api/specs/network.swagger.json",
  57. Path: "network",
  58. }, mware)
  59. mware = middleware.Redoc(middleware.RedocOpts{
  60. BasePath: "/api/docs/",
  61. SpecURL: "/api/specs/auth.swagger.json",
  62. Path: "auth",
  63. }, mware)
  64. mux.Handle("/api/", mware)
  65. mux.HandleFunc("/", webuiHandler)
  66. return allowCORS(mux), cancel, nil
  67. }
  68. func specsHandler(w http.ResponseWriter, r *http.Request) {
  69. w.Header().Set("Content-Type", "application/json")
  70. switch r.URL.Path {
  71. case "/api/specs/user.swagger.json":
  72. userData, err := bindata.Asset("template/user.swagger.json")
  73. if err != nil {
  74. logrus.Warn(err)
  75. }
  76. w.Write(userData)
  77. case "/api/specs/network.swagger.json":
  78. networkData, err := bindata.Asset("template/network.swagger.json")
  79. if err != nil {
  80. logrus.Warn(err)
  81. }
  82. w.Write(networkData)
  83. case "/api/specs/vpn.swagger.json":
  84. vpnData, err := bindata.Asset("template/vpn.swagger.json")
  85. if err != nil {
  86. logrus.Warn(err)
  87. }
  88. w.Write(vpnData)
  89. case "/api/specs/auth.swagger.json":
  90. vpnData, err := bindata.Asset("template/auth.swagger.json")
  91. if err != nil {
  92. logrus.Warn(err)
  93. }
  94. w.Write(vpnData)
  95. }
  96. }
  97. func webuiHandler(w http.ResponseWriter, r *http.Request) {
  98. switch r.URL.Path {
  99. case "/bundle.js":
  100. userData, err := bindata.Asset("template/bundle.js")
  101. if err != nil {
  102. logrus.Warn(err)
  103. }
  104. w.Header().Set("Content-Type", "application/javascript")
  105. w.Write(userData)
  106. case "/js/mui.min.js":
  107. userData, err := bindata.Asset("template/mui.min.js")
  108. if err != nil {
  109. logrus.Warn(err)
  110. }
  111. w.Header().Set("Content-Type", "application/javascript")
  112. w.Write(userData)
  113. case "/css/bootstrap.min.css":
  114. userData, err := bindata.Asset("template/bootstrap.min.css")
  115. if err != nil {
  116. logrus.Warn(err)
  117. }
  118. w.Header().Set("Content-Type", "text/css")
  119. w.Write(userData)
  120. case "/css/mui.min.css":
  121. userData, err := bindata.Asset("template/mui.min.css")
  122. if err != nil {
  123. logrus.Warn(err)
  124. }
  125. w.Header().Set("Content-Type", "text/css")
  126. w.Write(userData)
  127. case "/fonts/glyphicons-halflings-regular.woff":
  128. userData, err := bindata.Asset("template/glyphicons-halflings-regular.woff")
  129. if err != nil {
  130. logrus.Warn(err)
  131. }
  132. w.Header().Set("Content-Type", "application/font-woff")
  133. w.Write(userData)
  134. default:
  135. networkData, err := bindata.Asset("template/index.html")
  136. if err != nil {
  137. logrus.Warn(err)
  138. }
  139. w.Write(networkData)
  140. }
  141. }
  142. func preflightHandler(w http.ResponseWriter, r *http.Request) {
  143. headers := []string{"Content-Type", "Accept", "Authorization"}
  144. w.Header().Set("Access-Control-Allow-Headers", strings.Join(headers, ","))
  145. methods := []string{"GET", "HEAD", "POST", "PUT", "DELETE"}
  146. w.Header().Set("Access-Control-Allow-Methods", strings.Join(methods, ","))
  147. w.Header().Set("Access-Control-Expose-Headers", "Access-Control-Allow-Origin")
  148. logrus.Debugf("rest: preflight request for %s", r.URL.Path)
  149. return
  150. }
  151. func allowCORS(h http.Handler) http.Handler {
  152. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  153. if origin := r.Header.Get("Origin"); origin != "" {
  154. w.Header().Set("Access-Control-Allow-Origin", origin)
  155. if r.Method == "OPTIONS" && r.Header.Get("Access-Control-Request-Method") != "" {
  156. preflightHandler(w, r)
  157. return
  158. }
  159. }
  160. h.ServeHTTP(w, r)
  161. })
  162. }