Browse Source

grpc整理

shao 1 week ago
parent
commit
e61b28d64e

+ 22 - 0
api/v1/dicom.go

@@ -0,0 +1,22 @@
+package v1
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/spf13/cast"
+)
+
+import (
+	"auth-server/common"
+	"auth-server/service"
+)
+
+func GenerateUniqueIdentifier(c *gin.Context) {
+	flag := c.Query("flag")
+	number := cast.ToInt32(c.Query("number"))
+	res, err := service.DcmtkService.GenerateUniqueIdentifier(common.GC2GM(c), flag, number)
+	if err != nil {
+		common.HttpErr(c, err)
+		return
+	}
+	common.HttpSuccess(c, res)
+}

+ 32 - 0
api/v1/protocol.go

@@ -0,0 +1,32 @@
+package v1
+
+import (
+	"github.com/gin-gonic/gin"
+)
+
+import (
+	"auth-server/common"
+	"auth-server/service"
+)
+
+func GetPatientType(c *gin.Context) {
+	res, err := service.ProtocolService.GetPatientType(common.GC2GM(c), common.IsEnabled(c))
+	if err != nil {
+		common.HttpErr(c, err)
+		return
+	}
+	common.HttpSuccess(c, res)
+}
+
+func GetBodyPart(c *gin.Context) {
+
+	res, err := service.ProtocolService.GetBodyPart(common.GC2GM(c),
+		common.GetQueryString(c, "patient_type"),
+		common.GetQueryString(c, "category"),
+		common.IsEnabled(c))
+	if err != nil {
+		common.HttpErr(c, err)
+		return
+	}
+	common.HttpSuccess(c, res)
+}

+ 6 - 0
api/v1/public.go

@@ -17,6 +17,7 @@ func SoftwareInfo(c *gin.Context) {
 	rssi := service.ResourceService.GetSoftwareInfo()
 	sssi := service.StudyService.GetSoftwareInfo()
 	pssi := service.ProtocolService.GetSoftwareInfo()
+	dssi := service.DcmtkService.GetSoftwareInfo()
 	common.HttpSuccess(c, map[string]interface{}{
 		"server": map[string]interface{}{
 			"auth-server": map[string]interface{}{
@@ -39,6 +40,11 @@ func SoftwareInfo(c *gin.Context) {
 				"build":   pssi.GetBuild(),
 				"version": pssi.GetVersion(),
 			},
+			"dcmtk-server": map[string]interface{}{
+				"desc":    dssi.GetDesc(),
+				"build":   dssi.GetBuild(),
+				"version": dssi.GetVersion(),
+			},
 		},
 		"language": common.MetadataConfig.GetLanguages(),
 	})

+ 2 - 1
cmd/httpserver/server.go

@@ -45,7 +45,7 @@ var (
 
 func init() {
 	StartCmd.Flags().StringVarP(&configFolder, "config", "c", "config/", "Start server with provided configuration folder")
-	StartCmd.Flags().StringVarP(&addr, "addr", "a", "0.0.0.0:6001", "Tcp server listening on")
+	StartCmd.Flags().StringVarP(&addr, "addr", "a", "", "Tcp server listening on")
 	StartCmd.Flags().StringVarP(&mode, "mode", "m", "debug", "server mode ; eg:debug,test,release")
 }
 
@@ -69,6 +69,7 @@ func setup() {
 	service.ResourceService.Setup()
 	service.StudyService.Setup()
 	service.ProtocolService.Setup()
+	service.DcmtkService.Setup()
 
 	slog.Info(`starting api server`, "pid", os.Getpid())
 }

+ 5 - 1
common/config.go

@@ -26,6 +26,7 @@ type server struct {
 	Resource string
 	Study    string
 	Protocol string
+	Dcmtk    string
 }
 
 type basic struct {
@@ -73,6 +74,7 @@ func (p *postgres) setup() {
 
 // metadata配置
 type metadata struct {
+	Locales   []string
 	Languages []Lang
 	Product   Product
 	Sources   []Source
@@ -186,7 +188,9 @@ func SetupConfig(path string, addr string, mode string) {
 	ServerConfig = InitServer(cfgServer)
 
 	BasicConfig.Mode = mode
-	ServerConfig.Auth = addr
+	if addr != "" {
+		ServerConfig.Auth = addr
+	}
 
 	cfgLog := viper.Sub("logger")
 	if cfgLog == nil {

+ 14 - 14
common/enum.go

@@ -34,22 +34,22 @@ func AllLanguages() []Lang {
 type Source string
 
 const (
-	SOURCE_GUI     Source = "gui"
-	SOURCE_BROWSER Source = "browser"
-	SOURCE_ANDROID Source = "android"
-	SOURCE_DEV     Source = "dev"
+	SOURCE_ELECTRON Source = "ELectron"
+	SOURCE_BROWSER  Source = "Browser"
+	SOURCE_ANDROID  Source = "Android"
+	SOURCE_DEV      Source = "Dev"
 )
 
 func (p Source) ToString() string {
 	switch p {
-	case SOURCE_GUI:
-		return "gui"
+	case SOURCE_ELECTRON:
+		return "ELectron"
 	case SOURCE_BROWSER:
-		return "browser"
+		return "Browser"
 	case SOURCE_ANDROID:
-		return "android"
+		return "Android"
 	case SOURCE_DEV:
-		return "dev"
+		return "Dev"
 	default:
 		return ""
 	}
@@ -65,22 +65,22 @@ func ValidSources(sources []Source) bool {
 }
 
 func AllSources() []Source {
-	return []Source{SOURCE_GUI, SOURCE_BROWSER, SOURCE_ANDROID, SOURCE_DEV}
+	return []Source{SOURCE_ELECTRON, SOURCE_BROWSER, SOURCE_ANDROID, SOURCE_DEV}
 }
 
 type Product string
 
 const (
-	PRODUCT_DROC Product = "droc"
-	PRODUCT_VET  Product = "vetdroc"
+	PRODUCT_DROC Product = "DROC"
+	PRODUCT_VET  Product = "VETDROC"
 )
 
 func (p Product) ToString() string {
 	switch p {
 	case PRODUCT_DROC:
-		return "droc"
+		return "DROC"
 	case PRODUCT_VET:
-		return "vetdroc"
+		return "VETDROC"
 	default:
 		return ""
 	}

+ 16 - 0
common/utils.go

@@ -75,6 +75,22 @@ func GC2GM(c *gin.Context) context.Context {
 	return grpcmd.NewOutgoingContext(context.Background(), md)
 }
 
+func GetQueryString(c *gin.Context, key string) *string {
+	if t, ok := c.GetQuery(key); ok {
+		return &t
+	}
+	return nil
+}
+
+func IsEnabled(c *gin.Context) *bool {
+	if isEnabled, ok := c.GetQuery("is_enabled"); ok {
+		if r, e := cast.ToBoolE(isEnabled); e == nil {
+			return &r
+		}
+	}
+	return nil
+}
+
 func MD5(v []byte) string {
 	h := md5.New()
 	h.Write(v)

+ 5 - 4
config/config.toml.template

@@ -7,6 +7,7 @@ auth = "0.0.0.0:6001"
 resource = "localhost:6102"
 study = "localhost:6103"
 protocol = "localhost:6104"
+dcmtk = "localhost:6199"
 
 [logger]
 logDir = "./logs/" # 日志存储目录
@@ -37,7 +38,7 @@ locales = [
 ]
 # 支持的语言,可选项:"en","zh"
 languages = ["en", "zh"]
-# 支持的产品,可选项:"droc","vetdroc"
-product = "vetdroc"
-# 支持的访问源,可选项:"gui","browser","android"
-sources = ["gui", "browser", "android"]
+# 支持的产品,可选项:"DROC","VETDROC"
+product = "DROC"
+# 支持的访问源,可选项:"Electron","Browser","Android"
+sources = ["ELectron", "Browser", "Android"]

+ 3 - 3
router/middleware.go

@@ -86,7 +86,7 @@ func CheckLanguage(c *gin.Context) {
 		}
 	}
 	if !ok {
-		c.AbortWithStatusJSON(200, common.ErrToH(common.InvalidLanguage, c.GetHeader("locale")))
+		c.AbortWithStatusJSON(200, common.ErrToH(common.InvalidLanguage, c.GetHeader("Language")))
 	} else {
 		c.Set("language", language)
 	}
@@ -102,7 +102,7 @@ func CheckSource(c *gin.Context) {
 		}
 	}
 	if !ok {
-		c.AbortWithStatusJSON(200, common.ErrToH(common.InvalidSource, c.GetHeader("locale")))
+		c.AbortWithStatusJSON(200, common.ErrToH(common.InvalidSource, c.GetHeader("Source")))
 	} else {
 		c.Set("source", source)
 	}
@@ -111,7 +111,7 @@ func CheckSource(c *gin.Context) {
 
 func CheckProduct(c *gin.Context) {
 	product := c.Request.Header.Get("Product")
-	if product != common.MetadataConfig.GetProduct().ToString() {
+	if strings.ToUpper(product) != common.MetadataConfig.GetProduct().ToString() {
 		c.AbortWithStatusJSON(200, common.ErrToH(common.InvalidProduct, product))
 	} else {
 		c.Set("product", product)

+ 9 - 0
router/router.go

@@ -30,6 +30,15 @@ func InitRouter() *gin.Engine {
 			configV1.GET("options", apiv1.GetConfigOptions)
 			configV1.POST("items", apiv1.UpdateConfigItems)
 		}
+		protocolV1 := authV1.Group("/protocol")
+		{
+			protocolV1.GET("patient_type", apiv1.GetPatientType)
+			protocolV1.GET("body_part", apiv1.GetBodyPart)
+		}
+		dicomV1 := authV1.Group("/dicom")
+		{
+			dicomV1.GET("generate/instance_uid", apiv1.GenerateUniqueIdentifier)
+		}
 	}
 	return r
 }

+ 1 - 1
rpc_idl

@@ -1 +1 @@
-Subproject commit 9dd27d243c67beca28b8dc0665ce060c6989e7e7
+Subproject commit fd1299aaac1e201fdd1a946f14143d93f04e4c14

+ 80 - 0
service/pb_dcmtk.go

@@ -0,0 +1,80 @@
+package service
+
+import (
+	"context"
+	"log/slog"
+)
+import (
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials/insecure"
+)
+
+import (
+	"auth-server/common"
+	pb "auth-server/rpc_idl/dr_dcmtk_pb"
+)
+
+var DcmtkService *Dcmtk
+
+func init() {
+	DcmtkService = new(Dcmtk)
+}
+
+type Dcmtk struct {
+	basicClient pb.BasicClient
+	dcmClient   pb.DcmClient
+}
+
+func (s *Dcmtk) Setup() {
+	conn, err := grpc.NewClient(common.ServerConfig.Dcmtk, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	if err != nil {
+		slog.Error("NewClient failed:", err)
+		panic(err)
+	}
+	slog.Info("dcmtk conn success", "conn", conn.GetState())
+
+	s.basicClient = pb.NewBasicClient(conn)
+	s.dcmClient = pb.NewDcmClient(conn)
+}
+
+func (s *Dcmtk) GetSoftwareInfo() *pb.SoftwareInfoReply {
+	slog.Info("[rpc]SoftwareInfo...")
+	r, err := s.basicClient.SoftwareInfo(context.Background(), &pb.EmptyRequest{})
+	if err != nil {
+		slog.Error("[rpc]SoftwareInfo failed:", err)
+		return &pb.SoftwareInfoReply{
+			Module:  "",
+			Desc:    "",
+			Build:   "",
+			Version: "",
+		}
+	}
+	return r
+}
+
+func (s *Dcmtk) GenerateUniqueIdentifier(ctx context.Context, flag string, number int32) (*pb.UidReply, error) {
+	slog.Info("[rpc]GenerateUniqueIdentifier...")
+	SiteUidRoot := "1.2.276.0.1000000.5"
+	uidRoot := SiteUidRoot
+	switch flag {
+	case "study":
+		uidRoot += ".1.2"
+	case "series":
+		uidRoot += ".1.3"
+	case "sop":
+		uidRoot += ".1.4"
+	default:
+		return nil, common.InvalidParam.Desc("invalid param 'flag'")
+	}
+	if number < 1 || number > 10 {
+		return nil, common.InvalidParam.Desc("number must be between 1 and 10")
+	}
+	r, err := s.dcmClient.GenerateUniqueIdentifier(ctx, &pb.UidRootRequest{
+		UidRoot: uidRoot,
+		Number:  number,
+	})
+	if err != nil {
+		slog.Error("[rpc]GenerateUniqueIdentifier failed:", err)
+	}
+	return r, err
+}

+ 28 - 1
service/pb_protocol.go

@@ -21,7 +21,8 @@ func init() {
 }
 
 type Protocol struct {
-	basicClient pb.BasicClient
+	basicClient    pb.BasicClient
+	protocolClient pb.ProtocolClient
 }
 
 func (s *Protocol) Setup() {
@@ -33,6 +34,7 @@ func (s *Protocol) Setup() {
 	slog.Info("protocol conn success", "conn", conn.GetState())
 
 	s.basicClient = pb.NewBasicClient(conn)
+	s.protocolClient = pb.NewProtocolClient(conn)
 }
 
 func (s *Protocol) GetSoftwareInfo() *pb.SoftwareInfoReply {
@@ -49,3 +51,28 @@ func (s *Protocol) GetSoftwareInfo() *pb.SoftwareInfoReply {
 	}
 	return r
 }
+
+func (s *Protocol) GetPatientType(ctx context.Context, isEnabled *bool) (*pb.PatientTypeReply, error) {
+	slog.Info("[rpc]GetPatientType...")
+	r, err := s.protocolClient.GetPatientType(ctx, &pb.PatientTypeRequest{
+		IsEnabled: isEnabled,
+	})
+	if err != nil {
+		slog.Error("[rpc]GetPatientType failed:", err)
+	}
+	slog.Info("[rpc]GetPatientType result:", "rows", len(r.PatientTypeList))
+	return r, err
+}
+
+func (s *Protocol) GetBodyPart(ctx context.Context, patientType *string, category *string, isEnabled *bool) (*pb.BodyPartReply, error) {
+	slog.Info("[rpc]GetBodyPart...")
+	r, err := s.protocolClient.GetBodyPart(ctx, &pb.BodyPartRequest{
+		PatientType: patientType,
+		Category:    category,
+		IsEnabled:   isEnabled,
+	})
+	if err != nil {
+		slog.Error("[rpc]GetPatientType failed:", err)
+	}
+	return r, err
+}