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

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)
}
}