func NewProxyAuthTransport(rawTransport *http.Transport, customHeaders http.Header) (*ProxyAuthTransport, error) {
	dialFn := rawTransport.Dial
	if dialFn == nil {
		dialFn = net.Dial
	}
	tr := &ProxyAuthTransport{Dial: dialFn, CustomHeaders: customHeaders}
	proxyUrlFn := rawTransport.Proxy
	if proxyUrlFn != nil {
		wrappedDialFn := tr.wrapTransportDial()
		rawTransport.Dial = wrappedDialFn
		proxyUrl, err := proxyUrlFn(nil)
		if err != nil {
			return nil, err
		}
		if proxyUrl.Scheme != "http" {
			return nil, fmt.Errorf("Only HTTP proxy supported, for SOCKS use http.Transport with custom dialers & upstreamproxy.NewProxyDialFunc")
		}
		if proxyUrl.User != nil {
			tr.Username = proxyUrl.User.Username()
			tr.Password, _ = proxyUrl.User.Password()
		}
		// strip username and password from the proxyURL because
		// we do not want the wrapped transport to handle authentication
		proxyUrl.User = nil
		rawTransport.Proxy = http.ProxyURL(proxyUrl)
	}

	tr.Transport = rawTransport
	return tr, nil
}
Example #2
0
func (auth *Auth) NewClient() *http.Client {
	var client *http.Client
	var transport *http.Transport
	if auth.Settings["insecure"] != "" || auth.Settings["proxy_host"] != "" {
		transport = &http.Transport{}
	}
	if auth.Settings["insecure"] != "" {
		//FIXME
		os.Setenv("HTTP_PROXY", "http://127.0.0.1:10004")
		os.Setenv("NO_PROXY", "")
		var config *tls.Config = &tls.Config{
			InsecureSkipVerify: true,
		}
		transport.TLSClientConfig = config
	}
	if auth.Settings["proxy_host"] != "" {
		turl, _ := url.Parse("http://" + auth.Settings["proxy_host"] + ":" + auth.Settings["proxy_port"])
		transport.Proxy = http.ProxyURL(turl)
	}
	if auth.Settings["insecure"] != "" || auth.Settings["proxy_host"] != "" {
		client = &http.Client{
			Jar:       auth.CookieJar,
			Transport: transport,
		}
	} else {
		client = &http.Client{
			Jar: auth.CookieJar,
		}
	}
	return client
}
Example #3
0
// ConfigureTransport configures the specified Transport according to the
// specified proto and addr.
// If the proto is unix (using a unix socket to communicate) or npipe the
// compression is disabled.
func ConfigureTransport(tr *http.Transport, proto, addr string) error {
	switch proto {
	case "unix":
		// No need for compression in local communications.
		tr.DisableCompression = true
		tr.Dial = func(_, _ string) (net.Conn, error) {
			return net.DialTimeout(proto, addr, defaultTimeout)
		}
	case "npipe":
		// No need for compression in local communications.
		tr.DisableCompression = true
		tr.Dial = func(_, _ string) (net.Conn, error) {
			return DialPipe(addr, defaultTimeout)
		}
	default:
		tr.Proxy = http.ProxyFromEnvironment
		dialer, err := DialerFromEnvironment(&net.Dialer{
			Timeout: defaultTimeout,
		})
		if err != nil {
			return err
		}
		tr.Dial = dialer.Dial
	}
	return nil
}
Example #4
0
// Creates a new HTTP connection pool using the given address and pool parameters.
//
// 'addr' is a net.Dial()-style 'host:port' destination for making the TCP connection for
// HTTP/HTTPS traffic.  It will be used as the hostname by default for virtual hosting
// and SSL certificate validation; if you'd like to use a different hostname,
// set params.HostHeader.
func NewSimplePool(addr string, params ConnectionParams) *SimplePool {
	pool := &SimplePool{
		addr:   addr,
		params: params,
		client: new(http.Client),
	}

	// setup HTTP transport
	transport := new(http.Transport)
	transport.ResponseHeaderTimeout = params.ResponseTimeout
	transport.MaxIdleConnsPerHost = params.MaxIdle
	transport.Proxy = http.ProxyFromEnvironment
	if params.Dial == nil {
		// dialTimeout could only be used in none proxy requests since it talks directly
		// to pool.addr
		if getenvEitherCase("HTTP_PROXY") == "" {
			transport.Dial = pool.dialTimeout
		}
	} else {
		transport.Dial = params.Dial
	}
	pool.transport = transport
	pool.client.Transport = transport

	if params.UseSSL && params.SkipVerifySSL {
		transport.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	return pool
}
Example #5
0
// Creates a new Infoblox client with the supplied user/pass configuration.
// Supports the use of HTTP proxies through the $HTTP_PROXY env var.
// For example:
//     export HTTP_PROXY=http://localhost:8888
//
// When using a proxy, disable TLS certificate verification with the following:
//    sslVerify = false
func NewClient(host, username, password string, sslVerify bool) *Client {
	var (
		req, _    = http.NewRequest("GET", host, nil)
		proxy, _  = http.ProxyFromEnvironment(req)
		transport *http.Transport
		tlsconfig *tls.Config
	)
	tlsconfig = &tls.Config{
		InsecureSkipVerify: !sslVerify,
	}
	if tlsconfig.InsecureSkipVerify {
		fmt.Println("WARNING: SSL cert verification  disabled!")
	}
	transport = &http.Transport{
		TLSClientConfig: tlsconfig,
	}
	if proxy != nil {
		transport.Proxy = http.ProxyURL(proxy)
	}
	return &Client{
		Host: host,
		HttpClient: &http.Client{
			Transport: transport,
		},
		Username: username,
		Password: password,
	}
}
Example #6
0
// Creates a new HTTP connection pool using the given address and pool parameters.
//
// 'addr' is a net.Dial()-style 'host:port' destination for making the TCP connection for
// HTTP/HTTPS traffic.  It will be used as the hostname by default for virtual hosting
// and SSL certificate validation; if you'd like to use a different hostname,
// set params.HostHeader.
func NewSimplePool(addr string, params ConnectionParams) *SimplePool {
	pool := &SimplePool{
		addr:   addr,
		params: params,
		client: new(http.Client),
	}

	// It's desirable to enforce the timeout at the client-level since it
	// includes the connection time, redirects and the time to finish reading
	// the full response. Unlike ResponseHeaderTimeout supported by
	// `http.Transport` which merely accounts for the timeout to receive the
	// first response header byte. It ignores the time to send the request or
	// the time to read the full response.
	pool.client.Timeout = params.ResponseTimeout

	// setup HTTP transport
	transport := new(http.Transport)
	transport.ResponseHeaderTimeout = params.ResponseTimeout
	transport.MaxIdleConnsPerHost = params.MaxIdle

	if params.Proxy != nil {
		transport.Proxy = params.Proxy
	} else {
		transport.Proxy = http.ProxyFromEnvironment
	}

	if params.Dial == nil {
		// dialTimeout could only be used in none proxy requests since it talks directly
		// to pool.addr
		if getenvEitherCase("HTTP_PROXY") == "" && params.Proxy == nil {
			transport.Dial = pool.dialTimeout
		}
	} else {
		transport.Dial = params.Dial
	}
	pool.transport = transport
	pool.client.Transport = transport

	if params.UseSSL && params.SkipVerifySSL {
		transport.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	return pool
}
Example #7
0
func NewClient(e *Env, config *ClientConfig, needCookie bool) *Client {
	var jar *cookiejar.Jar
	if needCookie && (config == nil || config.UseCookies) && e.GetTorMode().UseCookies() {
		jar, _ = cookiejar.New(nil)
	}

	var timeout time.Duration

	// from http.DefaultTransport;
	//
	// TODO: change this back (see comment below) to allow
	// shared Transport after we switch to go1.7
	xprt := http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).Dial,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	}

	// This disables HTTP/2. There's a bug introduced between (go1.6, go1.6.3]
	// that makes client.Get hang on certain HTTP/2 servers. See CORE-3441 for
	// details.
	//
	// TODO: remove this after the bug is fixed.
	xprt.TLSNextProto = make(
		map[string]func(authority string, c *tls.Conn) http.RoundTripper)

	if (config != nil && config.RootCAs != nil) || e.GetTorMode().Enabled() {
		if config != nil && config.RootCAs != nil {
			xprt.TLSClientConfig = &tls.Config{RootCAs: config.RootCAs}
		}
		if e.GetTorMode().Enabled() {
			dialSocksProxy := socks.DialSocksProxy(socks.SOCKS5, e.GetTorProxy())
			xprt.Dial = dialSocksProxy
		} else {
			xprt.Proxy = http.ProxyFromEnvironment
		}
	}
	if config == nil || config.Timeout == 0 {
		timeout = HTTPDefaultTimeout
	} else {
		timeout = config.Timeout
	}

	ret := &Client{
		cli:    &http.Client{Timeout: timeout},
		config: config,
	}
	if jar != nil {
		ret.cli.Jar = jar
	}
	ret.cli.Transport = &xprt
	return ret
}
Example #8
0
// SetTransportDefaults applies the defaults from http.DefaultTransport
// for the Proxy, Dial, and TLSHandshakeTimeout fields if unset
func SetTransportDefaults(t *http.Transport) *http.Transport {
	if t.Proxy == nil {
		t.Proxy = defaultTransport.Proxy
	}
	if t.Dial == nil {
		t.Dial = defaultTransport.Dial
	}
	if t.TLSHandshakeTimeout == 0 {
		t.TLSHandshakeTimeout = defaultTransport.TLSHandshakeTimeout
	}
	return t
}
Example #9
0
func newHttpClient(config *Config) *http.Client {
	transport := new(http.Transport)

	if defaultTransport, ok := http.DefaultTransport.(*http.Transport); ok {
		transport.Proxy = defaultTransport.Proxy
		transport.Dial = defaultTransport.Dial
		transport.TLSHandshakeTimeout = defaultTransport.TLSHandshakeTimeout
	}

	if config.ProxyHost != "" {
		host := config.ProxyHost

		if config.ProxyPort > 0 {
			host += ":" + strconv.Itoa(config.ProxyPort)
		}

		proxyUrl, err := url.Parse(util.HostToURL(host, "http"))

		if err != nil {
			panic(err)
		}

		transport.Proxy = http.ProxyURL(proxyUrl)
	}

	/*
		if c.ConnectionTimeout > 0 {
			transport.TLSHandshakeTimeout = c.ConnectionTimeout
		}
	*/

	if config.MaxConnections > 0 {
		transport.MaxIdleConnsPerHost = config.MaxConnections
	}

	return &http.Client{
		Transport: transport,
		Timeout:   config.Timeout,
	}
}
Example #10
0
// SetOldTransportDefaults applies the defaults from http.DefaultTransport
// for the Proxy, Dial, and TLSHandshakeTimeout fields if unset
func SetOldTransportDefaults(t *http.Transport) *http.Transport {
	if t.Proxy == nil || isDefault(t.Proxy) {
		// http.ProxyFromEnvironment doesn't respect CIDRs and that makes it impossible to exclude things like pod and service IPs from proxy settings
		// ProxierWithNoProxyCIDR allows CIDR rules in NO_PROXY
		t.Proxy = NewProxierWithNoProxyCIDR(http.ProxyFromEnvironment)
	}
	if t.Dial == nil {
		t.Dial = defaultTransport.Dial
	}
	if t.TLSHandshakeTimeout == 0 {
		t.TLSHandshakeTimeout = defaultTransport.TLSHandshakeTimeout
	}
	return t
}
Example #11
0
// ConfigureTCPTransport configures the specified Transport according to the
// specified proto and addr.
// If the proto is unix (using a unix socket to communicate) the compression
// is disabled.
func ConfigureTCPTransport(tr *http.Transport, proto, addr string) {
	// Why 32? See https://github.com/docker/docker/pull/8035.
	timeout := 32 * time.Second
	if proto == "unix" {
		// No need for compression in local communications.
		tr.DisableCompression = true
		tr.Dial = func(_, _ string) (net.Conn, error) {
			return net.DialTimeout(proto, addr, timeout)
		}
	} else {
		tr.Proxy = http.ProxyFromEnvironment
		tr.Dial = (&net.Dialer{Timeout: timeout}).Dial
	}
}
Example #12
0
func configureTransport(tr *http.Transport, proto, addr string) *http.Transport {
	if tr == nil {
		tr = &http.Transport{}
	}

	if proto == "unix" {
		// No need for compression in local communications.
		tr.DisableCompression = true
		tr.Dial = func(_, _ string) (net.Conn, error) {
			return net.Dial(proto, addr)
		}
	} else {
		tr.Proxy = http.ProxyFromEnvironment
		tr.Dial = (&net.Dialer{}).Dial
	}

	return tr
}
Example #13
0
// Do an HTTP roundtrip using the payload data in buf and the request metadata
// in info.
func roundTripWithHTTP(buf []byte, info *RequestInfo) (*http.Response, error) {
	tr := new(http.Transport)
	if info.ProxyURL != nil {
		if info.ProxyURL.Scheme != "http" {
			panic(fmt.Sprintf("don't know how to use proxy %s", info.ProxyURL.String()))
		}
		tr.Proxy = http.ProxyURL(info.ProxyURL)
	}
	req, err := http.NewRequest("POST", info.URL.String(), bytes.NewReader(buf))
	if err != nil {
		return nil, err
	}
	if info.Host != "" {
		req.Host = info.Host
	}
	req.Header.Set("X-Session-Id", info.SessionID)
	return tr.RoundTrip(req)
}
Example #14
0
// ConfigureTransport configures the specified Transport according to the
// specified proto and addr.
// If the proto is unix (using a unix socket to communicate) or npipe the
// compression is disabled.
func ConfigureTransport(tr *http.Transport, proto, addr string) error {
	switch proto {
	case "unix":
		return configureUnixTransport(tr, proto, addr)
	case "npipe":
		return configureNpipeTransport(tr, proto, addr)
	default:
		tr.Proxy = http.ProxyFromEnvironment
		dialer, err := DialerFromEnvironment(&net.Dialer{
			Timeout: defaultTimeout,
		})
		if err != nil {
			return err
		}
		tr.Dial = dialer.Dial
	}
	return nil
}
Example #15
0
// defaultTransport creates a new http.Transport with Docker's
// default transport configuration.
func defaultTransport(proto, addr string) *http.Transport {
	tr := new(http.Transport)

	// Why 32? See https://github.com/docker/docker/pull/8035.
	timeout := 32 * time.Second
	if proto == "unix" {
		// No need for compression in local communications.
		tr.DisableCompression = true
		tr.Dial = func(_, _ string) (net.Conn, error) {
			return net.DialTimeout(proto, addr, timeout)
		}
	} else if proto == "npipe" {
		tr.Dial = func(_, _ string) (net.Conn, error) {
			return DialPipe(addr, timeout)
		}
	} else {
		tr.Proxy = http.ProxyFromEnvironment
		tr.Dial = (&net.Dialer{Timeout: timeout}).Dial
	}

	return tr
}
Example #16
0
// Creates a new Infoblox client with the supplied user/pass configuration.
// Supports the use of HTTP proxies through the $HTTP_PROXY env var.
// For example:
//     export HTTP_PROXY=http://localhost:8888
//
// When using a proxy, disable TLS certificate verification with the following:
//    sslVerify = false
//
// To save and re-use infoblox session cookies, set useCookies = true
// NOTE: The infoblox cookie uses a comma separated string, and requires golang 1.3+ to be correctly stored.
//
func NewClient(host, username, password string, sslVerify, useCookies bool) *Client {
	var (
		req, _    = http.NewRequest("GET", host, nil)
		proxy, _  = http.ProxyFromEnvironment(req)
		transport *http.Transport
		tlsconfig *tls.Config
	)
	tlsconfig = &tls.Config{
		InsecureSkipVerify: !sslVerify,
	}
	if tlsconfig.InsecureSkipVerify {
		log.Printf("WARNING: SSL cert verification  disabled\n")
	}
	transport = &http.Transport{
		TLSClientConfig: tlsconfig,
	}
	if proxy != nil {
		transport.Proxy = http.ProxyURL(proxy)
	}

	client := &Client{
		Host: host,
		HttpClient: &http.Client{
			Transport: transport,
		},
		Username:   username,
		Password:   password,
		UseCookies: useCookies,
	}
	if useCookies {
		options := cookiejar.Options{
			PublicSuffixList: publicsuffix.List,
		}
		jar, _ := cookiejar.New(&options)
		client.HttpClient.Jar = jar
	}
	return client

}
Example #17
0
func NewClient(e *Env, config *ClientConfig, needCookie bool) *Client {
	var jar *cookiejar.Jar
	if needCookie && (config == nil || config.UseCookies) && e.GetTorMode().UseCookies() {
		jar, _ = cookiejar.New(nil)
	}

	var xprt *http.Transport
	var timeout time.Duration

	if (config != nil && config.RootCAs != nil) || e.GetTorMode().Enabled() {
		xprt = &http.Transport{}
		if config != nil && config.RootCAs != nil {
			xprt.TLSClientConfig = &tls.Config{RootCAs: config.RootCAs}
		}
		if e.GetTorMode().Enabled() {
			dialSocksProxy := socks.DialSocksProxy(socks.SOCKS5, e.GetTorProxy())
			xprt.Dial = dialSocksProxy
		} else {
			xprt.Proxy = http.ProxyFromEnvironment
		}
	}
	if config == nil || config.Timeout == 0 {
		timeout = HTTPDefaultTimeout
	} else {
		timeout = config.Timeout
	}

	ret := &Client{
		cli:    &http.Client{Timeout: timeout},
		config: config,
	}
	if jar != nil {
		ret.cli.Jar = jar
	}
	if xprt != nil {
		ret.cli.Transport = xprt
	}
	return ret
}
Example #18
0
// ConfigureTransport configures the http client transport (ssl, proxy)
func ConfigureTransport(insecure bool, clientCertFile string, clientKeyFile string, caCerts ...string) (*http.Transport, error) {
	Log.Debug("configure transport",
		"insecure", insecure,
		"clientCertFile", clientCertFile,
		"clientKeyFile", clientKeyFile,
		"cacerts", strings.Join(caCerts, ","),
	)
	transport := new(http.Transport)
	tlsConfig := &tls.Config{InsecureSkipVerify: insecure}
	if len(clientCertFile) != 0 && len(clientKeyFile) != 0 {
		clientCert, err := tls.LoadX509KeyPair(clientCertFile, clientKeyFile)
		if err != nil {
			return nil, err
		}
		tlsConfig.Certificates = []tls.Certificate{clientCert}
	}
	if len(caCerts) > 0 {
		caCertPool := x509.NewCertPool()
		for _, cert := range caCerts {
			if len(cert) == 0 {
				continue
			}
			caCert, err := ioutil.ReadFile(cert)
			if err != nil {
				return nil, err
			}
			caCertPool.AppendCertsFromPEM(caCert)
		}
		tlsConfig.RootCAs = caCertPool
	}
	tlsConfig.BuildNameToCertificate()
	transport.TLSClientConfig = tlsConfig
	proxyURL, err := url.Parse(os.Getenv("http_proxy"))
	if err == nil {
		transport.Proxy = http.ProxyURL(proxyURL)
	}
	return transport, nil
}
Example #19
0
// Transport returns an http.RoundTripper with the correct timeouts
func (ci *ConfigInfo) Transport() http.RoundTripper {
	noTransport.Do(func() {
		// Start with a sensible set of defaults then override.
		// This also means we get new stuff when it gets added to go
		t := new(http.Transport)
		setDefaults(t, http.DefaultTransport.(*http.Transport))
		t.Proxy = http.ProxyFromEnvironment
		t.MaxIdleConnsPerHost = 4 * (ci.Checkers + ci.Transfers + 1)
		t.TLSHandshakeTimeout = ci.ConnectTimeout
		t.ResponseHeaderTimeout = ci.Timeout
		t.TLSClientConfig = &tls.Config{InsecureSkipVerify: ci.InsecureSkipVerify}
		t.DisableCompression = *noGzip
		// Set in http_old.go initTransport
		//   t.Dial
		// Set in http_new.go initTransport
		//   t.DialContext
		//   t.IdelConnTimeout
		//   t.ExpectContinueTimeout
		ci.initTransport(t)
		// Wrap that http.Transport in our own transport
		transport = NewTransport(t, ci.DumpHeaders, ci.DumpBodies)
	})
	return transport
}
Example #20
0
// performRequest is a template that creates HTTP requests with proxy and debug support.
func (c *Casper) performRequest(method string, endpoint string, params map[string]string, headers map[string]string) ([]byte, error) {
	var tr *http.Transport
	var casperForm url.Values
	var req *http.Request

	if c.Debug == true {
		fmt.Printf(method+"\t%s\n", CasperBaseURL+endpoint)
	}

	tr = &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: false},
	}

	if c.ProxyURL != nil {
		tr.Proxy = http.ProxyURL(c.ProxyURL)
		tr.TLSClientConfig.InsecureSkipVerify = true
	}

	client := &http.Client{Transport: tr}

	if params != nil {
		casperForm = url.Values{}
		for k, v := range params {
			casperForm.Add(k, v)
		}
	}

	if c.Debug == true {
		fmt.Printf("%s\n", casperForm)
	}

	if method == "GET" {
		req, _ = http.NewRequest(method, CasperBaseURL+endpoint, nil)
	} else {
		req, _ = http.NewRequest(method, CasperBaseURL+endpoint, strings.NewReader(casperForm.Encode()))
	}

	if c.ProjectName != "" {
		c.ProjectName = c.ProjectName + " "
	}

	req.Header.Set("User-Agent", "CasperGoAPIClient/"+c.ProjectName+"1.1")
	req.Header.Set("X-Casper-API-Key", c.APIKey)
	req.Header.Set("Accept", "*/*")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	res, err := client.Do(req)
	if err != nil {
		casperHTTPError.Reason = err
		return nil, casperHTTPError
	}
	defer res.Body.Close()

	parsedData, err := parseBody(res)
	if err != nil {
		return nil, err
	}

	if res.StatusCode != 200 {
		var model APIErrorResponseModel
		json.Unmarshal(parsedData, &model)
		casperHTTPError.Reason = errors.New(model.Message + "  (" + res.Status + ")")
		return nil, casperHTTPError
	}

	if c.Debug == true {
		fmt.Println(string(parsedData))
	}
	return parsedData, nil
}
Example #21
0
// performRequest is a template that creates HTTP requests with proxy and debug support.
func (s *Snapchat) performRequest(method string, endpoint string, params map[string]string, headers map[string]string) ([]byte, error) {
	var tr *http.Transport
	var snapchatForm url.Values
	var req *http.Request

	if s.CasperClient.Debug == true {
		fmt.Printf(method+"\t%s\n", SnapchatBaseURL+endpoint)
	}

	tr = &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: false},
	}

	if s.CasperClient.ProxyURL != nil {
		tr.Proxy = http.ProxyURL(s.CasperClient.ProxyURL)
		tr.TLSClientConfig.InsecureSkipVerify = true
	}

	client := &http.Client{Transport: tr}

	if params != nil {
		snapchatForm = url.Values{}
		for k, v := range params {
			snapchatForm.Add(k, v)
		}
	}

	if s.CasperClient.Debug == true {
		fmt.Printf("%s\n", snapchatForm)
	}

	if method == "GET" {
		req, _ = http.NewRequest(method, SnapchatBaseURL+endpoint, nil)
	} else {
		req, _ = http.NewRequest(method, SnapchatBaseURL+endpoint, strings.NewReader(snapchatForm.Encode()))
	}

	if headers != nil {
		for k, v := range headers {
			req.Header.Set(k, v)
		}
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	res, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	if endpoint == "/bq/get_captcha" {
		captchaID = res.Header["Content-Disposition"][0][20:]
	}

	if endpoint == "/ph/logout" || endpoint == "/loq/send" || endpoint == "/bq/delete_story" {
		status = res.StatusCode
	}

	parsedData, err := parseBody(res)
	if err != nil {
		return nil, err
	}

	if s.CasperClient.Debug == true {
		fmt.Println(string(parsedData))
	}

	return parsedData, nil
}