Best K6 code snippet using httpext.Done
request.go
Source:request.go
1/*2 *3 * k6 - a next-generation load testing tool4 * Copyright (C) 2016 Load Impact5 *6 * This program is free software: you can redistribute it and/or modify7 * it under the terms of the GNU Affero General Public License as8 * published by the Free Software Foundation, either version 3 of the9 * License, or (at your option) any later version.10 *11 * This program is distributed in the hope that it will be useful,12 * but WITHOUT ANY WARRANTY; without even the implied warranty of13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14 * GNU Affero General Public License for more details.15 *16 * You should have received a copy of the GNU Affero General Public License17 * along with this program. If not, see <http://www.gnu.org/licenses/>.18 *19 */20package http21import (22 "bytes"23 "errors"24 "fmt"25 "mime/multipart"26 "net/http"27 "net/textproto"28 "net/url"29 "reflect"30 "strings"31 "time"32 "github.com/dop251/goja"33 "gopkg.in/guregu/null.v3"34 "go.k6.io/k6/js/common"35 "go.k6.io/k6/lib/netext/httpext"36 "go.k6.io/k6/lib/types"37)38// ErrHTTPForbiddenInInitContext is used when a http requests was made in the init context39var ErrHTTPForbiddenInInitContext = common.NewInitContextError("Making http requests in the init context is not supported")40// ErrBatchForbiddenInInitContext is used when batch was made in the init context41var ErrBatchForbiddenInInitContext = common.NewInitContextError("Using batch in the init context is not supported")42func (c *Client) getMethodClosure(method string) func(url goja.Value, args ...goja.Value) (*Response, error) {43 return func(url goja.Value, args ...goja.Value) (*Response, error) {44 return c.Request(method, url, args...)45 }46}47// Request makes an http request of the provided `method` and returns a corresponding response by48// taking goja.Values as arguments49func (c *Client) Request(method string, url goja.Value, args ...goja.Value) (*Response, error) {50 state := c.moduleInstance.vu.State()51 if state == nil {52 return nil, ErrHTTPForbiddenInInitContext53 }54 var body interface{}55 var params goja.Value56 if len(args) > 0 {57 body = args[0].Export()58 }59 if len(args) > 1 {60 params = args[1]61 }62 req, err := c.parseRequest(method, url, body, params)63 if err != nil {64 if state.Options.Throw.Bool {65 return nil, err66 }67 state.Logger.WithField("error", err).Warn("Request Failed")68 r := httpext.NewResponse()69 r.Error = err.Error()70 var k6e httpext.K6Error71 if errors.As(err, &k6e) {72 r.ErrorCode = int(k6e.Code)73 }74 return &Response{Response: r, client: c}, nil75 }76 resp, err := httpext.MakeRequest(c.moduleInstance.vu.Context(), state, req)77 if err != nil {78 return nil, err79 }80 c.processResponse(resp, req.ResponseType)81 return c.responseFromHTTPext(resp), nil82}83// processResponse stores the body as an ArrayBuffer if indicated by84// respType. This is done here instead of in httpext.readResponseBody to avoid85// a reverse dependency on js/common or goja.86func (c *Client) processResponse(resp *httpext.Response, respType httpext.ResponseType) {87 if respType == httpext.ResponseTypeBinary && resp.Body != nil {88 resp.Body = c.moduleInstance.vu.Runtime().NewArrayBuffer(resp.Body.([]byte))89 }90}91func (c *Client) responseFromHTTPext(resp *httpext.Response) *Response {92 return &Response{Response: resp, client: c}93}94// TODO: break this function up95//nolint: gocyclo, cyclop, funlen, gocognit96func (c *Client) parseRequest(97 method string, reqURL, body interface{}, params goja.Value,98) (*httpext.ParsedHTTPRequest, error) {99 rt := c.moduleInstance.vu.Runtime()100 state := c.moduleInstance.vu.State()101 if state == nil {102 return nil, ErrHTTPForbiddenInInitContext103 }104 if urlJSValue, ok := reqURL.(goja.Value); ok {105 reqURL = urlJSValue.Export()106 }107 u, err := httpext.ToURL(reqURL)108 if err != nil {109 return nil, err110 }111 result := &httpext.ParsedHTTPRequest{112 URL: &u,113 Req: &http.Request{114 Method: method,115 URL: u.GetURL(),116 Header: make(http.Header),117 },118 Timeout: 60 * time.Second,119 Throw: state.Options.Throw.Bool,120 Redirects: state.Options.MaxRedirects,121 Cookies: make(map[string]*httpext.HTTPRequestCookie),122 Tags: make(map[string]string),123 ResponseCallback: c.responseCallback,124 }125 if state.Options.DiscardResponseBodies.Bool {126 result.ResponseType = httpext.ResponseTypeNone127 } else {128 result.ResponseType = httpext.ResponseTypeText129 }130 formatFormVal := func(v interface{}) string {131 // TODO: handle/warn about unsupported/nested values132 return fmt.Sprintf("%v", v)133 }134 handleObjectBody := func(data map[string]interface{}) error {135 if !requestContainsFile(data) {136 bodyQuery := make(url.Values, len(data))137 for k, v := range data {138 if arr, ok := v.([]interface{}); ok {139 for _, el := range arr {140 bodyQuery.Add(k, formatFormVal(el))141 }142 continue143 }144 bodyQuery.Set(k, formatFormVal(v))145 }146 result.Body = bytes.NewBufferString(bodyQuery.Encode())147 result.Req.Header.Set("Content-Type", "application/x-www-form-urlencoded")148 return nil149 }150 // handling multipart request151 result.Body = &bytes.Buffer{}152 mpw := multipart.NewWriter(result.Body)153 // For parameters of type common.FileData, created with open(file, "b"),154 // we write the file boundary to the body buffer.155 // Otherwise parameters are treated as standard form field.156 for k, v := range data {157 switch ve := v.(type) {158 case FileData:159 // writing our own part to handle receiving160 // different content-type than the default application/octet-stream161 h := make(textproto.MIMEHeader)162 escapedFilename := escapeQuotes(ve.Filename)163 h.Set("Content-Disposition",164 fmt.Sprintf(`form-data; name="%s"; filename="%s"`,165 k, escapedFilename))166 h.Set("Content-Type", ve.ContentType)167 // this writer will be closed either by the next part or168 // the call to mpw.Close()169 fw, err := mpw.CreatePart(h)170 if err != nil {171 return err172 }173 if _, err := fw.Write(ve.Data); err != nil {174 return err175 }176 default:177 fw, err := mpw.CreateFormField(k)178 if err != nil {179 return err180 }181 if _, err := fw.Write([]byte(formatFormVal(v))); err != nil {182 return err183 }184 }185 }186 if err := mpw.Close(); err != nil {187 return err188 }189 result.Req.Header.Set("Content-Type", mpw.FormDataContentType())190 return nil191 }192 if body != nil {193 switch data := body.(type) {194 case map[string]goja.Value:195 // TODO: fix forms submission and serialization in k6/html before fixing this..196 newData := map[string]interface{}{}197 for k, v := range data {198 newData[k] = v.Export()199 }200 if err := handleObjectBody(newData); err != nil {201 return nil, err202 }203 case goja.ArrayBuffer:204 result.Body = bytes.NewBuffer(data.Bytes())205 case map[string]interface{}:206 if err := handleObjectBody(data); err != nil {207 return nil, err208 }209 case string:210 result.Body = bytes.NewBufferString(data)211 case []byte:212 result.Body = bytes.NewBuffer(data)213 default:214 return nil, fmt.Errorf("unknown request body type %T", body)215 }216 }217 result.Req.Header.Set("User-Agent", state.Options.UserAgent.String)218 if state.CookieJar != nil {219 result.ActiveJar = state.CookieJar220 }221 // TODO: ditch goja.Value, reflections and Object and use a simple go map and type assertions?222 if params != nil && !goja.IsUndefined(params) && !goja.IsNull(params) {223 params := params.ToObject(rt)224 for _, k := range params.Keys() {225 switch k {226 case "cookies":227 cookiesV := params.Get(k)228 if goja.IsUndefined(cookiesV) || goja.IsNull(cookiesV) {229 continue230 }231 cookies := cookiesV.ToObject(rt)232 if cookies == nil {233 continue234 }235 for _, key := range cookies.Keys() {236 cookieV := cookies.Get(key)237 if goja.IsUndefined(cookieV) || goja.IsNull(cookieV) {238 continue239 }240 switch cookieV.ExportType() {241 case reflect.TypeOf(map[string]interface{}{}):242 result.Cookies[key] = &httpext.HTTPRequestCookie{Name: key, Value: "", Replace: false}243 cookie := cookieV.ToObject(rt)244 for _, attr := range cookie.Keys() {245 switch strings.ToLower(attr) {246 case "replace":247 result.Cookies[key].Replace = cookie.Get(attr).ToBoolean()248 case "value":249 result.Cookies[key].Value = cookie.Get(attr).String()250 }251 }252 default:253 result.Cookies[key] = &httpext.HTTPRequestCookie{Name: key, Value: cookieV.String(), Replace: false}254 }255 }256 case "headers":257 headersV := params.Get(k)258 if goja.IsUndefined(headersV) || goja.IsNull(headersV) {259 continue260 }261 headers := headersV.ToObject(rt)262 if headers == nil {263 continue264 }265 for _, key := range headers.Keys() {266 str := headers.Get(key).String()267 if strings.ToLower(key) == "host" {268 result.Req.Host = str269 }270 result.Req.Header.Set(key, str)271 }272 case "jar":273 jarV := params.Get(k)274 if goja.IsUndefined(jarV) || goja.IsNull(jarV) {275 continue276 }277 switch v := jarV.Export().(type) {278 case *CookieJar:279 result.ActiveJar = v.Jar280 }281 case "compression":282 algosString := strings.TrimSpace(params.Get(k).ToString().String())283 if algosString == "" {284 continue285 }286 algos := strings.Split(algosString, ",")287 var err error288 result.Compressions = make([]httpext.CompressionType, len(algos))289 for index, algo := range algos {290 algo = strings.TrimSpace(algo)291 result.Compressions[index], err = httpext.CompressionTypeString(algo)292 if err != nil {293 return nil, fmt.Errorf("unknown compression algorithm %s, supported algorithms are %s",294 algo, httpext.CompressionTypeValues())295 }296 }297 case "redirects":298 result.Redirects = null.IntFrom(params.Get(k).ToInteger())299 case "tags":300 tagsV := params.Get(k)301 if goja.IsUndefined(tagsV) || goja.IsNull(tagsV) {302 continue303 }304 tagObj := tagsV.ToObject(rt)305 if tagObj == nil {306 continue307 }308 for _, key := range tagObj.Keys() {309 result.Tags[key] = tagObj.Get(key).String()310 }311 case "auth":312 result.Auth = params.Get(k).String()313 case "timeout":314 t, err := types.GetDurationValue(params.Get(k).Export())315 if err != nil {316 return nil, fmt.Errorf("invalid timeout value: %w", err)317 }318 result.Timeout = t319 case "throw":320 result.Throw = params.Get(k).ToBoolean()321 case "responseType":322 responseType, err := httpext.ResponseTypeString(params.Get(k).String())323 if err != nil {324 return nil, err325 }326 result.ResponseType = responseType327 case "responseCallback":328 v := params.Get(k).Export()329 if v == nil {330 result.ResponseCallback = nil331 } else if c, ok := v.(*expectedStatuses); ok {332 result.ResponseCallback = c.match333 } else {334 return nil, fmt.Errorf("unsupported responseCallback")335 }336 }337 }338 }339 if result.ActiveJar != nil {340 httpext.SetRequestCookies(result.Req, result.ActiveJar, result.Cookies)341 }342 return result, nil343}344func (c *Client) prepareBatchArray(requests []interface{}) (345 []httpext.BatchParsedHTTPRequest, []*Response, error,346) {347 reqCount := len(requests)348 batchReqs := make([]httpext.BatchParsedHTTPRequest, reqCount)349 results := make([]*Response, reqCount)350 for i, req := range requests {351 resp := httpext.NewResponse()352 parsedReq, err := c.parseBatchRequest(i, req)353 if err != nil {354 resp.Error = err.Error()355 var k6e httpext.K6Error356 if errors.As(err, &k6e) {357 resp.ErrorCode = int(k6e.Code)358 }359 results[i] = c.responseFromHTTPext(resp)360 return batchReqs, results, err361 }362 batchReqs[i] = httpext.BatchParsedHTTPRequest{363 ParsedHTTPRequest: parsedReq,364 Response: resp,365 }366 results[i] = c.responseFromHTTPext(resp)367 }368 return batchReqs, results, nil369}370func (c *Client) prepareBatchObject(requests map[string]interface{}) (371 []httpext.BatchParsedHTTPRequest, map[string]*Response, error,372) {373 reqCount := len(requests)374 batchReqs := make([]httpext.BatchParsedHTTPRequest, reqCount)375 results := make(map[string]*Response, reqCount)376 i := 0377 for key, req := range requests {378 resp := httpext.NewResponse()379 parsedReq, err := c.parseBatchRequest(key, req)380 if err != nil {381 resp.Error = err.Error()382 var k6e httpext.K6Error383 if errors.As(err, &k6e) {384 resp.ErrorCode = int(k6e.Code)385 }386 results[key] = c.responseFromHTTPext(resp)387 return batchReqs, results, err388 }389 batchReqs[i] = httpext.BatchParsedHTTPRequest{390 ParsedHTTPRequest: parsedReq,391 Response: resp,392 }393 results[key] = c.responseFromHTTPext(resp)394 i++395 }396 return batchReqs, results, nil397}398// Batch makes multiple simultaneous HTTP requests. The provideds reqsV should be an array of request399// objects. Batch returns an array of responses and/or error400func (c *Client) Batch(reqsV goja.Value) (interface{}, error) {401 state := c.moduleInstance.vu.State()402 if state == nil {403 return nil, ErrBatchForbiddenInInitContext404 }405 var (406 err error407 batchReqs []httpext.BatchParsedHTTPRequest408 results interface{} // either []*Response or map[string]*Response409 )410 if reqsV == nil {411 return nil, errors.New("no argument was provided to http.batch()")412 }413 switch v := reqsV.Export().(type) {414 case []interface{}:415 batchReqs, results, err = c.prepareBatchArray(v)416 case map[string]interface{}:417 batchReqs, results, err = c.prepareBatchObject(v)418 default:419 return nil, fmt.Errorf("invalid http.batch() argument type %T", v)420 }421 if err != nil {422 if state.Options.Throw.Bool {423 return nil, err424 }425 state.Logger.WithField("error", err).Warn("A batch request failed")426 return results, nil427 }428 reqCount := len(batchReqs)429 errs := httpext.MakeBatchRequests(430 c.moduleInstance.vu.Context(), state, batchReqs, reqCount,431 int(state.Options.Batch.Int64), int(state.Options.BatchPerHost.Int64),432 c.processResponse,433 )434 for i := 0; i < reqCount; i++ {435 if e := <-errs; e != nil && err == nil { // Save only the first error436 err = e437 }438 }439 return results, err440}441func (c *Client) parseBatchRequest(key interface{}, val interface{}) (*httpext.ParsedHTTPRequest, error) {442 var (443 method = http.MethodGet444 ok bool445 body, reqURL interface{}446 params goja.Value447 rt = c.moduleInstance.vu.Runtime()448 )449 switch data := val.(type) {450 case []interface{}:451 // Handling of ["GET", "http://example.com/"]452 dataLen := len(data)453 if dataLen < 2 {454 return nil, fmt.Errorf("invalid batch request '%#v'", data)455 }456 method, ok = data[0].(string)457 if !ok {458 return nil, fmt.Errorf("invalid method type '%#v'", data[0])459 }460 reqURL = data[1]461 if dataLen > 2 {462 body = data[2]463 }464 if dataLen > 3 {465 params = rt.ToValue(data[3])466 }467 case map[string]interface{}:468 // Handling of {method: "GET", url: "https://test.k6.io"}469 if _, ok := data["url"]; !ok {470 return nil, fmt.Errorf("batch request %v doesn't have a url key", key)471 }472 reqURL = data["url"]473 body = data["body"] // It's fine if it's missing, the map lookup will return474 if newMethod, ok := data["method"]; ok {475 if method, ok = newMethod.(string); !ok {476 return nil, fmt.Errorf("invalid method type '%#v'", newMethod)477 }478 method = strings.ToUpper(method)479 if method == http.MethodGet || method == http.MethodHead {480 body = nil481 }482 }483 if p, ok := data["params"]; ok {484 params = rt.ToValue(p)485 }486 default:487 reqURL = val488 }489 return c.parseRequest(method, reqURL, body, params)490}491func requestContainsFile(data map[string]interface{}) bool {492 for _, v := range data {493 switch v.(type) {494 case FileData:495 return true496 }497 }498 return false499}...
remote_write.go
Source:remote_write.go
1package remotewrite2import (3 "bytes"4 "encoding/binary"5 "fmt"6 "log"7 "math"8 "math/rand"9 "net/http"10 "net/url"11 "sort"12 "strconv"13 "strings"14 "time"15 "github.com/dop251/goja"16 "github.com/golang/protobuf/proto"17 "github.com/golang/snappy"18 "github.com/pkg/errors"19 "github.com/prometheus/prometheus/prompb"20 "github.com/xhit/go-str2duration/v2"21 "go.k6.io/k6/js/common"22 "go.k6.io/k6/js/modules"23 "go.k6.io/k6/lib"24 "go.k6.io/k6/lib/netext/httpext"25 "google.golang.org/protobuf/encoding/protowire"26)27// Register the extension on module initialization, available to28// import from JS as "k6/x/remotewrite".29func init() {30 modules.Register("k6/x/remotewrite", new(remoteWriteModule))31}32// RemoteWrite is the k6 extension for interacting Prometheus Remote Write endpoints.33type RemoteWrite struct {34 vu modules.VU35}36type remoteWriteModule struct{}37var _ modules.Module = &remoteWriteModule{}38func (r *remoteWriteModule) NewModuleInstance(vu modules.VU) modules.Instance {39 return &RemoteWrite{40 vu: vu,41 }42}43func (r *RemoteWrite) Exports() modules.Exports {44 return modules.Exports{45 Named: map[string]interface{}{46 "Client": r.xclient,47 "Sample": r.sample,48 "Timeseries": r.timeseries,49 "precompileLabelTemplates": compileLabelTemplates,50 },51 }52}53// Client is the client wrapper.54type Client struct {55 client *http.Client56 cfg *Config57 vu modules.VU58}59type Config struct {60 Url string `json:"url"`61 UserAgent string `json:"user_agent"`62 Timeout string `json:"timeout"`63 TenantName string `json:"tenant_name"`64}65// xclient represents66func (r *RemoteWrite) xclient(c goja.ConstructorCall) *goja.Object {67 var config Config68 rt := r.vu.Runtime()69 err := rt.ExportTo(c.Argument(0), &config)70 if err != nil {71 common.Throw(rt, fmt.Errorf("Client constructor expects first argument to be Config"))72 }73 if config.Url == "" {74 log.Fatal(fmt.Errorf("url is required"))75 }76 if config.UserAgent == "" {77 config.UserAgent = "k6-remote-write/0.0.2"78 }79 if config.Timeout == "" {80 config.Timeout = "10s"81 }82 return rt.ToValue(&Client{83 client: &http.Client{},84 cfg: &config,85 vu: r.vu,86 }).ToObject(rt)87}88type Timeseries struct {89 Labels []Label90 Samples []Sample91}92type Label struct {93 Name, Value string94}95type Sample struct {96 Value float6497 Timestamp int6498}99func (r *RemoteWrite) sample(c goja.ConstructorCall) *goja.Object {100 rt := r.vu.Runtime()101 call, _ := goja.AssertFunction(rt.ToValue(xsample))102 v, err := call(goja.Undefined(), c.Arguments...)103 if err != nil {104 common.Throw(rt, err)105 }106 return v.ToObject(rt)107}108func xsample(value float64, timestamp int64) Sample {109 return Sample{110 Value: value,111 Timestamp: timestamp,112 }113}114func (r *RemoteWrite) timeseries(c goja.ConstructorCall) *goja.Object {115 rt := r.vu.Runtime()116 call, _ := goja.AssertFunction(rt.ToValue(xtimeseries))117 v, err := call(goja.Undefined(), c.Arguments...)118 if err != nil {119 common.Throw(rt, err)120 }121 return v.ToObject(rt)122}123func xtimeseries(labels map[string]string, samples []Sample) *Timeseries {124 t := &Timeseries{125 Labels: make([]Label, 0, len(labels)),126 Samples: samples,127 }128 for k, v := range labels {129 t.Labels = append(t.Labels, Label{Name: k, Value: v})130 }131 return t132}133func (c *Client) StoreGenerated(total_series, batches, batch_size, batch int64) (httpext.Response, error) {134 ts, err := generate_series(total_series, batches, batch_size, batch)135 if err != nil {136 return *httpext.NewResponse(), err137 }138 return c.Store(ts)139}140func generate_series(total_series, batches, batch_size, batch int64) ([]Timeseries, error) {141 if total_series == 0 {142 return nil, nil143 }144 if batch > batches {145 return nil, errors.New("batch must be in the range of batches")146 }147 if total_series/batches != batch_size {148 return nil, errors.New("total_series must divide evenly into batches of size batch_size")149 }150 r := rand.New(rand.NewSource(time.Now().Unix()))151 series := make([]Timeseries, batch_size)152 timestamp := time.Now().UnixNano() / int64(time.Millisecond)153 for i := int64(0); i < batch_size; i++ {154 series_id := batch_size*(batch-1) + i155 labels := generate_cardinality_labels(total_series, series_id)156 labels = append(labels, Label{157 Name: "__name__",158 Value: "k6_generated_metric_" + strconv.Itoa(int(series_id)),159 })160 // Required for querying in order to have unique series excluding the metric name.161 labels = append(labels, Label{162 Name: "series_id",163 Value: strconv.Itoa(int(series_id)),164 })165 series[i] = Timeseries{166 labels,167 []Sample{{r.Float64() * 100, timestamp}},168 }169 }170 return series, nil171}172func generate_cardinality_labels(total_series, series_id int64) []Label {173 // exp is the greatest exponent of 10 that is less than total series.174 exp := int64(math.Log10(float64(total_series)))175 labels := make([]Label, 0, exp)176 for x := 1; int64(x) <= exp; x++ {177 labels = append(labels, Label{178 Name: "cardinality_1e" + strconv.Itoa(x),179 Value: strconv.Itoa(int(series_id / int64(math.Pow(10, float64(x))))),180 })181 }182 return labels183}184func (c *Client) Store(ts []Timeseries) (httpext.Response, error) {185 var batch []prompb.TimeSeries186 for _, t := range ts {187 batch = append(batch, FromTimeseriesToPrometheusTimeseries(t))188 }189 return c.store(batch)190}191func (c *Client) store(batch []prompb.TimeSeries) (httpext.Response, error) {192 // Required for k6 metrics193 state := c.vu.State()194 if state == nil {195 return *httpext.NewResponse(), errors.New("State is nil")196 }197 req := prompb.WriteRequest{198 Timeseries: batch,199 }200 data, err := proto.Marshal(&req)201 if err != nil {202 return *httpext.NewResponse(), errors.Wrap(err, "failed to marshal remote-write request")203 }204 compressed := snappy.Encode(nil, data)205 res, err := c.send(state, compressed)206 if err != nil {207 return *httpext.NewResponse(), errors.Wrap(err, "remote-write request failed")208 }209 res.Request.Body = ""210 return res, nil211}212// send sends a batch of samples to the HTTP endpoint, the request is the proto marshalled213// and encoded bytes214func (c *Client) send(state *lib.State, req []byte) (httpext.Response, error) {215 httpResp := httpext.NewResponse()216 r, err := http.NewRequest("POST", c.cfg.Url, nil)217 if err != nil {218 return *httpResp, err219 }220 r.Header.Add("Content-Encoding", "snappy")221 r.Header.Set("Content-Type", "application/x-protobuf")222 r.Header.Set("User-Agent", c.cfg.UserAgent)223 r.Header.Set("X-Prometheus-Remote-Write-Version", "0.0.2")224 if c.cfg.TenantName != "" {225 r.Header.Set("X-Scope-OrgID", c.cfg.TenantName)226 }227 duration, err := str2duration.ParseDuration(c.cfg.Timeout)228 if err != nil {229 return *httpResp, err230 }231 u, err := url.Parse(c.cfg.Url)232 if err != nil {233 return *httpResp, err234 }235 url, _ := httpext.NewURL(c.cfg.Url, u.Host+u.Path)236 response, err := httpext.MakeRequest(c.vu.Context(), state, &httpext.ParsedHTTPRequest{237 URL: &url,238 Req: r,239 Body: bytes.NewBuffer(req),240 Throw: state.Options.Throw.Bool,241 Redirects: state.Options.MaxRedirects,242 Timeout: duration,243 ResponseCallback: ResponseCallback,244 })245 if err != nil {246 return *httpResp, err247 }248 return *response, err249}250func ResponseCallback(n int) bool {251 return n == 200252}253func FromTimeseriesToPrometheusTimeseries(ts Timeseries) prompb.TimeSeries {254 var labels []prompb.Label255 var samples []prompb.Sample256 for _, label := range ts.Labels {257 labels = append(labels, prompb.Label{258 Name: label.Name,259 Value: label.Value,260 })261 }262 for _, sample := range ts.Samples {263 if sample.Timestamp == 0 {264 sample.Timestamp = time.Now().UnixNano() / int64(time.Millisecond)265 }266 samples = append(samples, prompb.Sample{267 Value: sample.Value,268 Timestamp: sample.Timestamp,269 })270 }271 return prompb.TimeSeries{272 Labels: labels,273 Samples: samples,274 }275}276// The only supported things are:277// 1. replacing ${series_id} with the series_id provided278// 2. replacing ${series_id/<integer>} with the evaluation of that279// 3. if error in parsing return error280func compileTemplate(template string) (*labelGenerator, error) {281 i := strings.Index(template, "${series_id")282 if i == -1 {283 return newIdentityLabelGenerator(template), nil284 }285 switch template[i+len("${series_id")] {286 case '}':287 return &labelGenerator{288 AppendByte: func(b []byte, seriesID int) []byte {289 b = append(b, template[:i]...)290 b = strconv.AppendInt(b, int64(seriesID), 10)291 return append(b, template[i+len("${series_id}"):]...)292 },293 }, nil294 case '%':295 end := strings.Index(template[i:], "}")296 if end == -1 {297 return nil, errors.New("no closing bracket in template")298 }299 d, err := strconv.Atoi(template[i+len("${series_id%") : i+end])300 if err != nil {301 return nil, fmt.Errorf("can't parse divisor of the module operator %w", err)302 }303 possibleValues := make([][]byte, d)304 // TODO have an upper limit305 for j := 0; j < d; j++ {306 var b []byte307 b = append(b, template[:i]...)308 b = strconv.AppendInt(b, int64(j), 10)309 possibleValues[j] = append(b, template[i+end+1:]...)310 }311 return &labelGenerator{312 AppendByte: func(b []byte, seriesID int) []byte {313 return append(b, possibleValues[seriesID%d]...)314 },315 }, nil316 case '/':317 end := strings.Index(template[i:], "}")318 if end == -1 {319 return nil, errors.New("no closing bracket in template")320 }321 d, err := strconv.Atoi(template[i+len("${series_id/") : i+end])322 if err != nil {323 return nil, err324 }325 var memoize []byte326 var memoizeValue int64327 return &labelGenerator{328 AppendByte: func(b []byte, seriesID int) []byte {329 value := int64(seriesID / d)330 if memoize == nil || value != memoizeValue {331 memoizeValue = value332 memoize = memoize[:0]333 memoize = append(memoize, template[:i]...)334 memoize = strconv.AppendInt(memoize, value, 10)335 memoize = append(memoize, template[i+end+1:]...)336 }337 return append(b, memoize...)338 },339 }, nil340 }341 return nil, errors.New("unsupported template")342}343type labelGenerator struct {344 AppendByte func([]byte, int) []byte345}346func newIdentityLabelGenerator(t string) *labelGenerator {347 return &labelGenerator{348 AppendByte: func(b []byte, _ int) []byte { return append(b, t...) },349 }350}351// this is opaque on purpose so that it can't be done anything to from the js side352type labelTemplates struct {353 compiledTemplates []compiledTemplate354 labelValue []byte355}356type compiledTemplate struct {357 name string358 generator *labelGenerator359}360func compileLabelTemplates(labelsTemplate map[string]string) (*labelTemplates, error) {361 compiledTemplates := make([]compiledTemplate, len(labelsTemplate))362 {363 i := 0364 var err error365 for k, v := range labelsTemplate {366 compiledTemplates[i].name = k367 compiledTemplates[i].generator, err = compileTemplate(v)368 if err != nil {369 return nil, fmt.Errorf("error while compiling template %q, %w", v, err)370 }371 i++372 }373 }374 sort.Slice(compiledTemplates, func(i, j int) bool {375 return compiledTemplates[i].name < compiledTemplates[j].name376 })377 return &labelTemplates{378 compiledTemplates: compiledTemplates,379 labelValue: make([]byte, 128), // this is way more than necessary and it will grow if needed380 }, nil381}382func (c *Client) StoreFromTemplates(383 minValue, maxValue int,384 timestamp int64, minSeriesID, maxSeriesID int,385 labelsTemplate map[string]string,386) (httpext.Response, error) {387 template, err := compileLabelTemplates(labelsTemplate)388 if err != nil {389 return *httpext.NewResponse(), err390 }391 return c.StoreFromPrecompiledTemplates(minValue, maxValue, timestamp, minSeriesID, maxSeriesID, template)392}393func (template *labelTemplates) writeFor(w *bytes.Buffer, value float64, seriesID int, timestamp int64) (err error) {394 labelValue := template.labelValue[:]395 for _, template := range template.compiledTemplates {396 labelValue = labelValue[:0]397 w.WriteByte(0xa)398 labelValue = protowire.AppendVarint(labelValue, uint64(len(template.name)))399 n1 := len(labelValue)400 labelValue = template.generator.AppendByte(labelValue, seriesID)401 n2 := len(labelValue)402 labelValue = protowire.AppendVarint(labelValue, uint64(n2-n1))403 n3 := len(labelValue)404 labelValue = protowire.AppendVarint(labelValue, uint64(n3+1+1+len(template.name)))405 w.Write(labelValue[n3:])406 w.WriteByte(0xa)407 w.Write(labelValue[:n1])408 w.WriteString(template.name)409 w.WriteByte(0x12)410 w.Write(labelValue[n2:n3])411 w.Write(labelValue[n1:n2])412 }413 labelValue = labelValue[:10]414 labelValue[0] = 0x9415 binary.LittleEndian.PutUint64(labelValue[1:9], uint64(math.Float64bits(value)))416 labelValue[9] = 0x10417 labelValue = protowire.AppendVarint(labelValue, uint64(timestamp))418 n := len(labelValue)419 labelValue = labelValue[:n+1]420 labelValue[n] = 0x12421 labelValue = protowire.AppendVarint(labelValue, uint64(n))422 w.Write(labelValue[n:])423 w.Write(labelValue[:n])424 template.labelValue = labelValue425 return nil // TODO fix426}427func (c *Client) StoreFromPrecompiledTemplates(428 minValue, maxValue int,429 timestamp int64, minSeriesID, maxSeriesID int,430 template *labelTemplates,431) (httpext.Response, error) {432 state := c.vu.State()433 if state == nil {434 return *httpext.NewResponse(), errors.New("State is nil")435 }436 r := rand.New(rand.NewSource(time.Now().Unix()))437 buf := generateFromPrecompiledTemplates(r, minValue, maxValue, timestamp, minSeriesID, maxSeriesID, template)438 b := buf.Bytes()439 compressed := make([]byte, len(b)/9) // the general size is actually between 1/9 and 1/10th but this is closed enough440 compressed = snappy.Encode(compressed, b)441 res, err := c.send(state, compressed)442 if err != nil {443 return *httpext.NewResponse(), errors.Wrap(err, "remote-write request failed")444 }445 res.Request.Body = ""446 return res, nil447}448func generateFromPrecompiledTemplates(449 r *rand.Rand,450 minValue, maxValue int,451 timestamp int64, minSeriesID, maxSeriesID int,452 template *labelTemplates,453) *bytes.Buffer {454 bigB := make([]byte, 1024)455 buf := new(bytes.Buffer)456 buf.Reset()457 tsBuf := new(bytes.Buffer)458 bigB[0] = 0xa459 template.writeFor(tsBuf, valueBetween(r, minValue, maxValue), minSeriesID, timestamp)460 bigB = protowire.AppendVarint(bigB[:1], uint64(tsBuf.Len()))461 buf.Write(bigB)462 tsBuf.WriteTo(buf)463 buf.Grow((buf.Len() + 2) * (maxSeriesID - minSeriesID)) // heuristics to try to get big enough buffer in one go464 for seriesID := minSeriesID + 1; seriesID < maxSeriesID; seriesID++ {465 tsBuf.Reset()466 bigB[0] = 0xa467 template.writeFor(tsBuf, valueBetween(r, minValue, maxValue), seriesID, timestamp)468 bigB = protowire.AppendVarint(bigB[:1], uint64(tsBuf.Len()))469 buf.Write(bigB)470 tsBuf.WriteTo(buf)471 }472 return buf473}474func valueBetween(r *rand.Rand, min, max int) float64 {475 return (r.Float64() * float64(max-min)) + float64(min)476}...
client.go
Source:client.go
...286 }287 now := time.Now()288 tags := metrics.NewSampleTags(map[string]string{"endpoint": queryType.Endpoint()})289 ctx := c.vu.Context()290 metrics.PushIfNotDone(ctx, c.vu.State().Samples, metrics.ConnectedSamples{291 Samples: []metrics.Sample{292 {293 Metric: c.metrics.BytesProcessedTotal,294 Tags: tags,295 Value: float64(responseWithStats.Data.stats.Summary.TotalBytesProcessed),296 Time: now,297 },298 {299 Metric: c.metrics.BytesProcessedPerSeconds,300 Tags: tags,301 Value: float64(responseWithStats.Data.stats.Summary.BytesProcessedPerSecond),302 Time: now,303 },304 {...
Done
Using AI Code Generation
1import (2func main() {3 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {4 fmt.Fprintln(w, "Hello World")5 })6 http.ListenAndServe(":8080", nil)7}8import (9type ResponseWriter struct {10}11func (w *ResponseWriter) Done() {12}13func (w *ResponseWriter) WriteHeader(code int) {14 w.ResponseWriter.WriteHeader(code)15}16func (w *ResponseWriter) Write(b []byte) (int, error) {17 return w.ResponseWriter.Write(b)18}19func Wrap(w http.ResponseWriter) *ResponseWriter {20 return &ResponseWriter{w, make(chan bool)}21}22import (23func main() {24 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {25 fmt.Fprintln(w, "Hello World")26 })27 http.ListenAndServe(":8080", nil)28}29import (30type ResponseWriter struct {31}32func (w *ResponseWriter) Done() {33}34func (w *ResponseWriter) WriteHeader(code int) {35 w.ResponseWriter.WriteHeader(code)36}37func (w *ResponseWriter) Write(b []byte) (int, error) {38 return w.ResponseWriter.Write(b)39}40func Wrap(w http.ResponseWriter) *ResponseWriter {41 return &ResponseWriter{w, make(chan bool)}42}43import (44func main() {45 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {46 fmt.Fprintln(w, "Hello World")47 })48 http.ListenAndServe(":8080", nil)49}50import (51type ResponseWriter struct {52}53func (w *ResponseWriter) Done() {54}55func (w *ResponseWriter) WriteHeader(code int) {56 w.ResponseWriter.WriteHeader(code)57}58func (w *ResponseWriter) Write(b []byte) (int, error) {59 return w.ResponseWriter.Write(b)60}61func Wrap(w http.ResponseWriter) *ResponseWriter {62 return &ResponseWriter{w, make(chan bool)}63}64import (
Done
Using AI Code Generation
1import (2func main() {3 if err != nil {4 fmt.Println(err)5 }6 c := http.Client{}7 resp, err := c.Do(req)8 if err != nil {9 fmt.Println(err)10 }11 defer resp.Body.Close()12 fmt.Println("Response Status:", resp.Status)13 fmt.Println("Response Headers:", resp.Header)14 fmt.Println("Response Body:", resp.Body)15}16Response Headers: map[Alt-Svc:[h3-27=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"] Cache-Control:[private, max-age=0] Content-Encoding:[gzip] Content-Type:[text/html; charset=ISO-8859-1] Date:[Wed, 07 Apr 2021 15:48:03 GMT] Expires:[-1] P3p:[CP="This is not a P3P policy! See g.co/p3phelp for more info."] Server:[gws] Set-Cookie:[1P_JAR=2021-04-07-15; expires=Fri, 07-May-2021 15:48:03 GMT; path=/; domain=.google.com, NID=206=HdR7VcJgKp0hVWY9Yq3Oq0ZuK7jNfN8Wf7VpNzB0n7rjKf2Y2YbFvZ2xj7Vx2c8WgTtT2jKuJ7VpNzB0n7rjKf2Y2YbFvZ2xj7Vx2c8WgTtT2jKuJ7VpNzB0n7rjKf2Y2YbFvZ2xj7Vx2c8WgTtT2jKuJ7V
Done
Using AI Code Generation
1import (2func main() {3 urls := []string{4 }5 start := time.Now()6 ch := make(chan string)7 for _, url := range urls {8 }9 for range urls {10 }11 fmt.Printf("%.2fs elapsed12", time.Since(start).Seconds())13}14func fetch(url string, ch chan<- string) {15 start := time.Now()16 resp, err := http.Get(url)17 if err != nil {18 }19 nbytes, err := httpext.Done(resp)20 secs := time.Since(start).Seconds()
Done
Using AI Code Generation
1import "fmt"2import "net/http"3import "net/httpext"4func main() {5 c := httpext.NewClient()6 if err != nil {7 panic(err)8 }9 resp, err := c.Do(req)10 if err != nil {11 panic(err)12 }13 fmt.Println(resp)14}15import "fmt"16import "net/http"17import "net/httpext"18func main() {19 c := httpext.NewClient()20 if err != nil {21 panic(err)22 }23 fmt.Println(resp)24}25import "fmt"26import "net/http"27import "net/httpext"28func main() {29 c := httpext.NewClient()30 if err != nil {31 panic(err)32 }33 fmt.Println(resp)34}35import "fmt"36import "net/http"37import "net/httpext"38func main() {39 c := httpext.NewClient()40 if err != nil {41 panic(err)42 }43 fmt.Println(resp)44}45import "fmt"46import "net/http"47import "net/httpext"48func main() {49 c := httpext.NewClient()50 if err != nil {51 panic(err)52 }53 fmt.Println(resp)54}55import "fmt"56import "net/http"57import "net/httpext"58func main() {59 c := httpext.NewClient()60 if err != nil {61 panic(err)62 }
Done
Using AI Code Generation
1import (2func TestDone(t *testing.T) {3 w := httptest.NewRecorder()4 h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {5 fmt.Fprintln(w, "Hello, client")6 })7 h.ServeHTTP(w, req)8 resp := w.Result()9 defer resp.Body.Close()10 fmt.Println(resp.Status)11 fmt.Println(resp.StatusCode)12 fmt.Println(resp.Proto)13 fmt.Println(resp.ProtoMajor)14 fmt.Println(resp.ProtoMinor)15 fmt.Println(resp.Header)16 fmt.Println(resp.Body)17 fmt.Println(resp.ContentLength)18 fmt.Println(resp.TransferEncoding)19 fmt.Println(resp.Close)20 fmt.Println(resp.Trailer)21 fmt.Println(resp.Request)22 fmt.Println(resp.TLS)23}24import (25func TestDone(t *testing.T) {26 w := httptest.NewRecorder()27 h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {28 fmt.Fprintln(w, "Hello, client")29 })30 h.ServeHTTP(w, req)31 resp := w.Result()32 defer resp.Body.Close()33 fmt.Println(resp.Status)34 fmt.Println(resp.StatusCode)35 fmt.Println(resp.Proto)36 fmt.Println(resp.ProtoMajor)37 fmt.Println(resp.ProtoMinor)38 fmt.Println(resp.Header)39 fmt.Println(resp.Body)40 fmt.Println(resp.ContentLength)41 fmt.Println(resp.TransferEncoding)42 fmt.Println(resp.Close)43 fmt.Println(resp.Trailer)44 fmt.Println(resp.Request)45 fmt.Println(resp.TLS)46}
Done
Using AI Code Generation
1import "fmt"2import "github.com/astaxie/beego/httplib"3func main() {4 str, err := req.String()5 if err != nil {6 fmt.Println(err)7 } else {8 fmt.Println(str)9 }10}11import "fmt"12import "github.com/astaxie/beego/httplib"13func main() {14 str, err := req.String()15 if err != nil {16 fmt.Println(err)17 } else {18 fmt.Println(str)19 }20}21import "fmt"22import "github.com/astaxie/beego/httplib"23func main() {24 str, err := req.String()25 if err != nil {26 fmt.Println(err)27 } else {28 fmt.Println(str)29 }30}31import "fmt"32import "github.com/astaxie/beego/httplib"33func main() {34 str, err := req.String()35 if err != nil {36 fmt.Println(err)37 } else {38 fmt.Println(str)39 }40}41import "fmt"42import "github.com/astaxie/beego/httplib"43func main() {44 str, err := req.String()45 if err != nil {46 fmt.Println(err)47 } else {48 fmt.Println(str)49 }50}51import "fmt"52import "github.com/astaxie/beego/httplib"53func main() {54 str, err := req.String()
Done
Using AI Code Generation
1import (2func main() {3}4import (5func main() {6}7import (8func main() {9}10import (11func main() {12}13import (14func main() {15}16import (17func main() {18}
Done
Using AI Code Generation
1import (2func main() {3 jar, err := cookiejar.New(nil)4 if err != nil {5 fmt.Println(err)6 }7 client := &http.Client{8 }9 if err != nil {10 fmt.Println(err)11 }12 trace := &httptrace.ClientTrace{13 GotConn: func(connInfo httptrace.GotConnInfo) {14 fmt.Println("Got Connection")15 },16 }17 req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))18 resp, err := client.Do(req)19 if err != nil {20 fmt.Println(err)21 }22 body, err := ioutil.ReadAll(resp.Body)23 if err != nil {24 fmt.Println(err)25 }26 fmt.Println(string(body))27 resp.Body.Close()28}29import (30func main() {31 jar, err := cookiejar.New(nil)32 if err != nil {33 fmt.Println(err)34 }35 client := &http.Client{36 }37 if err != nil {38 fmt.Println(err)39 }40 trace := &httptrace.ClientTrace{41 GotConn: func(connInfo httptrace.GotConnInfo) {42 fmt.Println("Got Connection")43 },44 }
Done
Using AI Code Generation
1import (2func main() {3 context := &context.Context{4 Input: &context.BeegoInput{},5 Output: &context.BeegoOutput{},6 }7 context.Input.Reset()8 context.Output.Reset()9 go func() {10 time.Sleep(time.Second * 2)11 context.Output.Done()12 }()13 context.Output.Wait()14 fmt.Println("Done")15}16import (17func main() {18 context := &context.Context{19 Input: &context.BeegoInput{},20 Output: &context.BeegoOutput{},21 }22 context.Input.Reset()23 context.Output.Reset()24 go func() {25 time.Sleep(time.Second * 2)26 context.Output.Done()27 }()28 context.Output.Wait()29 fmt.Println("Done")30}31import (32func main() {33 context := &context.Context{34 Input: &context.BeegoInput{},35 Output: &context.BeegoOutput{},36 }37 context.Input.Reset()38 context.Output.Reset()39 go func() {40 time.Sleep(time.Second * 2)41 context.Output.Done()42 }()43 context.Output.Wait()44 fmt.Println("Done")45}46import (47func main() {
Done
Using AI Code Generation
1import (2func main() {3 fmt.Println("Hello World!")4 ts := ×tamp.Timestamp{5 }6 data, err := proto.Marshal(ts)7 if err != nil {8 fmt.Println(err)9 }10 fmt.Println(data)11 if err != nil {12 fmt.Println(err)13 }14 client := &http.Client{}15 resp, err := client.Do(req)16 if err != nil {17 fmt.Println(err)18 }19 defer resp.Body.Close()20}21import (22func main() {23 fmt.Println("Hello World!")24 ts := ×tamp.Timestamp{25 }26 data, err := proto.Marshal(ts)27 if err != nil {28 fmt.Println(err)29 }30 fmt.Println(data)31 if err != nil {32 fmt.Println(err)33 }34 client := &http.Client{}35 resp, err := client.Do(req)36 if err != nil {37 fmt.Println(err)38 }39 defer resp.Body.Close()40 fmt.Println(resp)41 fmt.Println(resp.Body)42 fmt.Println(resp.Body.Close())43}44import (45func main() {46 fmt.Println("Hello World!")47 ts := ×tamp.Timestamp{48 }49 data, err := proto.Marshal(ts)
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!