package utility import ( "crawler/config" "encoding/json" "fmt" "github.com/gin-gonic/gin" "log" "math/rand" "net" "net/http" "os" "regexp" "strings" "time" ) // 패키지 호출 시 실행 func SetEnviron() { // 변수화 대상 설정 파일 var configFiles = [...]string{ config.ENV_PATH, config.CONFIG_PATH_DATABASE, config.CONFIG_PATH_MOVIE, config.CONFIG_PATH_G2A, } // json 설정 파일을 읽어들인 후 변수화 for _, file := range configFiles { SetValueFromJsonFile(file) } // 현재 개발환경 변수 확인 (local, dev) var DEVELOPER_ENV = DeveloperEnv() if DEVELOPER_ENV == "" { DEVELOPER_ENV = config.Env.DeveloperEnv } if os.Setenv(config.EnvKey, DEVELOPER_ENV) == nil { config.Env.DeveloperEnv = DEVELOPER_ENV } } // json 파일에서 값 추출 후 변수화 func SetValueFromJsonFile(filePath string) { file, err := os.Open(filePath) defer func() { err := file.Close() if err != nil { log.Fatalln(err) } }() Check(err, nil) decoder := json.NewDecoder(file) switch filePath { case config.ENV_PATH: err = decoder.Decode(&config.Env) case config.CONFIG_PATH_DATABASE: err = decoder.Decode(&config.DB) case config.CONFIG_PATH_MOVIE: err = decoder.Decode(&config.Movie) case config.CONFIG_PATH_G2A: err = decoder.Decode(&config.G2A) } Check(err, nil) } // Gin 디버그 모드 사용할 것인가 여부 func SetDebug() { if config.Env.IsDebug { gin.SetMode(gin.DebugMode) } else { gin.SetMode(gin.ReleaseMode) } } // 오류 확인 func Check(err error, path interface{}) { if err != nil { if path == nil || path == "" { path = "./log/error.txt" } logFile, err := os.OpenFile(path.(string), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { panic(err) } defer logFile.Close() logger := log.New(logFile, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile) logger.Printf("%s\n", err.Error()) } } // 설정된 개발 환경변수 조회 func DeveloperEnv() string { return strings.ToLower(os.Getenv(config.EnvKey)) // 소문자로 변환 } // 시작시간으로 부터 소요시간(초) func GetDurationInMillseconds(start time.Time) float64 { end := time.Now() duration := end.Sub(start) milliseconds := float64(duration) / float64(time.Millisecond) rounded := float64(int(milliseconds*100+.5)) / 100 return rounded } func IpAddrFromRemoteAddr(s string) string { idx := strings.LastIndex(s, ":") if idx == -1 { return s } return s[:idx] } // 현재 요청 IP func GetClientIP(c *gin.Context) string { // first check the X-Forwarded-For header requester := c.Request.Header.Get("X-Forwarded-For") // if empty, check the Real-IP header if len(requester) == 0 { requester = c.Request.Header.Get("X-Real-IP") } // if the requester is still empty, use the hard-coded address from the socket if len(requester) == 0 { requester = c.Request.RemoteAddr } // if requester is a comma delimited list, take the first one // (this happens when proxied via elastic load balancer then again through nginx) if strings.Contains(requester, ",") { requester = strings.Split(requester, ",")[0] } return requester } // 현재 서버 IP func GetLocalIP() string { addrs, err := net.InterfaceAddrs() if err != nil { return "" } for _, address := range addrs { // check the address type and if it is not a loopback the display it if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { if ipnet.IP.To4() != nil { return ipnet.IP.String() } } } return "" } func RequestGetRemoteAddress(r *http.Request) string { hdr := r.Header hdrRealIP := hdr.Get("X-Real-Ip") hdrForwardedFor := hdr.Get("X-Forwarded-For") if hdrRealIP == "" && hdrForwardedFor == "" { return IpAddrFromRemoteAddr(r.RemoteAddr) } if hdrForwardedFor != "" { // X-Forwarded-For is potentially a list of addresses separated with "," parts := strings.Split(hdrForwardedFor, ",") for i, p := range parts { parts[i] = strings.TrimSpace(p) } // TODO: should return first non-local address return parts[0] } return hdrRealIP } // 사용자 useragent 조회 func UserAgent(w http.ResponseWriter, r *http.Request) { ua := r.UserAgent() //<---- simpler and faster! fmt.Printf("user agent is: %s \n", ua) w.Write([]byte("user agent is " + ua)) } // 데이터 단위 변환 func ByteSize(bytes uint64) string { unit := "" value := float32(bytes) switch { case bytes >= config.TERABYTE: unit = "T" value = value / config.TERABYTE case bytes >= config.GIGABYTE: unit = "G" value = value / config.GIGABYTE case bytes >= config.MEGABYTE: unit = "M" value = value / config.MEGABYTE case bytes >= config.KILOBYTE: unit = "K" value = value / config.KILOBYTE case bytes >= config.BYTE: unit = "B" case bytes == 0: return "0" } stringValue := fmt.Sprintf("%.1f", value) stringValue = strings.TrimSuffix(stringValue, ".0") return fmt.Sprintf("%s%s", stringValue, unit) } // inArray func Find(slice []string, val string) (int, bool) { for i, item := range slice { if item == val { return i, true } } return -1, false } const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" func RandomString() string { b := make([]byte, rand.Intn(10)+10) for i := range b { b[i] = letterBytes[rand.Intn(len(letterBytes))] } return string(b) } // 특수문자 제거 func RemoveSpecialChar(s string) string { return strings.TrimSpace(regexp.MustCompile(`[\{\}\[\]\/?.,;:|\)*~!^\-_+<>@\#$%&\\\=\(\'\"\n\r]+`).ReplaceAllString(s, "")) }