package main import ( "context" "embed" "io/fs" "log" "net" "net/http" "pinned_message/internal/app" "pinned_message/internal/config" "pinned_message/internal/modules/data_parser" "pinned_message/internal/modules/date_parser" "pinned_message/internal/services" "pinned_message/internal/services/schedule_parser" "pinned_message/internal/services/schedule_storage" proto "pinned_message/proto" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) const ( tcpPort = ":8200" gwPort = ":8210" clientPort = ":8220" ) //go:embed static/user/* var userFS embed.FS func main() { // Create a listener on TCP port lis, err := net.Listen("tcp", tcpPort) if err != nil { log.Fatalln("Failed to listen:", err) } // Create a gRPC server object s := grpc.NewServer() ctx := context.Background() scheduleStorage := schedule_storage.NewScheduleStorage(config.GetScheduleFilepath()) scheduleParser := schedule_parser.NewScheduleParser( data_parser.NewGoogleTableScheduleParser(), date_parser.NewDateParser(), scheduleStorage, ) go func() { scheduleParser.Run(ctx) }() // Attach the Greeter service to the server proto.RegisterPinnedMessageServer( s, app.NewServer( services.NewServices( scheduleStorage, ), ), ) // Serve gRPC server log.Println("Serving gRPC on 0.0.0.0" + tcpPort) go func() { log.Fatalln(s.Serve(lis)) }() // Create a client connection to the gRPC server we just started // This is where the gRPC-Gateway proxies the requests conn, err := grpc.NewClient( "0.0.0.0"+tcpPort, grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { log.Fatalln("Failed to dial server:", err) } gwmux := runtime.NewServeMux() // Register Greeter err = proto.RegisterPinnedMessageHandler(context.Background(), gwmux, conn) if err != nil { log.Fatalln("Failed to register gateway:", err) } gwServer := &http.Server{ Addr: gwPort, Handler: cors(gwmux), } // Serve gRPC-Gateway server log.Println("Serving gRPC-Gateway on http://0.0.0.0" + gwPort) go func() { log.Fatalln(gwServer.ListenAndServe()) }() muxUser := http.NewServeMux() subUserFS, err := fs.Sub(userFS, "static/user") if err != nil { log.Fatalln(err) } fileServerUser := http.FileServer(http.FS(subUserFS)) muxUser.Handle("/", fileServerUser) // Serve admin web server log.Println("Serving user web on http://0.0.0.0" + clientPort) log.Fatalln(http.ListenAndServe(clientPort, muxUser)) } func cors(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE") w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization, ResponseType, X-Id, X-Password") if r.Method == "OPTIONS" { return } h.ServeHTTP(w, r) }) }