6 changed files with 388 additions and 0 deletions
@ -0,0 +1,88 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"fmt" |
|||
"time" |
|||
|
|||
"git.realxlfd.cc/RealXLFD/golib/utils/str" |
|||
"github.com/gookit/color" |
|||
) |
|||
|
|||
type Logger struct { |
|||
Level Level |
|||
HideTime bool |
|||
} |
|||
|
|||
type Level int |
|||
|
|||
const ( |
|||
LevelSlient Level = iota - 3 |
|||
LevelError |
|||
LevelWarn |
|||
LevelInfo |
|||
LevelDebug |
|||
) |
|||
|
|||
var ( |
|||
red = color.FgRed.Render |
|||
yellow = color.FgYellow.Render |
|||
green = color.FgGreen.Render |
|||
gray = color.FgGray.Render |
|||
) |
|||
|
|||
var ( |
|||
argError = red("ERR") |
|||
argWarn = yellow("WRN") |
|||
argInfo = green("INF") |
|||
argDebug = "DBG" |
|||
) |
|||
|
|||
var ( |
|||
Timer = func() string { |
|||
return time.Now().Format(time.Kitchen) |
|||
} |
|||
) |
|||
|
|||
func (l Logger) Info(msg ...interface{}) { |
|||
if l.Level < LevelInfo { |
|||
return |
|||
} |
|||
timeStamp := "" |
|||
if !l.HideTime { |
|||
timeStamp = str.Join(Timer(), " ") |
|||
} |
|||
fmt.Println(str.Join(timeStamp, argInfo), msg) |
|||
} |
|||
|
|||
func (l Logger) Debug(msg ...interface{}) { |
|||
if l.Level < LevelDebug { |
|||
return |
|||
} |
|||
timeStamp := "" |
|||
if !l.HideTime { |
|||
timeStamp = str.Join(Timer(), " ") |
|||
} |
|||
fmt.Println(str.Join(timeStamp, argDebug), msg) |
|||
} |
|||
|
|||
func (l Logger) Warn(msg ...interface{}) { |
|||
if l.Level < LevelWarn { |
|||
return |
|||
} |
|||
timeStamp := "" |
|||
if !l.HideTime { |
|||
timeStamp = str.Join(Timer(), " ") |
|||
} |
|||
fmt.Println(str.Join(timeStamp, argWarn), msg) |
|||
} |
|||
|
|||
func (l Logger) Error(msg ...interface{}) { |
|||
if l.Level < LevelError { |
|||
return |
|||
} |
|||
timeStamp := "" |
|||
if !l.HideTime { |
|||
timeStamp = str.Join(Timer(), " ") |
|||
} |
|||
fmt.Println(str.Join(timeStamp, argError), msg) |
|||
} |
@ -0,0 +1,13 @@ |
|||
package rproxy |
|||
|
|||
import ( |
|||
"git.realxlfd.cc/RealXLFD/golib/cli/logger" |
|||
) |
|||
|
|||
var ( |
|||
l = &logger.Logger{} |
|||
) |
|||
|
|||
func SetLogLevel(level logger.Level) { |
|||
l.Level = level |
|||
} |
@ -0,0 +1,139 @@ |
|||
package rproxy |
|||
|
|||
import ( |
|||
"context" |
|||
"errors" |
|||
"fmt" |
|||
"net/http" |
|||
"net/http/httputil" |
|||
"net/url" |
|||
"time" |
|||
|
|||
"git.realxlfd.cc/RealXLFD/golib/utils/str" |
|||
) |
|||
|
|||
type Server struct { |
|||
config *config |
|||
revProxyClient *httputil.ReverseProxy |
|||
httpServer *http.Server |
|||
} |
|||
|
|||
type config struct { |
|||
Port int |
|||
TargetURL *url.URL |
|||
ProxyURL *url.URL |
|||
Handler func(r *http.Request) |
|||
} |
|||
|
|||
func CreateServer(port int, target *url.URL) *Server { |
|||
if port < 80 || port > 65535 { |
|||
panic("port out of range (80-65535)") |
|||
} |
|||
conf := &config{ |
|||
Port: port, |
|||
TargetURL: target, |
|||
ProxyURL: nil, |
|||
Handler: func(r *http.Request) {}, |
|||
} |
|||
reverseProxy := httputil.NewSingleHostReverseProxy(conf.TargetURL) |
|||
server := &Server{ |
|||
config: conf, |
|||
revProxyClient: reverseProxy, |
|||
httpServer: nil, |
|||
} |
|||
return server |
|||
} |
|||
func (s *Server) WithTransportProxy(proxy string) *Server { |
|||
if proxy == "" { |
|||
return s |
|||
} |
|||
proxyURL, err := url.Parse(proxy) |
|||
if err != nil { |
|||
panic(err) |
|||
} |
|||
s.config.ProxyURL = proxyURL |
|||
s.revProxyClient.Transport = &http.Transport{ |
|||
Proxy: http.ProxyURL(proxyURL), |
|||
} |
|||
return s |
|||
} |
|||
|
|||
func (s *Server) WithRequestHandler(f func(r *http.Request)) *Server { |
|||
s.config.Handler = f |
|||
return s |
|||
} |
|||
func (s *Server) Run() *Server { |
|||
if s.httpServer != nil { |
|||
return s |
|||
} |
|||
go func() { |
|||
err := s.runner()() |
|||
if err != nil { |
|||
logger.Error(fmt.Sprintf("server failed: %s", err.Error())) |
|||
} |
|||
}() |
|||
return s |
|||
} |
|||
func (s *Server) RunSync() error { |
|||
if s.httpServer != nil { |
|||
return errors.New("server already running") |
|||
} |
|||
exitCh := make(chan error) |
|||
go func() { |
|||
exitCh <- s.runner()() |
|||
}() |
|||
err := <-exitCh |
|||
return err |
|||
} |
|||
|
|||
func (s *Server) runner() func() error { |
|||
return func() error { |
|||
mux := http.NewServeMux() |
|||
mux.HandleFunc("/", s.requestHandler()) |
|||
httpServer := &http.Server{ |
|||
Addr: fmt.Sprintf(":%d", s.config.Port), |
|||
Handler: mux, |
|||
} |
|||
return httpServer.ListenAndServe() |
|||
} |
|||
} |
|||
|
|||
func (s *Server) IsRunning() bool { |
|||
return s.httpServer != nil |
|||
} |
|||
|
|||
func (s *Server) Stop() error { |
|||
if !s.IsRunning() { |
|||
return errors.New("server has already stopped") |
|||
} |
|||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
|||
defer cancel() |
|||
err := s.httpServer.Shutdown(ctx) |
|||
return err |
|||
} |
|||
|
|||
func (s *Server) requestHandler() func( |
|||
w http.ResponseWriter, r *http.Request, |
|||
) { |
|||
return func(w http.ResponseWriter, r *http.Request) { |
|||
var proxyInfo string |
|||
if s.config.ProxyURL != nil { |
|||
proxyInfo = fmt.Sprintf(" -> [%s]", s.config.ProxyURL.Host) |
|||
} |
|||
logger.Info( |
|||
fmt.Sprintf( |
|||
"%s -> [:%d]%s -> %s", |
|||
r.RemoteAddr, |
|||
s.config.Port, |
|||
proxyInfo, |
|||
str.Trim( |
|||
str.Join(s.config.TargetURL.Host, r.RequestURI), |
|||
20, |
|||
), |
|||
), |
|||
) |
|||
r.Host = s.config.TargetURL.Host |
|||
s.config.Handler(r) |
|||
s.revProxyClient.ServeHTTP(w, r) |
|||
} |
|||
} |
@ -0,0 +1,11 @@ |
|||
package proc |
|||
|
|||
import ( |
|||
"sync" |
|||
) |
|||
|
|||
func JustWait() { |
|||
lock := sync.Mutex{} |
|||
lock.Lock() |
|||
lock.Lock() |
|||
} |
@ -0,0 +1,57 @@ |
|||
package test |
|||
|
|||
import ( |
|||
"testing" |
|||
|
|||
"git.realxlfd.cc/RealXLFD/golib/utils/str" |
|||
"github.com/stretchr/testify/assert" |
|||
) |
|||
|
|||
func TestNewFilter(t *testing.T) { |
|||
preclude := []string{"test1", "test2"} |
|||
filter := str.NewFilter(preclude...) |
|||
|
|||
assert.True(t, filter.Contains("test1")) |
|||
assert.True(t, filter.Contains("test2")) |
|||
assert.False(t, filter.Contains("test3")) |
|||
} |
|||
|
|||
func TestContains(t *testing.T) { |
|||
preclude := []string{"test1", "test2"} |
|||
filter := str.NewFilter(preclude...) |
|||
|
|||
assert.True(t, filter.Contains("test1")) |
|||
assert.False(t, filter.Contains("test3")) |
|||
} |
|||
|
|||
func TestGetCount(t *testing.T) { |
|||
preclude := []string{"test1", "test2"} |
|||
filter := str.NewFilter(preclude...) |
|||
|
|||
filter.Count("test1") |
|||
filter.Count("test1") |
|||
|
|||
assert.Equal(t, 2, filter.GetCount("test1")) |
|||
assert.Equal(t, 0, filter.GetCount("test2")) |
|||
} |
|||
|
|||
func TestCount(t *testing.T) { |
|||
preclude := []string{"test1", "test2"} |
|||
filter := str.NewFilter(preclude...) |
|||
|
|||
filter.Count("test1") |
|||
filter.Count("test1") |
|||
filter.Count("test2") |
|||
|
|||
assert.Equal(t, 2, filter.GetCount("test1")) |
|||
assert.Equal(t, 1, filter.GetCount("test2")) |
|||
} |
|||
|
|||
func TestCountWithNonExistentKey(t *testing.T) { |
|||
preclude := []string{"test1", "test2"} |
|||
filter := str.NewFilter(preclude...) |
|||
|
|||
filter.Count("test3") |
|||
|
|||
assert.Equal(t, 0, filter.GetCount("test3")) |
|||
} |
@ -0,0 +1,80 @@ |
|||
package fos |
|||
|
|||
import ( |
|||
"errors" |
|||
"io/fs" |
|||
"os" |
|||
"path/filepath" |
|||
|
|||
"git.realxlfd.cc/RealXLFD/golib/utils/str" |
|||
) |
|||
|
|||
func RemoveNullDirs(path string, ignoreTypes ...string) error { |
|||
var stat fs.FileInfo |
|||
var err error |
|||
stat, err = os.Stat(path) |
|||
if err != nil || !stat.IsDir() { |
|||
return errors.New("remover: path have to be a directory") |
|||
} |
|||
filter := str.NewFilter(ignoreTypes...) |
|||
var dirs []fs.DirEntry |
|||
dirs, err = os.ReadDir(path) |
|||
for _, dir := range dirs { |
|||
if !dir.IsDir() { |
|||
ext := filepath.Ext(dir.Name()) |
|||
if ext != "" { |
|||
ext = ext[1:] |
|||
} |
|||
if filter.Contains(ext) { |
|||
err = os.Remove(filepath.Join(path, dir.Name())) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
} |
|||
continue |
|||
} |
|||
err, _ = removeNullDir(filepath.Join(path, dir.Name()), filter) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func removeNullDir(path string, filter *str.Filter) ( |
|||
err error, isNull bool, |
|||
) { |
|||
isNull = true |
|||
var isChildNull bool |
|||
dirs, err := os.ReadDir(path) |
|||
if err != nil { |
|||
return err, false |
|||
} |
|||
for _, dir := range dirs { |
|||
if dir.IsDir() { |
|||
err, isChildNull = removeNullDir( |
|||
filepath.Join(path, dir.Name()), filter, |
|||
) |
|||
if err != nil { |
|||
return err, false |
|||
} |
|||
if !isChildNull { |
|||
isNull = false |
|||
} |
|||
continue |
|||
} |
|||
ext := filepath.Ext(dir.Name()) |
|||
if ext != "" { |
|||
ext = ext[1:] |
|||
} |
|||
if filter.Contains(ext) { |
|||
continue |
|||
} |
|||
isNull = false |
|||
} |
|||
if isNull { |
|||
err = os.RemoveAll(path) |
|||
return err, true |
|||
} |
|||
return nil, isNull |
|||
} |
Loading…
Reference in new issue