func (r Request) AbsoluteURL(src string) string {
	if strings.HasPrefix(src, "#") {
		return ""
	}
	u, err := url.Parse(r.URL)
	if err != nil {
		return ""
	}
	absoluteURL, err := u.Parse(src)
	if err != nil {
		return ""
	}
	absoluteURL.Fragment = ""
	if absoluteURL.Scheme == "//" {
		absoluteURL.Scheme = u.Scheme
	}
	return absoluteURL.String()
}
AbsoluteURL returns with the resolved absolute URL of an URL chunk.
AbsoluteURL returns empty string if the URL chunk is a fragment or
could not be parsed
package predator
import (
	"bytes"
	"crypto/sha1"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"sync/atomic"
	pctx "github.com/thep0y/predator/context"
	"github.com/thep0y/predator/json"
	"github.com/valyala/fasthttp"
)
type Request struct {
	URL string
	Method string
	Headers *fasthttp.RequestHeader
	Ctx pctx.Context
	Body []byte
	cachedMap map[string]string
	ID uint32
	abort bool
	crawler *Crawler
	retryCounter uint32
	maxRedirectsCount uint
}
func (r *Request) New(method, URL string, body []byte) *Request {
	return &Request{
		Method:  method,
		URL:     URL,
		Body:    body,
		Ctx:     r.Ctx,
		Headers: &fasthttp.RequestHeader{},
		ID:      atomic.AddUint32(&r.crawler.requestCount, 1),
		crawler: r.crawler,
	}
}
func (r *Request) Abort() {
	r.abort = true
}
func (r *Request) SetContentType(contentType string) {
	r.Headers.Set("Content-Type", contentType)
}
func (r *Request) AllowRedirect(maxRedirectsCount uint) {
	r.maxRedirectsCount = maxRedirectsCount
}
func (r *Request) SetHeaders(headers map[string]string) {
	for k, v := range headers {
		r.Headers.Set(k, v)
	}
}
func (r Request) NumberOfRetries() uint32 {
	return r.retryCounter
}
func (r Request) Get(u string) error {
	return r.crawler.Get(u)
}
func (r Request) Post(URL string, requestData map[string]string, ctx pctx.Context) error {
	return r.crawler.Post(URL, requestData, ctx)
}