2024-12-30 20:04:26 +05:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2025-02-16 23:13:53 +05:00
|
|
|
"errors"
|
2024-12-30 20:04:26 +05:00
|
|
|
"fmt"
|
|
|
|
"git.sch9.ru/new_gate/ms-auth/config"
|
2025-02-16 23:13:53 +05:00
|
|
|
delivery "git.sch9.ru/new_gate/ms-auth/internal/users/delivery/grpc"
|
2024-12-30 20:04:26 +05:00
|
|
|
userv1gw "git.sch9.ru/new_gate/ms-auth/proto/user/v1"
|
|
|
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
|
|
|
"github.com/ilyakaznacheev/cleanenv"
|
2025-02-16 23:13:53 +05:00
|
|
|
"github.com/rs/cors"
|
2024-12-30 20:04:26 +05:00
|
|
|
"google.golang.org/grpc"
|
|
|
|
"google.golang.org/grpc/credentials/insecure"
|
2025-02-16 23:13:53 +05:00
|
|
|
"google.golang.org/grpc/metadata"
|
2024-12-30 20:04:26 +05:00
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
2025-02-16 23:13:53 +05:00
|
|
|
"time"
|
2024-12-30 20:04:26 +05:00
|
|
|
)
|
|
|
|
|
2025-02-16 23:13:53 +05:00
|
|
|
func CustomOutgoingHeaderMatcher(key string) (string, bool) {
|
|
|
|
if key == delivery.SessionHeaderName {
|
|
|
|
return "Set-Cookie", true
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Sprintf("%s%s", runtime.MetadataHeaderPrefix, key), true
|
|
|
|
}
|
|
|
|
|
|
|
|
func CustomIncomingHeaderMatcher(key string) (string, bool) {
|
|
|
|
if key == "Cookie" {
|
|
|
|
return "Cookie", true
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Sprintf("%s%s", runtime.MetadataPrefix, key), true
|
|
|
|
}
|
|
|
|
|
|
|
|
func UnaryClientInterceptor(
|
|
|
|
ctx context.Context,
|
|
|
|
method string,
|
|
|
|
req, reply interface{},
|
|
|
|
cc *grpc.ClientConn,
|
|
|
|
invoker grpc.UnaryInvoker,
|
|
|
|
opts ...grpc.CallOption,
|
|
|
|
) error {
|
|
|
|
md, ok := metadata.FromOutgoingContext(ctx)
|
|
|
|
|
|
|
|
hasCookie := ok && len(md.Get("Cookie")) > 0
|
|
|
|
|
|
|
|
if hasCookie {
|
|
|
|
cookies, err := http.ParseCookie(md.Get("Cookie")[0])
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(cookies) != 1 {
|
|
|
|
return errors.New("invalid cookie")
|
|
|
|
}
|
|
|
|
|
|
|
|
md.Set(delivery.SessionHeaderName, cookies[0].Value)
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx = metadata.NewOutgoingContext(ctx, md)
|
|
|
|
|
|
|
|
err := invoker(ctx, method, req, reply, cc, opts...)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, o := range opts {
|
|
|
|
header, ok := o.(grpc.HeaderCallOption)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
values := header.HeaderAddr.Get(delivery.SessionHeaderName)
|
|
|
|
|
|
|
|
if len(values) != 1 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
sessionId := values[0]
|
|
|
|
|
|
|
|
cookie := http.Cookie{
|
|
|
|
Name: "SESSIONID",
|
|
|
|
Value: sessionId,
|
|
|
|
Path: "/",
|
|
|
|
HttpOnly: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(sessionId) == 0 {
|
|
|
|
cookie.Expires = time.Unix(0, 0)
|
|
|
|
} else {
|
|
|
|
cookie.MaxAge = 3600
|
|
|
|
}
|
|
|
|
|
|
|
|
header.HeaderAddr.Set(delivery.SessionHeaderName, cookie.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-12-30 20:04:26 +05:00
|
|
|
func main() {
|
|
|
|
var cfg config.Config
|
|
|
|
err := cleanenv.ReadConfig(".env", &cfg)
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("error reading config: %s", err.Error()))
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
|
|
defer cancel()
|
|
|
|
|
2025-02-16 23:13:53 +05:00
|
|
|
mux := runtime.NewServeMux(runtime.WithOutgoingHeaderMatcher(CustomOutgoingHeaderMatcher), runtime.WithIncomingHeaderMatcher(CustomIncomingHeaderMatcher))
|
|
|
|
opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithChainUnaryInterceptor(UnaryClientInterceptor)}
|
2024-12-30 20:04:26 +05:00
|
|
|
err = userv1gw.RegisterUserServiceHandlerFromEndpoint(ctx, mux, cfg.Address, opts)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2025-02-16 23:13:53 +05:00
|
|
|
c := cors.New(cors.Options{
|
|
|
|
AllowedOrigins: []string{"http://*", "https://*"},
|
|
|
|
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
|
|
|
AllowedHeaders: []string{"Content-Type", "Set-Cookie", "Credentials"},
|
|
|
|
ExposedHeaders: []string{"Link"},
|
|
|
|
AllowCredentials: true,
|
|
|
|
})
|
|
|
|
|
2024-12-30 20:04:26 +05:00
|
|
|
go func() {
|
2025-02-16 23:13:53 +05:00
|
|
|
err = http.ListenAndServe(cfg.ProxyAddress, c.Handler(mux))
|
2024-12-30 20:04:26 +05:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
fmt.Println("server proxy started")
|
|
|
|
|
|
|
|
stop := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(stop, syscall.SIGTERM, syscall.SIGINT)
|
|
|
|
|
|
|
|
<-stop
|
|
|
|
return
|
|
|
|
}
|