Przeglądaj źródła

更新标志解析和版本信息

增加了新的命令行标志以显示许可证、报告和选项,并改进了输出格式。同时更新了版本号到1.1.0,并添加了一些实用工具函数。
SongZihuan 3 miesięcy temu
rodzic
commit
405d0181b8

+ 1 - 1
VERSION

@@ -1 +1 @@
-v1.0.0
+v1.1.0

+ 6 - 0
resource.go

@@ -6,3 +6,9 @@ import (
 
 //go:embed VERSION
 var Version string
+
+//go:embed LICENSE
+var License string
+
+//go:embed
+var Report string

+ 3 - 15
src/flagparser/data.go

@@ -1,10 +1,5 @@
 package flagparser
 
-import (
-	"fmt"
-	"strings"
-)
-
 var HttpAddress string = ":3366"
 var HttpsAddress string = ""
 var HttpsDomain = ""
@@ -12,15 +7,8 @@ var HttpsEmail = ""
 var HttpsCertDir = "./ssl-certs"
 var HttpsAliyunKey string
 var HttpsAliyunSecret string
+var ShowOption = false
 var DryRun = false
 var Version = false
-
-func Print() {
-	fmt.Println("HttpAddress:", HttpAddress)
-	fmt.Println("HttpsAddress:", HttpsAddress)
-	fmt.Println("HttpsDomain:", HttpsDomain)
-	fmt.Println("HttpsEmail:", HttpsEmail)
-	fmt.Println("HttpsCertDir:", HttpsCertDir)
-	fmt.Println("HttpsAliyunKey:", HttpsAliyunKey)
-	fmt.Println("HttpsAliyunSecret:", strings.Repeat("*", len(HttpsAliyunSecret)))
-}
+var License = false
+var Report = false

+ 12 - 0
src/flagparser/flag.go

@@ -3,6 +3,7 @@ package flagparser
 import (
 	"flag"
 	"fmt"
+	"os"
 )
 
 func initFlag() (err error) {
@@ -14,6 +15,8 @@ func initFlag() (err error) {
 		}
 	}()
 
+	flag.CommandLine.SetOutput(os.Stdout)
+
 	flag.StringVar(&HttpAddress, "address", HttpAddress, "http server listen address")
 	flag.StringVar(&HttpAddress, "http-address", HttpAddress, "http server listen address")
 
@@ -30,6 +33,15 @@ func initFlag() (err error) {
 	flag.BoolVar(&Version, "version", Version, "show the version")
 	flag.BoolVar(&Version, "v", Version, "show the version")
 
+	flag.BoolVar(&License, "license", License, "show the license")
+	flag.BoolVar(&License, "l", License, "show the license")
+
+	flag.BoolVar(&Report, "report", Report, "show the report")
+	flag.BoolVar(&Report, "r", Report, "show the report")
+
+	flag.BoolVar(&ShowOption, "show-option", ShowOption, "show the option")
+	flag.BoolVar(&ShowOption, "s", ShowOption, "show the option")
+
 	flag.Parse()
 
 	return nil

+ 40 - 0
src/flagparser/print.go

@@ -0,0 +1,40 @@
+package flagparser
+
+import (
+	"flag"
+	"fmt"
+	resource "github.com/SongZihuan/http-demo"
+	"github.com/SongZihuan/http-demo/src/utils"
+	"strings"
+)
+
+func PrintLicense() (int, error) {
+	title := utils.FormatTextToWidth(fmt.Sprintf("License of %s:", utils.GetArgs0Name()), utils.NormalConsoleWidth)
+	license := utils.FormatTextToWidth(resource.License, utils.NormalConsoleWidth)
+	return fmt.Fprintf(flag.CommandLine.Output(), "%s\n%s\n", title, license)
+}
+
+func PrintVersion() (int, error) {
+	version := utils.FormatTextToWidth(fmt.Sprintf("Version of %s: %s", utils.GetArgs0Name(), resource.Version), utils.NormalConsoleWidth)
+	return fmt.Fprintf(flag.CommandLine.Output(), "%s\n", version)
+}
+
+func PrintReport() (int, error) {
+	// 不需要title
+	report := utils.FormatTextToWidth(resource.Report, utils.NormalConsoleWidth)
+	return fmt.Fprintf(flag.CommandLine.Output(), "%s\n", report)
+}
+
+func PrintLF() (int, error) {
+	return fmt.Fprintf(flag.CommandLine.Output(), "\n")
+}
+
+func Print() {
+	fmt.Println("HttpAddress:", HttpAddress)
+	fmt.Println("HttpsAddress:", HttpsAddress)
+	fmt.Println("HttpsDomain:", HttpsDomain)
+	fmt.Println("HttpsEmail:", HttpsEmail)
+	fmt.Println("HttpsCertDir:", HttpsCertDir)
+	fmt.Println("HttpsAliyunKey:", HttpsAliyunKey)
+	fmt.Println("HttpsAliyunSecret:", strings.Repeat("*", len(HttpsAliyunSecret)))
+}

+ 29 - 4
src/mainfunc/version1.go

@@ -3,7 +3,6 @@ package mainfunc
 import (
 	"errors"
 	"fmt"
-	resource "github.com/SongZihuan/http-demo"
 	"github.com/SongZihuan/http-demo/src/engine"
 	"github.com/SongZihuan/http-demo/src/flagparser"
 	"github.com/SongZihuan/http-demo/src/httpserver"
@@ -19,7 +18,7 @@ func MainV1() (exitcode int) {
 		}
 	}()
 
-	fmt.Printf("")
+	var hasPrint = false
 	err := flagparser.InitFlagParser()
 	if err != nil {
 		fmt.Printf("init flag fail: %s\n", err.Error())
@@ -27,12 +26,38 @@ func MainV1() (exitcode int) {
 	}
 
 	if flagparser.Version {
-		fmt.Printf("Version: %s\n", resource.Version)
+		_, _ = flagparser.PrintVersion()
+		hasPrint = true
 		return 0
 	}
 
-	if flagparser.DryRun {
+	if flagparser.License {
+		if hasPrint {
+			_, _ = flagparser.PrintLF()
+		}
+		_, _ = flagparser.PrintLicense()
+		hasPrint = true
+		return 0
+	}
+
+	if flagparser.Report {
+		if hasPrint {
+			_, _ = flagparser.PrintLF()
+		}
+		_, _ = flagparser.PrintReport()
+		hasPrint = true
+		return 0
+	}
+
+	if flagparser.DryRun || flagparser.ShowOption {
+		if hasPrint {
+			_, _ = flagparser.PrintLF()
+		}
+
 		flagparser.Print()
+	}
+
+	if flagparser.DryRun {
 		return 0
 	}
 

+ 53 - 0
src/utils/cmd.go

@@ -0,0 +1,53 @@
+package utils
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+)
+
+var _args0 = ""
+
+func init() {
+	var err error
+	if len(os.Args) > 0 {
+		_args0, err = os.Executable()
+		if err != nil {
+			_args0 = os.Args[0]
+		}
+	}
+
+	if _args0 == "" {
+		panic("args was empty")
+	}
+}
+
+func GetArgs0() string {
+	return _args0
+}
+
+func GetArgs0Name() string {
+	return filepath.Base(_args0)
+}
+
+func SayHellof(format string, args ...interface{}) {
+	var msg string
+	if len(format) == 0 && len(args) == 0 {
+		msg = fmt.Sprintf("%s: %s", GetArgs0Name(), "Normal startup, thank you.")
+	} else {
+		str := fmt.Sprintf(format, args...)
+		msg = fmt.Sprintf("%s: %s", GetArgs0Name(), str)
+	}
+	fmt.Println(FormatTextToWidth(msg, NormalConsoleWidth))
+}
+
+func SayGoodByef(format string, args ...interface{}) {
+	var msg string
+	if len(format) == 0 && len(args) == 0 {
+		msg = fmt.Sprintf("%s: %s", GetArgs0Name(), "Normal shutdown, thank you.")
+	} else {
+		str := fmt.Sprintf(format, args...)
+		msg = fmt.Sprintf("%s: %s", GetArgs0Name(), str)
+	}
+	fmt.Println(FormatTextToWidth(msg, NormalConsoleWidth))
+}

+ 20 - 0
src/utils/rand.go

@@ -0,0 +1,20 @@
+package utils
+
+import (
+	"math/rand"
+	"time"
+)
+
+var r *rand.Rand = nil
+
+func init() {
+	r = rand.New(rand.NewSource(time.Now().UnixNano()))
+}
+
+func Rand() *rand.Rand {
+	if r == nil {
+		panic("nil Rand")
+	}
+
+	return r
+}

+ 131 - 1
src/utils/string.go

@@ -1,6 +1,29 @@
 package utils
 
-import "regexp"
+import (
+	"regexp"
+	"strings"
+	"unicode"
+)
+
+const BASE_CHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+func RandStr(length int) string {
+	bytes := []byte(BASE_CHAR)
+
+	var result []byte
+	for i := 0; i < length; i++ {
+		result = append(result, bytes[Rand().Intn(len(bytes))])
+	}
+
+	return string(result)
+}
+
+func InvalidPhone(phone string) bool {
+	pattern := `^1[3-9]\d{9}$`
+	matched, _ := regexp.MatchString(pattern, phone)
+	return matched
+}
 
 func IsValidEmail(email string) bool {
 	pattern := `^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`
@@ -8,8 +31,115 @@ func IsValidEmail(email string) bool {
 	return matched
 }
 
+const NormalConsoleWidth = 80
+
+func FormatTextToWidth(text string, width int) string {
+	return FormatTextToWidthAndPrefix(text, 0, width)
+}
+
+func FormatTextToWidthAndPrefix(text string, prefixWidth int, overallWidth int) string {
+	var result strings.Builder
+
+	width := overallWidth - prefixWidth
+	if width <= 0 {
+		panic("bad width")
+	}
+
+	text = strings.ReplaceAll(text, "\r\n", "\n")
+
+	for _, line := range strings.Split(text, "\n") {
+		result.WriteString(strings.Repeat(" ", prefixWidth))
+
+		if line == "" {
+			result.WriteString("\n")
+			continue
+		}
+
+		spaceCount := CountSpaceInStringPrefix(line) % width
+		newLineLength := 0
+		if spaceCount < 80 {
+			result.WriteString(strings.Repeat(" ", spaceCount))
+			newLineLength = spaceCount
+		}
+
+		for _, word := range strings.Fields(line) {
+			if newLineLength+len(word) >= width {
+				result.WriteString("\n")
+				result.WriteString(strings.Repeat(" ", prefixWidth))
+				newLineLength = 0
+			}
+
+			// 不是第一个词时,添加空格
+			if newLineLength != 0 {
+				result.WriteString(" ")
+				newLineLength += 1
+			}
+
+			result.WriteString(word)
+			newLineLength += len(word)
+		}
+
+		if newLineLength != 0 {
+			result.WriteString("\n")
+			newLineLength = 0
+		}
+	}
+
+	return strings.TrimRight(result.String(), "\n")
+}
+
+func CountSpaceInStringPrefix(str string) int {
+	var res int
+	for _, r := range str {
+		if r == ' ' {
+			res += 1
+		} else {
+			break
+		}
+	}
+
+	return res
+}
+
+func IsValidURLPath(path string) bool {
+	if path == "" {
+		return true
+	} else if path == "/" {
+		return false
+	}
+
+	pattern := `^\/[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;%=]+$`
+	matched, _ := regexp.MatchString(pattern, path)
+	return matched
+}
+
 func IsValidDomain(domain string) bool {
 	pattern := `^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$`
 	matched, _ := regexp.MatchString(pattern, domain)
 	return matched
 }
+
+func StringToOnlyPrint(str string) string {
+	runeLst := []rune(str)
+	res := make([]rune, 0, len(runeLst))
+
+	for _, r := range runeLst {
+		if unicode.IsPrint(r) {
+			res = append(res, r)
+		}
+	}
+
+	return string(res)
+}
+
+func IsGoodQueryKey(key string) bool {
+	pattern := `^[a-zA-Z0-9\-._~]+$`
+	matched, _ := regexp.MatchString(pattern, key)
+	return matched
+}
+
+func IsValidHTTPHeaderKey(key string) bool {
+	pattern := `^[a-zA-Z0-9!#$%&'*+.^_` + "`" + `|~-]+$`
+	matched, _ := regexp.MatchString(pattern, key)
+	return matched
+}