You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
3.2 KiB
128 lines
3.2 KiB
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
|
|
"git.chrishayward.xyz/x/users/proto"
|
|
"git.chrishayward.xyz/x/users/server"
|
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/reflection"
|
|
"gopkg.in/yaml.v3"
|
|
"gorm.io/driver/postgres"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
var configPath = flag.String("config", "./config/server.yaml", "--config=./config/server.yaml")
|
|
|
|
type config struct {
|
|
Port int `yaml:"port"`
|
|
Secret string `yaml:"secret"`
|
|
Gateway struct {
|
|
URL string `yaml:"url"`
|
|
Port int `yaml:"port"`
|
|
}
|
|
Database struct {
|
|
Type string `yaml:"type"`
|
|
File string `yaml:"file"`
|
|
Host string `yaml:"host"`
|
|
Port int `yaml:"port"`
|
|
Name string `yaml:"name"`
|
|
User string `yaml:"user"`
|
|
Password string `yaml:"password"`
|
|
} `yaml:"database"`
|
|
}
|
|
|
|
func main() {
|
|
// Create the context.
|
|
ctx := context.Background()
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
defer cancel()
|
|
|
|
// Parse the application flags.
|
|
flag.Parse()
|
|
|
|
// Read the config file.
|
|
config := &config{}
|
|
file, err := os.Open(*configPath)
|
|
if err != nil {
|
|
log.Fatalf("Failed to open config file: %v", err)
|
|
}
|
|
defer file.Close()
|
|
if err := yaml.NewDecoder(file).Decode(&config); err != nil {
|
|
log.Fatalf("Failed to read config file: %v", err)
|
|
}
|
|
|
|
// Create the server network listener.
|
|
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", config.Port))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Initialize the database.
|
|
var db *gorm.DB
|
|
switch config.Database.Type {
|
|
case "postgres":
|
|
db, _ = gorm.Open(postgres.Open(fmt.Sprintf(
|
|
"host=%s user=%s password=%s dbname=%s port=%d sslmode=disable",
|
|
config.Database.Host,
|
|
config.Database.User,
|
|
config.Database.Password,
|
|
config.Database.Name,
|
|
config.Database.Port)))
|
|
case "sqlite":
|
|
fallthrough
|
|
default:
|
|
db, _ = gorm.Open(sqlite.Open(config.Database.File), &gorm.Config{})
|
|
}
|
|
|
|
// Create the server.
|
|
grpcServer := grpc.NewServer()
|
|
proto.RegisterUsersServer(grpcServer, server.NewUsersServer(config.Secret, db))
|
|
reflection.Register(grpcServer)
|
|
go grpcServer.Serve(lis)
|
|
|
|
// Create the gateway client connection.
|
|
conn, err := grpc.Dial(fmt.Sprintf("localhost:%d", config.Port), grpc.WithInsecure())
|
|
if err != nil {
|
|
log.Fatalf("Failed to create client connection: %v", err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
// Create the gRPC gateway.
|
|
rmux := runtime.NewServeMux()
|
|
client := proto.NewUsersClient(conn)
|
|
err = proto.RegisterUsersHandlerClient(ctx, rmux, client)
|
|
if err != nil {
|
|
log.Fatalf("Failed to register client handler: %v", err)
|
|
}
|
|
|
|
// Create a standard HTTP router.
|
|
mux := http.NewServeMux()
|
|
|
|
// Mount the gRPC gateway.
|
|
mux.Handle("/", rmux)
|
|
|
|
// Create the gRPC OpenAPI UI.
|
|
mux.HandleFunc("/swagger-ui/swagger.json", func(w http.ResponseWriter, r *http.Request) {
|
|
http.ServeFile(w, r, "./proto/users.swagger.json")
|
|
})
|
|
mux.Handle("/swagger-ui/",
|
|
http.StripPrefix("/swagger-ui/",
|
|
http.FileServer(http.Dir("./modules/swagger-ui/dist"))))
|
|
|
|
// Start listening for requests.
|
|
log.Println(fmt.Sprintf("Listening on:\n=>\tgRPC[::]:%d\n=>\tHTTP[::]:%d",
|
|
config.Port, config.Gateway.Port))
|
|
err = http.ListenAndServe(fmt.Sprintf(":%d", config.Gateway.Port), mux)
|
|
if err != nil {
|
|
log.Fatalf("Failed to listen: %v", err)
|
|
}
|
|
}
|