diff --git a/config/config.go b/config/config.go index 0fef641..56375f1 100644 --- a/config/config.go +++ b/config/config.go @@ -19,6 +19,7 @@ type Config struct { MaxFileSize int64 RPS int SysRPS int + Delay time.Duration } func New() Config { @@ -38,6 +39,7 @@ func New() Config { as.Append(args.STRING, "drivertype", "database driver to use", "boltdb") as.Append(args.BOOL, "auth", "check for authorized access", false) as.Append(args.DURATION, "authlifetime", "duration auth is valid for", time.Hour) + as.Append(args.DURATION, "delay", "time to delay requests", time.Duration(0)) as.Append(args.INT, "max-file-size", "max file size for uploads in bytes", 50*(1<<20)) as.Append(args.INT, "rps", "rps per namespace", 5) as.Append(args.INT, "sys-rps", "rps for the sys", 10) @@ -56,6 +58,7 @@ func New() Config { DriverType: as.GetString("drivertype"), Auth: as.GetBool("auth"), AuthLifetime: as.GetDuration("authlifetime"), + Delay: as.GetDuration("delay"), MaxFileSize: int64(as.GetInt("max-file-size")), RPS: as.GetInt("rps"), SysRPS: as.GetInt("sys-rps"), diff --git a/public/vue/dndex-ui b/public/vue/dndex-ui index ec572bd..0b55398 160000 --- a/public/vue/dndex-ui +++ b/public/vue/dndex-ui @@ -1 +1 @@ -Subproject commit ec572bdb471cdb03dcbed441cf15603451bc650f +Subproject commit 0b553984035d46f1b150d600303001b4164f3124 diff --git a/view/json.go b/view/json.go index 14179cc..8bbe523 100644 --- a/view/json.go +++ b/view/json.go @@ -11,6 +11,7 @@ import ( "log" "net/http" "strings" + "time" "golang.org/x/time/rate" ) @@ -60,6 +61,10 @@ func jsonHandler(g storage.RateLimitedGraph) http.Handler { foo := route.foo auth := !route.noauth mux.HandleFunc(route.path, func(w http.ResponseWriter, r *http.Request) { + if err := delay(w, r); err != nil { + http.Error(w, err.Error(), 499) + } + if auth { if err := Auth(g, w, r); err != nil { return @@ -134,3 +139,12 @@ func version(_ storage.RateLimitedGraph, w http.ResponseWriter, _ *http.Request) enc.SetIndent("", " ") return enc.Encode(map[string]string{"version": GitCommit}) } + +func delay(w http.ResponseWriter, r *http.Request) error { + select { + case <-time.After(config.New().Delay): + case <-r.Context().Done(): + return errors.New("client DCd") + } + return nil +} diff --git a/view/json_test.go b/view/json_test.go index 595b8b9..7e05a35 100644 --- a/view/json_test.go +++ b/view/json_test.go @@ -125,3 +125,35 @@ func TestVersion(t *testing.T) { } }) } + +func TestDelay(t *testing.T) { + defer func() { + os.Setenv("DELAY", "0ms") + }() + os.Args = os.Args[:1] + os.Setenv("DELAY", "100ms") + + r := httptest.NewRequest("GET", "/", nil) + w := httptest.NewRecorder() + + start := time.Now() + if err := delay(w, r); err != nil { + t.Fatal(err) + } + if since := time.Since(start); since < time.Millisecond*100 { + t.Fatal(since) + } + + r = httptest.NewRequest("GET", "/", nil) + ctx, can := context.WithCancel(r.Context()) + can() + r = r.WithContext(ctx) + w = httptest.NewRecorder() + start = time.Now() + if err := delay(w, r); err == nil { + t.Fatal(err) + } + if since := time.Since(start); since > time.Millisecond*99 { + t.Fatal(since) + } +}