2020-12-26 09:25:15 +00:00
|
|
|
package http
|
|
|
|
|
2020-12-28 14:32:26 +00:00
|
|
|
import (
|
2021-02-07 20:25:53 +00:00
|
|
|
"bytes"
|
2020-12-28 14:32:26 +00:00
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httputil"
|
|
|
|
"net/url"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2020-12-28 20:00:07 +00:00
|
|
|
"github.com/projectdiscovery/gologger"
|
2020-12-28 14:32:26 +00:00
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
2021-01-01 14:06:21 +00:00
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
2020-12-28 14:32:26 +00:00
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
|
2021-01-01 09:58:28 +00:00
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/tostring"
|
2021-01-16 06:36:27 +00:00
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/httpclientpool"
|
2020-12-28 14:32:26 +00:00
|
|
|
"github.com/projectdiscovery/rawhttp"
|
|
|
|
"github.com/remeh/sizedwaitgroup"
|
|
|
|
"go.uber.org/multierr"
|
|
|
|
)
|
|
|
|
|
|
|
|
const defaultMaxWorkers = 150
|
|
|
|
|
|
|
|
// executeRaceRequest executes race condition request for a URL
|
2021-02-26 07:43:11 +00:00
|
|
|
func (r *Request) executeRaceRequest(reqURL string, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
|
2021-02-04 16:30:09 +00:00
|
|
|
generator := r.newGenerator()
|
2020-12-26 09:25:15 +00:00
|
|
|
|
2021-02-04 16:30:09 +00:00
|
|
|
maxWorkers := r.RaceNumberRequests
|
2020-12-26 09:25:15 +00:00
|
|
|
swg := sizedwaitgroup.New(maxWorkers)
|
2020-12-28 14:32:26 +00:00
|
|
|
|
|
|
|
var requestErr error
|
2020-12-30 11:19:45 +00:00
|
|
|
mutex := &sync.Mutex{}
|
2020-12-26 09:25:15 +00:00
|
|
|
|
2021-01-11 19:19:26 +00:00
|
|
|
request, err := generator.Make(reqURL, nil)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-02-04 16:30:09 +00:00
|
|
|
for i := 0; i < r.RaceNumberRequests; i++ {
|
2020-12-28 14:32:26 +00:00
|
|
|
swg.Add()
|
|
|
|
go func(httpRequest *generatedRequest) {
|
2021-02-26 07:43:11 +00:00
|
|
|
err := r.executeRequest(reqURL, httpRequest, previous, callback)
|
2020-12-28 14:32:26 +00:00
|
|
|
mutex.Lock()
|
2020-12-26 09:25:15 +00:00
|
|
|
if err != nil {
|
2020-12-28 14:32:26 +00:00
|
|
|
requestErr = multierr.Append(requestErr, err)
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
2020-12-28 14:32:26 +00:00
|
|
|
mutex.Unlock()
|
|
|
|
swg.Done()
|
2020-12-26 09:25:15 +00:00
|
|
|
}(request)
|
|
|
|
}
|
|
|
|
swg.Wait()
|
2021-01-01 14:06:21 +00:00
|
|
|
return requestErr
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
2021-02-04 16:30:09 +00:00
|
|
|
// executeRaceRequest executes parallel requests for a template
|
|
|
|
func (r *Request) executeParallelHTTP(reqURL string, dynamicValues, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
|
|
|
|
generator := r.newGenerator()
|
2020-12-26 09:25:15 +00:00
|
|
|
|
|
|
|
// Workers that keeps enqueuing new requests
|
2021-02-04 16:30:09 +00:00
|
|
|
maxWorkers := r.Threads
|
2020-12-26 09:25:15 +00:00
|
|
|
swg := sizedwaitgroup.New(maxWorkers)
|
2020-12-28 14:32:26 +00:00
|
|
|
|
|
|
|
var requestErr error
|
2020-12-30 11:19:45 +00:00
|
|
|
mutex := &sync.Mutex{}
|
2020-12-28 14:32:26 +00:00
|
|
|
for {
|
|
|
|
request, err := generator.Make(reqURL, dynamicValues)
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if err != nil {
|
2021-02-04 16:30:09 +00:00
|
|
|
r.options.Progress.DecrementRequests(int64(generator.Total()))
|
2021-01-01 14:06:21 +00:00
|
|
|
return err
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
2020-12-28 14:32:26 +00:00
|
|
|
swg.Add()
|
|
|
|
go func(httpRequest *generatedRequest) {
|
|
|
|
defer swg.Done()
|
|
|
|
|
2021-02-04 16:30:09 +00:00
|
|
|
r.options.RateLimiter.Take()
|
2021-02-26 07:43:11 +00:00
|
|
|
err := r.executeRequest(reqURL, httpRequest, previous, callback)
|
2020-12-28 14:32:26 +00:00
|
|
|
mutex.Lock()
|
|
|
|
if err != nil {
|
|
|
|
requestErr = multierr.Append(requestErr, err)
|
|
|
|
}
|
|
|
|
mutex.Unlock()
|
|
|
|
}(request)
|
2021-02-04 16:30:09 +00:00
|
|
|
r.options.Progress.IncrementRequests()
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
swg.Wait()
|
2021-01-01 14:06:21 +00:00
|
|
|
return requestErr
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
2021-02-04 16:30:09 +00:00
|
|
|
// executeRaceRequest executes turbo http request for a URL
|
|
|
|
func (r *Request) executeTurboHTTP(reqURL string, dynamicValues, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
|
|
|
|
generator := r.newGenerator()
|
2020-12-26 09:25:15 +00:00
|
|
|
|
|
|
|
// need to extract the target from the url
|
|
|
|
URL, err := url.Parse(reqURL)
|
|
|
|
if err != nil {
|
2021-01-01 14:06:21 +00:00
|
|
|
return err
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pipeOptions := rawhttp.DefaultPipelineOptions
|
|
|
|
pipeOptions.Host = URL.Host
|
|
|
|
pipeOptions.MaxConnections = 1
|
2021-02-04 16:30:09 +00:00
|
|
|
if r.PipelineConcurrentConnections > 0 {
|
|
|
|
pipeOptions.MaxConnections = r.PipelineConcurrentConnections
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
2021-02-04 16:30:09 +00:00
|
|
|
if r.PipelineRequestsPerConnection > 0 {
|
|
|
|
pipeOptions.MaxPendingRequests = r.PipelineRequestsPerConnection
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
pipeclient := rawhttp.NewPipelineClient(pipeOptions)
|
|
|
|
|
|
|
|
// defaultMaxWorkers should be a sufficient value to keep queues always full
|
|
|
|
maxWorkers := defaultMaxWorkers
|
|
|
|
// in case the queue is bigger increase the workers
|
|
|
|
if pipeOptions.MaxPendingRequests > maxWorkers {
|
|
|
|
maxWorkers = pipeOptions.MaxPendingRequests
|
|
|
|
}
|
|
|
|
swg := sizedwaitgroup.New(maxWorkers)
|
2020-12-28 14:32:26 +00:00
|
|
|
|
|
|
|
var requestErr error
|
2020-12-30 11:19:45 +00:00
|
|
|
mutex := &sync.Mutex{}
|
2020-12-28 14:32:26 +00:00
|
|
|
for {
|
|
|
|
request, err := generator.Make(reqURL, dynamicValues)
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
2020-12-28 14:32:26 +00:00
|
|
|
if err != nil {
|
2021-02-04 16:30:09 +00:00
|
|
|
r.options.Progress.DecrementRequests(int64(generator.Total()))
|
2021-01-01 14:06:21 +00:00
|
|
|
return err
|
2020-12-28 14:32:26 +00:00
|
|
|
}
|
|
|
|
request.pipelinedClient = pipeclient
|
|
|
|
|
|
|
|
swg.Add()
|
|
|
|
go func(httpRequest *generatedRequest) {
|
|
|
|
defer swg.Done()
|
2020-12-26 09:25:15 +00:00
|
|
|
|
2021-02-26 07:43:11 +00:00
|
|
|
err := r.executeRequest(reqURL, httpRequest, previous, callback)
|
2020-12-28 14:32:26 +00:00
|
|
|
mutex.Lock()
|
|
|
|
if err != nil {
|
|
|
|
requestErr = multierr.Append(requestErr, err)
|
|
|
|
}
|
|
|
|
mutex.Unlock()
|
|
|
|
}(request)
|
2021-02-04 16:30:09 +00:00
|
|
|
r.options.Progress.IncrementRequests()
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
swg.Wait()
|
2021-01-01 14:06:21 +00:00
|
|
|
return requestErr
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
2020-12-29 06:12:46 +00:00
|
|
|
// ExecuteWithResults executes the final request on a URL
|
2021-01-16 08:40:24 +00:00
|
|
|
func (r *Request) ExecuteWithResults(reqURL string, dynamicValues, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
|
2020-12-26 09:25:15 +00:00
|
|
|
// verify if pipeline was requested
|
2020-12-30 15:44:04 +00:00
|
|
|
if r.Pipeline {
|
2021-01-16 08:40:24 +00:00
|
|
|
return r.executeTurboHTTP(reqURL, dynamicValues, previous, callback)
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// verify if a basic race condition was requested
|
2020-12-30 15:44:04 +00:00
|
|
|
if r.Race && r.RaceNumberRequests > 0 {
|
2021-02-26 07:43:11 +00:00
|
|
|
return r.executeRaceRequest(reqURL, previous, callback)
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// verify if parallel elaboration was requested
|
2020-12-30 15:44:04 +00:00
|
|
|
if r.Threads > 0 {
|
2021-01-16 08:40:24 +00:00
|
|
|
return r.executeParallelHTTP(reqURL, dynamicValues, previous, callback)
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
2020-12-30 15:44:04 +00:00
|
|
|
generator := r.newGenerator()
|
2020-12-26 09:25:15 +00:00
|
|
|
|
2020-12-28 14:32:26 +00:00
|
|
|
var requestErr error
|
|
|
|
for {
|
|
|
|
request, err := generator.Make(reqURL, dynamicValues)
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if err != nil {
|
2020-12-30 15:44:04 +00:00
|
|
|
r.options.Progress.DecrementRequests(int64(generator.Total()))
|
2021-01-01 14:06:21 +00:00
|
|
|
return err
|
2020-12-28 14:32:26 +00:00
|
|
|
}
|
2020-12-26 09:25:15 +00:00
|
|
|
|
2021-01-01 14:06:21 +00:00
|
|
|
var gotOutput bool
|
2020-12-30 15:44:04 +00:00
|
|
|
r.options.RateLimiter.Take()
|
2021-02-26 07:43:11 +00:00
|
|
|
err = r.executeRequest(reqURL, request, previous, func(event *output.InternalWrappedEvent) {
|
2021-01-01 11:22:41 +00:00
|
|
|
// Add the extracts to the dynamic values if any.
|
2021-01-01 14:06:21 +00:00
|
|
|
if event.OperatorsResult != nil {
|
|
|
|
gotOutput = true
|
|
|
|
dynamicValues = generators.MergeMaps(dynamicValues, event.OperatorsResult.DynamicValues)
|
2021-01-01 11:22:41 +00:00
|
|
|
}
|
2021-01-01 14:06:21 +00:00
|
|
|
callback(event)
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
requestErr = multierr.Append(requestErr, err)
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
2020-12-30 15:44:04 +00:00
|
|
|
r.options.Progress.IncrementRequests()
|
2020-12-26 09:25:15 +00:00
|
|
|
|
2021-01-01 14:06:21 +00:00
|
|
|
if request.original.options.Options.StopAtFirstMatch && gotOutput {
|
2020-12-30 15:44:04 +00:00
|
|
|
r.options.Progress.DecrementRequests(int64(generator.Total()))
|
2020-12-26 09:25:15 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2021-01-01 14:06:21 +00:00
|
|
|
return requestErr
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
2021-02-04 16:39:32 +00:00
|
|
|
const drainReqSize = int64(8 * 1024)
|
|
|
|
|
2021-02-26 07:43:11 +00:00
|
|
|
// executeRequest executes the actual generated request and returns error if occurred
|
|
|
|
func (r *Request) executeRequest(reqURL string, request *generatedRequest, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
|
2020-12-30 15:44:04 +00:00
|
|
|
r.setCustomHeaders(request)
|
2020-12-26 09:25:15 +00:00
|
|
|
|
|
|
|
var (
|
2021-02-25 01:08:10 +00:00
|
|
|
resp *http.Response
|
|
|
|
fromcache bool
|
|
|
|
dumpedRequest []byte
|
|
|
|
err error
|
2020-12-26 09:25:15 +00:00
|
|
|
)
|
2021-02-07 20:13:51 +00:00
|
|
|
|
2021-02-25 01:08:10 +00:00
|
|
|
// For race conditions we can't dump the request body at this point as it's already waiting the open-gate event
|
|
|
|
if !request.original.Race {
|
|
|
|
dumpedRequest, err = dump(request, reqURL)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.options.Options.Debug || r.options.Options.DebugRequests {
|
|
|
|
gologger.Info().Msgf("[%s] Dumped HTTP request for %s\n\n", r.options.TemplateID, reqURL)
|
|
|
|
gologger.Print().Msgf("%s", string(dumpedRequest))
|
|
|
|
}
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
2021-01-11 14:29:12 +00:00
|
|
|
var formedURL string
|
2021-01-16 06:36:27 +00:00
|
|
|
var hostname string
|
2020-12-26 09:25:15 +00:00
|
|
|
timeStart := time.Now()
|
2020-12-28 14:32:26 +00:00
|
|
|
if request.original.Pipeline {
|
2021-01-11 14:29:12 +00:00
|
|
|
formedURL = request.rawRequest.FullURL
|
2021-02-26 07:43:11 +00:00
|
|
|
if parsed, parseErr := url.Parse(formedURL); parseErr == nil {
|
|
|
|
hostname = parsed.Host
|
2021-01-16 06:36:27 +00:00
|
|
|
}
|
2020-12-28 20:00:07 +00:00
|
|
|
resp, err = request.pipelinedClient.DoRaw(request.rawRequest.Method, reqURL, request.rawRequest.Path, generators.ExpandMapValues(request.rawRequest.Headers), ioutil.NopCloser(strings.NewReader(request.rawRequest.Data)))
|
2021-02-08 10:37:16 +00:00
|
|
|
} else if request.original.Unsafe && request.rawRequest != nil {
|
2021-01-11 14:29:12 +00:00
|
|
|
formedURL = request.rawRequest.FullURL
|
2021-02-26 07:43:11 +00:00
|
|
|
if parsed, parseErr := url.Parse(formedURL); parseErr == nil {
|
|
|
|
hostname = parsed.Host
|
2021-01-16 06:36:27 +00:00
|
|
|
}
|
2020-12-28 20:00:07 +00:00
|
|
|
options := request.original.rawhttpClient.Options
|
2020-12-30 15:44:04 +00:00
|
|
|
options.FollowRedirects = r.Redirects
|
2021-02-26 07:43:11 +00:00
|
|
|
options.CustomRawBytes = request.rawRequest.UnsafeRawBytes
|
2020-12-28 20:00:07 +00:00
|
|
|
resp, err = request.original.rawhttpClient.DoRawWithOptions(request.rawRequest.Method, reqURL, request.rawRequest.Path, generators.ExpandMapValues(request.rawRequest.Headers), ioutil.NopCloser(strings.NewReader(request.rawRequest.Data)), options)
|
2020-12-26 09:25:15 +00:00
|
|
|
} else {
|
2021-02-26 07:43:11 +00:00
|
|
|
hostname = request.request.URL.Host
|
2021-01-11 14:29:12 +00:00
|
|
|
formedURL = request.request.URL.String()
|
2020-12-26 09:25:15 +00:00
|
|
|
// if nuclei-project is available check if the request was already sent previously
|
2020-12-30 15:44:04 +00:00
|
|
|
if r.options.ProjectFile != nil {
|
2020-12-26 09:25:15 +00:00
|
|
|
// if unavailable fail silently
|
|
|
|
fromcache = true
|
2020-12-30 15:44:04 +00:00
|
|
|
resp, err = r.options.ProjectFile.Get(dumpedRequest)
|
2020-12-26 09:25:15 +00:00
|
|
|
if err != nil {
|
|
|
|
fromcache = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if resp == nil {
|
2020-12-30 15:44:04 +00:00
|
|
|
resp, err = r.httpClient.Do(request.request)
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
}
|
2021-02-08 10:37:16 +00:00
|
|
|
if resp == nil {
|
|
|
|
err = errors.New("no response got for request")
|
|
|
|
}
|
2020-12-28 20:00:07 +00:00
|
|
|
if err != nil {
|
2021-01-11 20:35:41 +00:00
|
|
|
// rawhttp doesn't supports draining response bodies.
|
|
|
|
if resp != nil && resp.Body != nil && request.rawRequest == nil {
|
2021-02-06 22:04:07 +00:00
|
|
|
_, _ = io.CopyN(ioutil.Discard, resp.Body, drainReqSize)
|
2020-12-28 20:00:07 +00:00
|
|
|
resp.Body.Close()
|
|
|
|
}
|
2020-12-30 15:44:04 +00:00
|
|
|
r.options.Output.Request(r.options.TemplateID, reqURL, "http", err)
|
|
|
|
r.options.Progress.DecrementRequests(1)
|
2021-01-01 14:06:21 +00:00
|
|
|
return err
|
2020-12-28 20:00:07 +00:00
|
|
|
}
|
2021-02-26 07:43:11 +00:00
|
|
|
defer func() {
|
|
|
|
_, _ = io.CopyN(ioutil.Discard, resp.Body, drainReqSize)
|
|
|
|
resp.Body.Close()
|
|
|
|
}()
|
2021-02-05 07:06:01 +00:00
|
|
|
|
2021-01-11 14:29:12 +00:00
|
|
|
gologger.Verbose().Msgf("[%s] Sent HTTP request to %s", r.options.TemplateID, formedURL)
|
2020-12-30 15:44:04 +00:00
|
|
|
r.options.Output.Request(r.options.TemplateID, reqURL, "http", err)
|
2020-12-26 09:25:15 +00:00
|
|
|
|
|
|
|
duration := time.Since(timeStart)
|
2021-02-05 07:06:01 +00:00
|
|
|
|
2021-02-07 20:25:53 +00:00
|
|
|
dumpedResponseHeaders, err := httputil.DumpResponse(resp, false)
|
2021-02-05 07:06:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "could not dump http response")
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
2021-02-04 16:39:32 +00:00
|
|
|
var bodyReader io.Reader
|
|
|
|
if r.MaxSize != 0 {
|
|
|
|
bodyReader = io.LimitReader(resp.Body, int64(r.MaxSize))
|
|
|
|
} else {
|
|
|
|
bodyReader = resp.Body
|
|
|
|
}
|
|
|
|
data, err := ioutil.ReadAll(bodyReader)
|
2020-12-26 09:25:15 +00:00
|
|
|
if err != nil {
|
2021-01-01 14:06:21 +00:00
|
|
|
return errors.Wrap(err, "could not read http body")
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
resp.Body.Close()
|
|
|
|
|
2021-02-06 22:04:07 +00:00
|
|
|
redirectedResponse, err := dumpResponseWithRedirectChain(resp, data)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "could not read http response with redirect chain")
|
|
|
|
}
|
|
|
|
|
2020-12-28 20:00:07 +00:00
|
|
|
// net/http doesn't automatically decompress the response body if an
|
|
|
|
// encoding has been specified by the user in the request so in case we have to
|
|
|
|
// manually do it.
|
2021-02-07 20:25:53 +00:00
|
|
|
dataOrig := data
|
2021-02-08 10:43:55 +00:00
|
|
|
data, _ = handleDecompression(resp, data)
|
2020-12-26 09:25:15 +00:00
|
|
|
|
|
|
|
// Dump response - step 2 - replace gzip body with deflated one or with itself (NOP operation)
|
2021-02-07 20:25:53 +00:00
|
|
|
dumpedResponseBuilder := &bytes.Buffer{}
|
|
|
|
dumpedResponseBuilder.Write(dumpedResponseHeaders)
|
|
|
|
dumpedResponseBuilder.Write(data)
|
|
|
|
dumpedResponse := dumpedResponseBuilder.Bytes()
|
|
|
|
redirectedResponse = bytes.ReplaceAll(redirectedResponse, dataOrig, data)
|
2021-02-06 22:04:07 +00:00
|
|
|
|
2021-02-07 20:25:53 +00:00
|
|
|
// Dump response - step 2 - replace gzip body with deflated one or with itself (NOP operation)
|
|
|
|
if r.options.Options.Debug || r.options.Options.DebugResponse {
|
2021-01-11 14:29:12 +00:00
|
|
|
gologger.Info().Msgf("[%s] Dumped HTTP response for %s\n\n", r.options.TemplateID, formedURL)
|
2021-02-06 22:04:07 +00:00
|
|
|
gologger.Print().Msgf("%s", string(redirectedResponse))
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// if nuclei-project is enabled store the response if not previously done
|
2020-12-30 15:44:04 +00:00
|
|
|
if r.options.ProjectFile != nil && !fromcache {
|
|
|
|
err := r.options.ProjectFile.Set(dumpedRequest, resp, data)
|
2020-12-26 09:25:15 +00:00
|
|
|
if err != nil {
|
2021-01-01 14:06:21 +00:00
|
|
|
return errors.Wrap(err, "could not store in project file")
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-25 07:07:47 +00:00
|
|
|
matchedURL := reqURL
|
|
|
|
if request.rawRequest != nil && request.rawRequest.FullURL != "" {
|
2020-12-29 06:12:46 +00:00
|
|
|
matchedURL = request.rawRequest.FullURL
|
|
|
|
}
|
|
|
|
if request.request != nil {
|
|
|
|
matchedURL = request.request.URL.String()
|
|
|
|
}
|
2021-01-16 06:36:27 +00:00
|
|
|
outputEvent := r.responseToDSLMap(resp, reqURL, matchedURL, tostring.UnsafeToString(dumpedRequest), tostring.UnsafeToString(dumpedResponse), tostring.UnsafeToString(data), headersToString(resp.Header), duration, request.meta)
|
|
|
|
outputEvent["ip"] = httpclientpool.Dialer.GetDialedIP(hostname)
|
2021-02-06 22:04:07 +00:00
|
|
|
outputEvent["redirect-chain"] = tostring.UnsafeToString(redirectedResponse)
|
2021-01-16 08:40:24 +00:00
|
|
|
for k, v := range previous {
|
|
|
|
outputEvent[k] = v
|
|
|
|
}
|
2020-12-28 20:00:07 +00:00
|
|
|
|
2021-01-16 06:36:27 +00:00
|
|
|
event := &output.InternalWrappedEvent{InternalEvent: outputEvent}
|
2020-12-30 15:44:04 +00:00
|
|
|
if r.CompiledOperators != nil {
|
2021-01-17 06:56:45 +00:00
|
|
|
var ok bool
|
|
|
|
event.OperatorsResult, ok = r.CompiledOperators.Execute(outputEvent, r.Match, r.Extract)
|
|
|
|
if ok && event.OperatorsResult != nil {
|
|
|
|
event.OperatorsResult.PayloadValues = request.meta
|
2021-01-13 06:48:56 +00:00
|
|
|
event.Results = r.MakeResultEvent(event)
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
}
|
2021-01-13 06:48:56 +00:00
|
|
|
callback(event)
|
2021-01-01 14:06:21 +00:00
|
|
|
return nil
|
2020-12-28 20:00:07 +00:00
|
|
|
}
|
2020-12-26 09:25:15 +00:00
|
|
|
|
2020-12-28 20:00:07 +00:00
|
|
|
// setCustomHeaders sets the custom headers for generated request
|
2021-02-04 16:30:09 +00:00
|
|
|
func (r *Request) setCustomHeaders(req *generatedRequest) {
|
|
|
|
for k, v := range r.customHeaders {
|
|
|
|
if req.rawRequest != nil {
|
|
|
|
req.rawRequest.Headers[k] = v
|
2020-12-28 20:00:07 +00:00
|
|
|
} else {
|
2021-02-04 16:30:09 +00:00
|
|
|
req.request.Header.Set(strings.TrimSpace(k), strings.TrimSpace(v))
|
2020-12-28 20:00:07 +00:00
|
|
|
}
|
2020-12-26 09:25:15 +00:00
|
|
|
}
|
|
|
|
}
|