generated from VLADIMIR/template
197 lines
5.0 KiB
Go
197 lines
5.0 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"embed"
|
|
"evening_detective/internal/app"
|
|
"evening_detective/internal/config"
|
|
"evening_detective/internal/modules/cleaner"
|
|
"evening_detective/internal/modules/formatter"
|
|
"evening_detective/internal/modules/password"
|
|
"evening_detective/internal/services"
|
|
"evening_detective/internal/services/db"
|
|
"evening_detective/internal/services/link"
|
|
"evening_detective/internal/services/pdf"
|
|
"evening_detective/internal/services/story_service"
|
|
"evening_detective/internal/services/story_storage"
|
|
proto "evening_detective/proto"
|
|
"io/fs"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
"google.golang.org/grpc/metadata"
|
|
)
|
|
|
|
//go:embed static/user/*
|
|
var userFS embed.FS
|
|
|
|
//go:embed static/admin/*
|
|
var adminFS embed.FS
|
|
|
|
func main() {
|
|
// Create a listener on TCP port
|
|
lis, err := net.Listen("tcp", ":8080")
|
|
if err != nil {
|
|
log.Fatalln("Failed to listen:", err)
|
|
}
|
|
|
|
// Create a gRPC server object
|
|
s := grpc.NewServer()
|
|
// Attach the Greeter service to the server
|
|
dbFilepath := config.GetDBFilepath()
|
|
|
|
dbService, err := db.NewDBService(dbFilepath)
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
clientHost := config.GetHost()
|
|
fileHost := config.GetFileHost()
|
|
|
|
cleaner := cleaner.NewCleaner()
|
|
|
|
formatter := formatter.NewFormatter()
|
|
|
|
storyFilepath := config.GetStoryFilepath()
|
|
|
|
storyStorage := story_storage.NewFileStoryStorage(storyFilepath)
|
|
|
|
storyService, err := story_service.NewStoryService(
|
|
cleaner,
|
|
formatter,
|
|
storyStorage,
|
|
link.NewLinkService(fileHost),
|
|
)
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
linkService := link.NewLinkService(clientHost)
|
|
|
|
passwordGenerator := password.NewPasswordGenerator()
|
|
|
|
pdfGenerator := pdf.NewPDFGenerator()
|
|
|
|
proto.RegisterEveningDetectiveServer(
|
|
s,
|
|
app.NewServer(
|
|
services.NewServices(
|
|
dbService,
|
|
storyService,
|
|
linkService,
|
|
passwordGenerator,
|
|
pdfGenerator,
|
|
),
|
|
),
|
|
)
|
|
// Serve gRPC server
|
|
log.Println("Serving gRPC on 0.0.0.0:8080")
|
|
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:8080",
|
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
|
)
|
|
if err != nil {
|
|
log.Fatalln("Failed to dial server:", err)
|
|
}
|
|
|
|
gwmux := runtime.NewServeMux(
|
|
runtime.WithMetadata(func(ctx context.Context, request *http.Request) metadata.MD {
|
|
teamId := request.Header.Get("X-Id")
|
|
return metadata.Pairs("team-id", teamId)
|
|
}),
|
|
runtime.WithMetadata(func(ctx context.Context, request *http.Request) metadata.MD {
|
|
password := request.Header.Get("X-Password")
|
|
return metadata.Pairs("password", password)
|
|
}),
|
|
)
|
|
// Register Greeter
|
|
err = proto.RegisterEveningDetectiveHandler(context.Background(), gwmux, conn)
|
|
if err != nil {
|
|
log.Fatalln("Failed to register gateway:", err)
|
|
}
|
|
|
|
gwServer := &http.Server{
|
|
Addr: ":8090",
|
|
Handler: cors(gwmux),
|
|
}
|
|
|
|
// Serve gRPC-Gateway server
|
|
log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090")
|
|
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 user web server
|
|
log.Println("Serving user web on http://0.0.0.0" + config.ClientPort)
|
|
go func() {
|
|
log.Fatalln(http.ListenAndServe(config.ClientPort, muxUser))
|
|
}()
|
|
|
|
go func() {
|
|
dir := "./data/story/images"
|
|
// Создаем файловый сервер
|
|
fs := http.FileServer(http.Dir(dir))
|
|
|
|
// Добавляем middleware для логирования
|
|
http.Handle("/", loggingMiddleware(fs))
|
|
|
|
log.Println("Файловый сервер запущен на http://localhost:8120")
|
|
log.Println("Обслуживается директория: " + dir)
|
|
log.Fatal(http.ListenAndServe(":8120", nil))
|
|
}()
|
|
|
|
muxAdmin := http.NewServeMux()
|
|
subAdminFS, err := fs.Sub(adminFS, "static/admin")
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
fileServerAdmin := http.FileServer(http.FS(subAdminFS))
|
|
muxAdmin.Handle("/", fileServerAdmin)
|
|
|
|
// Serve admin web server
|
|
log.Println("Serving admin web on http://0.0.0.0:8110")
|
|
log.Fatalln(http.ListenAndServe(":8110", muxAdmin))
|
|
}
|
|
|
|
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)
|
|
})
|
|
}
|
|
|
|
func loggingMiddleware(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
start := time.Now()
|
|
|
|
// Логируем запрос
|
|
log.Printf("[%s] %s %s", r.Method, r.URL.Path, time.Since(start))
|
|
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|