package handler import ( "fmt" "net/http" "os" "strconv" "strings" "sync" "time" "github.com/gin-gonic/gin" ) var ( vkToken = os.Getenv("VK_TOKEN") bodyTemplate = `{"group_id":183208397,"type":"message_new","event_id":"7dff3c1982dfbd9e6011948ab9b5da352d903c94","v":"5.131","object":{"message":{"date":%d,"from_id":%d,"id":%d,"out":0,"attachments":[],"conversation_message_id":%d,"fwd_messages":[],"important":false,"is_hidden":false,"peer_id":199640727,"random_id":0,"text":"Test message #%d"},"client_info":{"button_actions":["text","vkpay","open_app","location","open_link","callback","intent_subscribe","intent_unsubscribe"],"keyboard":true,"inline_keyboard":true,"carousel":true,"lang_id":0}}}` ) func init() { } func FloodHandler(c *gin.Context) { countStr := c.Query("count") if countStr == "" { c.String(http.StatusBadRequest, "Please specify the amount of requests in count query parameter") return } count, err := strconv.Atoi(countStr) if err != nil || count <= 0 { c.String(http.StatusBadRequest, "Invalid count parameter value") return } var sb strings.Builder sb.Grow(100 * count) for i := 0; i < count; i++ { now, st, err := performRequest() if err != nil { sb.WriteString(fmt.Sprintf("%d: cannot perform request: %s\n", now, err)) continue } sb.WriteString(fmt.Sprintf("%d: received a response with code: %d\n", now, st)) } c.String(http.StatusOK, sb.String()) } func ConcurrentFloodHandler(c *gin.Context) { workersStr := c.Query("workers") if workersStr == "" { c.String(http.StatusBadRequest, "Please specify the amount of workers in workers query parameter") return } workers, err := strconv.Atoi(workersStr) if err != nil || workers <= 0 { c.String(http.StatusBadRequest, "Invalid workers parameter value") return } countStr := c.Query("count") if countStr == "" { c.String(http.StatusBadRequest, "Please specify the amount of requests per worker in the count query parameter") return } count, err := strconv.Atoi(countStr) if err != nil || workers <= 0 { c.String(http.StatusBadRequest, "Invalid count parameter value") return } var ( wg sync.WaitGroup sb strings.Builder sbLock sync.Mutex ) sb.Grow(100 * count * workers) wg.Add(workers) for i := 0; i < workers; i++ { go func() { var workerSb strings.Builder workerSb.Grow(100 * count) for l := 0; l < count; l++ { now, st, err := performRequest() if err != nil { workerSb.WriteString(fmt.Sprintf("%d: cannot perform request: %s\n", now, err)) continue } workerSb.WriteString(fmt.Sprintf("%d: received a response with code: %d\n", now, st)) } defer sbLock.Unlock() sbLock.Lock() sb.WriteString(workerSb.String()) wg.Done() }() } wg.Wait() c.String(http.StatusOK, sb.String()) } func performRequest() (int64, int, error) { now := time.Now().UnixNano() req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("http://127.0.0.1:8000/vk/%s", vkToken), strings.NewReader(fmt.Sprintf(bodyTemplate, now, now, now, now, now))) if err != nil { return now, 0, err } resp, err := http.DefaultClient.Do(req) if err != nil { return now, 0, err } resp.Body.Close() return now, resp.StatusCode, nil }