github.com/projectdiscovery/nuclei/v2@v2.9.15/pkg/protocols/headless/engine/instance.go (about) 1 package engine 2 3 import ( 4 "context" 5 "errors" 6 "time" 7 8 "github.com/go-rod/rod" 9 "github.com/go-rod/rod/lib/utils" 10 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/interactsh" 11 ) 12 13 // Instance is an isolated browser instance opened for doing operations with it. 14 type Instance struct { 15 browser *Browser 16 engine *rod.Browser 17 18 // redundant due to dependency cycle 19 interactsh *interactsh.Client 20 requestLog map[string]string // contains actual request that was sent 21 } 22 23 // NewInstance creates a new instance for the current browser. 24 // 25 // The login process is repeated only once for a browser, and the created 26 // isolated browser instance is used for entire navigation one by one. 27 // 28 // Users can also choose to run the login->actions process again 29 // which uses a new incognito browser instance to run actions. 30 func (b *Browser) NewInstance() (*Instance, error) { 31 browser, err := b.engine.Incognito() 32 if err != nil { 33 return nil, err 34 } 35 36 // We use a custom sleeper that sleeps from 100ms to 500 ms waiting 37 // for an interaction. Used throughout rod for clicking, etc. 38 browser = browser.Sleeper(func() utils.Sleeper { return maxBackoffSleeper(10) }) 39 return &Instance{browser: b, engine: browser, requestLog: map[string]string{}}, nil 40 } 41 42 // returns a map of [template-defined-urls] -> [actual-request-sent] 43 // Note: this does not include CORS or other requests while rendering that were not explicitly 44 // specified in template 45 func (i *Instance) GetRequestLog() map[string]string { 46 return i.requestLog 47 } 48 49 // Close closes all the tabs and pages for a browser instance 50 func (i *Instance) Close() error { 51 return i.engine.Close() 52 } 53 54 // SetInteractsh client 55 func (i *Instance) SetInteractsh(interactsh *interactsh.Client) { 56 i.interactsh = interactsh 57 } 58 59 // maxBackoffSleeper is a backoff sleeper respecting max backoff values 60 func maxBackoffSleeper(max int) utils.Sleeper { 61 count := 0 62 backoffSleeper := utils.BackoffSleeper(100*time.Millisecond, 500*time.Millisecond, nil) 63 64 return func(ctx context.Context) error { 65 if ctx.Err() != nil { 66 return ctx.Err() 67 } 68 if count == max { 69 return errors.New("max sleep count") 70 } 71 count++ 72 return backoffSleeper(ctx) 73 } 74 }