Files
dicom-iso/internal/config/config.go
2026-06-05 08:11:44 +07:00

174 lines
3.9 KiB
Go

package config
import (
"fmt"
"os"
"time"
"gopkg.in/yaml.v3"
)
// Config is the top-level configuration structure.
type Config struct {
Server ServerConfig `yaml:"server"`
Auth AuthConfig `yaml:"auth"`
DCMTK DCMTKConfig `yaml:"dcmtk"`
PACS PACSConfig `yaml:"pacs"`
OurAE OurAEConfig `yaml:"our_ae"`
PatientAPI PatientAPIConfig `yaml:"patient_api"`
CDPublisher CDPublisherConfig `yaml:"cd_publisher"`
ISO ISOConfig `yaml:"iso"`
}
type ServerConfig struct {
Port int `yaml:"port"`
ReadTimeout time.Duration `yaml:"read_timeout"`
WriteTimeout time.Duration `yaml:"write_timeout"`
}
type AuthConfig struct {
Enabled bool `yaml:"enabled"`
APIKey string `yaml:"api_key"`
}
type DCMTKConfig struct {
Storescp string `yaml:"storescp"`
Movescu string `yaml:"movescu"`
Storescu string `yaml:"storescu"`
}
type PACSConfig struct {
AETitle string `yaml:"ae_title"`
Host string `yaml:"host"`
Port int `yaml:"port"`
}
type OurAEConfig struct {
AETitle string `yaml:"ae_title"`
BasePort int `yaml:"base_port"`
PortRange int `yaml:"port_range"`
}
type PatientAPIConfig struct {
BaseURL string `yaml:"base_url"`
Endpoint string `yaml:"endpoint"`
AuthType string `yaml:"auth_type"`
AuthHeader string `yaml:"auth_header"`
AuthToken string `yaml:"auth_token"`
Timeout time.Duration `yaml:"timeout"`
Retry int `yaml:"retry"`
RetryBackoff time.Duration `yaml:"retry_backoff"`
}
type CDPublisherConfig struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
}
type ISOConfig struct {
MicrodicomPath string `yaml:"microdicom_path"`
TempDir string `yaml:"temp_dir"`
}
// Load reads and parses the config file from the given path.
// If path is empty, it reads from the MKISO_CONFIG env var, falling back
// to ./config.yaml.
func Load(path string) (*Config, error) {
if path == "" {
path = os.Getenv("MKISO_CONFIG")
}
if path == "" {
path = "./config.yaml"
}
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read config file %q: %w", path, err)
}
var cfg Config
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("parse config file %q: %w", path, err)
}
if err := cfg.validate(); err != nil {
return nil, fmt.Errorf("validate config: %w", err)
}
return &cfg, nil
}
func (c *Config) validate() error {
if c.Server.Port == 0 {
c.Server.Port = 8080
}
if c.Server.ReadTimeout == 0 {
c.Server.ReadTimeout = 300 * time.Second
}
if c.Server.WriteTimeout == 0 {
c.Server.WriteTimeout = 600 * time.Second
}
if c.DCMTK.Storescp == "" {
return fmt.Errorf("dcmtk.storescp is required")
}
if c.DCMTK.Movescu == "" {
return fmt.Errorf("dcmtk.movescu is required")
}
if c.DCMTK.Storescu == "" {
return fmt.Errorf("dcmtk.storescu is required")
}
if c.PACS.Host == "" {
c.PACS.Host = "localhost"
}
if c.PACS.Port == 0 {
c.PACS.Port = 11112
}
if c.PACS.AETitle == "" {
c.PACS.AETitle = "ABPACS"
}
if c.OurAE.AETitle == "" {
c.OurAE.AETitle = "CDRECORD"
}
if c.OurAE.BasePort == 0 {
c.OurAE.BasePort = 10104
}
if c.OurAE.PortRange == 0 {
c.OurAE.PortRange = 100
}
if c.PatientAPI.BaseURL == "" {
c.PatientAPI.BaseURL = "http://localhost:8090"
}
if c.PatientAPI.Endpoint == "" {
c.PatientAPI.Endpoint = "/patient/by-accession"
}
if c.PatientAPI.Timeout == 0 {
c.PatientAPI.Timeout = 10 * time.Second
}
if c.PatientAPI.Retry == 0 {
c.PatientAPI.Retry = 3
}
if c.PatientAPI.RetryBackoff == 0 {
c.PatientAPI.RetryBackoff = 500 * time.Millisecond
}
if c.CDPublisher.Host == "" {
c.CDPublisher.Host = "172.16.0.120"
}
if c.CDPublisher.Port == 0 {
c.CDPublisher.Port = 104
}
if c.ISO.MicrodicomPath == "" {
c.ISO.MicrodicomPath = "/var/www/html/microdicom"
}
if c.ISO.TempDir == "" {
c.ISO.TempDir = "/tmp"
}
return nil
}