@@ -3,7 +3,11 @@ package main
33import (
44 "errors"
55 "flag"
6+ "fmt"
7+ "math"
68 "os"
9+ "strconv"
10+ "strings"
711 "time"
812)
913
@@ -29,26 +33,79 @@ func LoadConfig() (*Config, error) {
2933 cfg .ServerReadTimeout = 120 * time .Second
3034 cfg .ServerReadHeaderTimeout = 10 * time .Second
3135 cfg .ServerWriteTimeout = 120 * time .Second
32- cfg . ServerMaxRequestSize = int64 ( 400 * 1024 * 1024 )
36+ maxFileSize := "400Mi"
3337
3438 if val , ok := os .LookupEnv ("DAEMON_ENDPOINT" ); ok {
3539 cfg .DaemonEndpoint = val
3640 }
41+ if val , ok := os .LookupEnv ("MAX_FILE_SIZE" ); ok {
42+ maxFileSize = val
43+ }
3744
3845 // Override with flags
3946 flag .StringVar (& cfg .BindAddress , "bind-address" , cfg .BindAddress , "Bind address" )
4047 flag .StringVar (& cfg .LogLevel , "log-level" , cfg .LogLevel , "Log level" )
4148 flag .StringVar (& cfg .DaemonEndpoint , "daemon-endpoint" , cfg .DaemonEndpoint , "ClamAV daemon endpoint" )
49+ flag .StringVar (& maxFileSize , "max-file-size" , maxFileSize , "Maximum file size accepted by /scan (e.g. 400Mi, 400M)" )
4250 timeout := flag .Int ("timeout" , int (cfg .Timeout .Seconds ()), "Timeout in seconds" )
4351 keepalive := flag .Int ("keepalive" , int (cfg .Keepalive .Seconds ()), "Keepalive in seconds" )
4452 flag .Parse ()
4553
4654 cfg .Timeout = time .Duration (* timeout ) * time .Second
4755 cfg .Keepalive = time .Duration (* keepalive ) * time .Second
56+ var err error
57+ cfg .ServerMaxRequestSize , err = parseByteSize (maxFileSize )
58+ if err != nil {
59+ return nil , fmt .Errorf ("invalid max file size %q: %w" , maxFileSize , err )
60+ }
4861
4962 if cfg .DaemonEndpoint == "" {
5063 return nil , errors .New ("daemon endpoint is required" )
5164 }
5265
5366 return cfg , nil
5467}
68+
69+ func parseByteSize (value string ) (int64 , error ) {
70+ normalized := strings .ToUpper (strings .TrimSpace (value ))
71+ if normalized == "" {
72+ return 0 , errors .New ("value cannot be empty" )
73+ }
74+ if strings .HasSuffix (normalized , "B" ) {
75+ normalized = strings .TrimSuffix (normalized , "B" )
76+ }
77+
78+ multiplier := int64 (1 )
79+ for _ , unit := range []struct {
80+ suffix string
81+ multiplier int64
82+ }{
83+ {suffix : "TI" , multiplier : 1024 * 1024 * 1024 * 1024 },
84+ {suffix : "GI" , multiplier : 1024 * 1024 * 1024 },
85+ {suffix : "MI" , multiplier : 1024 * 1024 },
86+ {suffix : "KI" , multiplier : 1024 },
87+ {suffix : "T" , multiplier : 1000 * 1000 * 1000 * 1000 },
88+ {suffix : "G" , multiplier : 1000 * 1000 * 1000 },
89+ {suffix : "M" , multiplier : 1000 * 1000 },
90+ {suffix : "K" , multiplier : 1000 },
91+ } {
92+ if strings .HasSuffix (normalized , unit .suffix ) {
93+ multiplier = unit .multiplier
94+ normalized = strings .TrimSuffix (normalized , unit .suffix )
95+ break
96+ }
97+ }
98+
99+ size , err := strconv .ParseInt (normalized , 10 , 64 )
100+ if err != nil {
101+ return 0 , fmt .Errorf ("invalid numeric value %q" , normalized )
102+ }
103+ if size < 0 {
104+ return 0 , errors .New ("value cannot be negative" )
105+ }
106+ if size > math .MaxInt64 / multiplier {
107+ return 0 , errors .New ("value is too large" )
108+ }
109+
110+ return size * multiplier , nil
111+ }
0 commit comments