Help us shape the future of Go! Take the 2026 Go Developer Survey

nodemaven

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 21 Imported by: 0

README

nodemaven-go

Go client for NodeMaven proxies. It builds the proxy username the gateway expects, checks the parameters before anything is sent, and hands the result to the HTTP client you already use. It also wraps the dashboard account API.

go get github.com/nodemaven/nodemaven-go

Requires Go 1.22 or later. One dependency, github.com/BurntSushi/toml, to read gateway definitions.

Quick start

proxy, err := nodemaven.New(
	nodemaven.WithLogin("your-login"),       // or NODEMAVEN_LOGIN
	nodemaven.WithPassword("your-password"), // or NODEMAVEN_PASSWORD
	nodemaven.WithParam("country", "us"),
	nodemaven.WithParam("sid", "order4417"),
)
if err != nil {
	log.Fatal(err)
}

client := &http.Client{Transport: &http.Transport{Proxy: proxy.HTTPProxy()}}
resp, err := client.Get("https://example.com")

Other forms of the same proxy:

call gives
proxy.Username() your-login-country-us-sid-order4417
proxy.URL() http://user:pass@host:port, both credentials percent-encoded
proxy.URLWithScheme("socks5") the same with another scheme
proxy.ProxyURL() a *url.URL
proxy.HTTPProxy() a value for http.Transport.Proxy
proxy.Browser() server, username and password separately, for Playwright, chromedp or Rod

Printing a Proxy, a Connect or a BrowserProxy with any verb, %#v included, shows the password as ***.

Parameters

parameter what it selects values measured to work
country country code, or any us, de, ...
region area inside the country a name
city city inside the country - send it with its region a name
isp the exit's ISP a name
type mobile or residential exits, which are different pools mobile, residential
sid the sticky session - see below any string with no -
ttl how long that session is held 1m, 10m, 10h, 24h
filter IP quality low, medium, high
speed claims a connection speed class fast, slow
ipv4 claims to force IPv4 true

ipv4 and speed are accepted by the gateway; their effects have not been independently verified.

Names are checked; values are passed through unless a gateway definition lists the legal ones. An unknown name fails in New, because the gateway answers it with 200 and drops the setting:

NodeMaven does not know the parameter "contry": it is answered with 200 and
dropped, so the connection would succeed and your setting would NOT be applied.
Known: ["city" "country" "filter" "ipv4" "isp" "region" "sid" "speed" "ttl" "type"]

country, region, city, isp and type are folded to the wire form: surrounding ASCII whitespace trimmed, A-Z lowered and nothing else, each remaining space turned into _. District of Columbia is sent as district_of_columbia. sid, filter, ttl and speed are sent as given, so pass those in lower case. A value that is not folded and contains whitespace is refused.

Errors are values you test with errors.Is:

error when
ErrParam an unknown name, an empty value, a value with whitespace or the separator in it, a value outside a declared list
ErrCredentials no login or password, no host or port, a port that is not 1 to 65535, no API key
ErrProvider a gateway definition that does not describe a gateway
ErrCheck a CONNECT that produced no answer at all
ErrAPI the account API answered with an error or with something that is not JSON
ErrAuth, ErrNotFound, ErrRateLimit 401/403, 404, 429 - each also matches ErrAPI

Every error is a *nodemaven.Error carrying the kind and, for the account API, the HTTP status. None carries a response body.

Sticky sessions

held, err := proxy.Session("order4417")
germany, err := proxy.With("country", "de") // a new identity, a new exit
plain, err := proxy.Without("filter")       // also a new identity

A Proxy never changes; these return new ones. The session key is the whole parameter set, so adding or removing any parameter moves you to a different exit. The order parameters are given in does not.

A session id cannot contain -: the gateway cuts every value at its separator. For a pool, draw the ids:

pool, err := proxy.Sessions(50) // 50 proxies, each its own exit

Ids are 12 hexadecimal characters from crypto/rand, distinct within one call; SessionsOfLength(n, bytes) sets the length.

Checking a connection

check, err := proxy.Check(ctx)
if err != nil {
	log.Fatal(err) // DNS, refused, timed out, or not an HTTP answer
}
fmt.Println(check)
// 407 Proxy Authentication Required via gate.nodemaven.com:8080 in 0.41s
// <what 407 means on this gateway>

Check sends one CONNECT to api.ipify.org:443 and reads the reply head. A refusal is a *Check with its Status, Reason, Headers and Meaning, not an error. ExitIP is empty when the gateway did not send the exit address, which is normal. OK() means the tunnel opened, not that every parameter was applied. To change the target or the timeout:

connect := proxy.Connect()
connect.Target = "example.com:443"
connect.Timeout = 30 * time.Second
check, err := connect.Send(ctx)

Check is the only call on a Proxy that opens a socket.

Account API

client, err := nodemaven.NewClient() // NODEMAVEN_APIKEY: the dashboard key, not the proxy password
me, err := client.Me(ctx)
page, err := client.Cities(ctx, url.Values{"country__code": {"us"}})

rows := client.Iterate(ctx, page)
for rows.Next() {
	city := rows.Row().(map[string]any)
	_ = city["code"]
}
if err := rows.Err(); err != nil { ... }
call returns
Me the account
Countries, Regions, Cities, ISPs, ISPRegions, ISPCities, ZipCodes, ZipCodeRegions, ZipCodeCities a *Page
StatisticsData, StatisticsRequests an object
DomainStatistics a *Page that does not page
SubUsers, WhitelistIPs a *Page
WhitelistIP an object
CreateSubUser, UpdateSubUser, DeleteSubUser, ResetSubUserUsage the server's payload
UpsertWhitelistIP, DeleteWhitelistIP the server's answer
Iterate, All every row from a page onwards
Validate problems with a proxy's country and city, checked against the catalogue

Objects are map[string]any with numbers as json.Number; rows are []any.

  • Me and SubUsers return live proxy passwords. Do not log their results.
  • Filters go through in the server's own spelling. The server ignores a name it does not know, so a misspelt filter is dropped without an error.
  • One location page holds at most 1000 rows; Cities for the US has more. Use Iterate. It stops with an error instead of looping, and refuses a next link to another host, since that request would carry the key.
  • Statistics dates are dd-mm-yyyy. Give start and end, or period (today, hours24); without either the server answers 500.
  • The built-in HTTP client follows no redirect and reads no proxy from the environment, because the key travels in a header. Pass your own with WithHTTPClient; a JSON-less 2xx is still an error.

Nothing here retries.

Other gateways

The dialect is data, not code: separators, known names, folds and status meanings live in a TOML definition. LoadFile("mygateway.toml") reads one and WithProvider uses it; NewProvider builds one in code. Definitions are checked when loaded.

License

MIT

Documentation

Overview

Package nodemaven builds NodeMaven proxy credentials, checks a connection through the gateway, and wraps the dashboard account API.

A Proxy is one gateway identity. New validates every parameter before anything is sent, because the gateway answers an unknown parameter name with 200 and drops it:

proxy, err := nodemaven.New(
	nodemaven.WithLogin("your-login"),
	nodemaven.WithPassword("your-password"),
	nodemaven.WithParam("country", "us"),
)
client := &http.Client{Transport: &http.Transport{Proxy: proxy.HTTPProxy()}}

Only Proxy.Check and the Client methods open connections. Errors are *Error values tested with errors.Is against ErrParam, ErrCredentials, ErrProvider, ErrCheck, ErrAPI, ErrAuth, ErrNotFound and ErrRateLimit.

The gateway's dialect - separators, known names, value folding and what its statuses mean - is data in a TOML definition. The NodeMaven one is built in; LoadFile reads another.

Example
package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/nodemaven/nodemaven-go"
)

func main() {
	proxy, err := nodemaven.New(
		nodemaven.WithLogin("your-login"),
		nodemaven.WithPassword("your-password"),
		nodemaven.WithParam("country", "us"),
		nodemaven.WithParam("sid", "order4417"),
	)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(proxy.Username())

	client := &http.Client{Transport: &http.Transport{Proxy: proxy.HTTPProxy()}}
	_ = client // client.Get("https://example.com") leaves from one sticky exit
}
Output:
your-login-country-us-sid-order4417

Index

Examples

Constants

View Source
const APIRoot = "/api/v2/base"

APIRoot is the path every account API route starts with.

View Source
const ASCIIWhitespace = " \t\n\r\v\f"

ASCIIWhitespace is every character treated as whitespace in a parameter value. It is spelled out rather than taken from a standard library: Go's unicode.IsSpace also matches U+0085 and U+00A0, and the rule has to be the same in every NodeMaven SDK.

View Source
const DefaultAPITimeout = 30 * time.Second

DefaultAPITimeout bounds one request made by the built-in HTTP client.

View Source
const DefaultBaseURL = "https://dashboard.nodemaven.com"

DefaultBaseURL is the dashboard host the account API lives on.

View Source
const DefaultCheckTimeout = 15 * time.Second

DefaultCheckTimeout bounds each step of a check. One of the gateway's measured reactions is no reply for about 20 seconds, so a shorter default would report a parameter mistake as a network problem.

View Source
const DefaultPageSize = 1000

DefaultPageSize is the largest limit the location endpoints accept. It is a ceiling on one answer, not a count of the rows behind it; Iterate walks the rest.

View Source
const DefaultProvider = "nodemaven"

DefaultProvider is the id of the definition used when none is given.

View Source
const DefaultTarget = "api.ipify.org:443"

DefaultTarget is the host a check asks the gateway to tunnel to. Whatever is named sees a real TCP connection from the exit address.

Variables

View Source
var (
	// ByOffset pages the location catalogue: limit and offset, from 0.
	ByOffset = Paging{SizeKey: "limit", CursorKey: "offset", CursorCountsRows: true, DefaultSize: DefaultPageSize}
	// ISPCitiesPaging is ByOffset at 100 rows, because that endpoint takes about
	// a minute to answer 1000.
	ISPCitiesPaging = Paging{SizeKey: "limit", CursorKey: "offset", CursorCountsRows: true, DefaultSize: 100}
	// ByPageNumber pages sub-users: per_page and page, from 1.
	ByPageNumber = Paging{SizeKey: "per_page", CursorKey: "page", FirstCursor: 1}
	// WhitelistPaging pages the IP whitelist: page_size and page, from 1, and a
	// 404 past the end.
	WhitelistPaging = Paging{SizeKey: "page_size", CursorKey: "page", DefaultSize: 100, FirstCursor: 1, EndsWithNotFound: true}
)
View Source
var (
	// ErrParam is input the gateway would silently ignore, misreport, or hang on.
	ErrParam = errors.New("nodemaven: parameter")
	// ErrCredentials is a missing or malformed login, password, host or port,
	// or a missing API key.
	ErrCredentials = errors.New("nodemaven: credentials")
	// ErrProvider is a provider definition that does not describe a gateway.
	ErrProvider = errors.New("nodemaven: provider")
	// ErrCheck is a CONNECT that produced no answer at all. A refused tunnel is
	// not this error: it comes back as a CheckResult carrying the status.
	ErrCheck = errors.New("nodemaven: check")
	// ErrAPI is an account API error: an error status, a body that is not
	// JSON, or no response at all.
	ErrAPI = errors.New("nodemaven: api")
	// ErrAuth is a 401 or 403 from the account API.
	ErrAuth = errors.New("nodemaven: auth")
	// ErrNotFound is a 404 from the account API, where a 404 does not end a
	// paged walk.
	ErrNotFound = errors.New("nodemaven: not found")
	// ErrRateLimit is a 429 from the account API. Nothing here retries.
	ErrRateLimit = errors.New("nodemaven: rate limit")
)

The kinds of error this package returns. Test for them with errors.Is:

if errors.Is(err, nodemaven.ErrParam) { ... }

The names line up with the other NodeMaven SDKs: param, credentials, provider, check, api, auth, not_found, rate_limit. ErrAuth, ErrNotFound and ErrRateLimit are kinds of ErrAPI, so errors.Is(err, ErrAPI) is true for all four.

Functions

func Available

func Available() []string

Available lists the ids of the shipped definitions, sorted.

Types

type BrowserProxy

type BrowserProxy struct {
	Server   string
	Username string
	Password string
}

BrowserProxy is the shape browser automation takes a proxy in: the server without credentials, and the credentials separately and not encoded.

func (BrowserProxy) GoString

func (b BrowserProxy) GoString() string

GoString redacts the password.

func (BrowserProxy) String

func (b BrowserProxy) String() string

String redacts the password.

type Check

type Check struct {
	// Status is the CONNECT status.
	Status int
	// Reason is the reason phrase, verbatim.
	Reason string
	// Server is the host:port that was asked.
	Server string
	// Elapsed includes DNS and the TCP handshake.
	Elapsed time.Duration
	// Headers holds every response header in the order received.
	Headers []Header
	// ExitIP is the exit address, or "" when the gateway did not send one.
	// That is normal on this gateway, not an error.
	ExitIP string
	// Meaning is what this status means on this gateway, or "" when nobody
	// has recorded it.
	Meaning string
}

Check is the gateway's answer to one CONNECT. A refusal is a Check with a status other than 200, not an error: the status is the answer.

func (*Check) Header

func (c *Check) Header(name string) (string, bool)

Header returns the last value sent under name, compared without case.

func (*Check) OK

func (c *Check) OK() bool

OK reports whether the tunnel opened. It does not mean every parameter was applied: an unknown name is answered 200 and dropped, which is why New refuses unknown names before anything is sent.

func (*Check) String

func (c *Check) String() string

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client talks to the account API. Build one with NewClient.

func NewClient

func NewClient(opts ...ClientOption) (*Client, error)

NewClient builds an account API client.

func (*Client) All

func (c *Client) All(ctx context.Context, page *Page) ([]any, error)

All walks the whole collection and returns every row.

func (*Client) Cities

func (c *Client) Cities(ctx context.Context, filters url.Values) (*Page, error)

Cities lists the cities. One page holds at most 1000; use Iterate.

func (*Client) Countries

func (c *Client) Countries(ctx context.Context, filters url.Values) (*Page, error)

Countries lists the countries. filters are passed through in the server's own spelling, such as country__code; the server ignores a name it does not know, so a misspelt filter is dropped without a word.

func (*Client) CreateSubUser

func (c *Client) CreateSubUser(ctx context.Context, proxyUsername, proxyPassword string, extra map[string]any) (any, error)

CreateSubUser creates a sub-user. extra adds fields such as traffic_limit.

func (*Client) DeleteSubUser

func (c *Client) DeleteSubUser(ctx context.Context, id any) (any, error)

DeleteSubUser deletes one sub-user.

func (*Client) DeleteWhitelistIP

func (c *Client) DeleteWhitelistIP(ctx context.Context, ipID any) (any, error)

DeleteWhitelistIP removes a whitelisted address.

func (*Client) DomainStatistics

func (c *Client) DomainStatistics(ctx context.Context, proxyUsername string, filters url.Values) (*Page, error)

DomainStatistics is traffic by domain for one proxy username. It does not page; the whole answer is one page.

func (*Client) GoString

func (c *Client) GoString() string

GoString does not show the key.

func (*Client) ISPCities

func (c *Client) ISPCities(ctx context.Context, filters url.Values) (*Page, error)

ISPCities lists the cities that have ISPs, 100 at a time.

func (*Client) ISPRegions

func (c *Client) ISPRegions(ctx context.Context, filters url.Values) (*Page, error)

ISPRegions lists the regions that have ISPs.

func (*Client) ISPs

func (c *Client) ISPs(ctx context.Context, filters url.Values) (*Page, error)

ISPs lists the ISPs.

func (*Client) Iterate

func (c *Client) Iterate(ctx context.Context, page *Page) *Rows

Iterate starts a walk from page.

Example
package main

import (
	"context"
	"fmt"
	"log"
	"net/url"

	"github.com/nodemaven/nodemaven-go"
)

func main() {
	client, err := nodemaven.NewClient() // reads NODEMAVEN_APIKEY
	if err != nil {
		log.Fatal(err)
	}
	ctx := context.Background()
	page, err := client.Cities(ctx, url.Values{"country__code": {"us"}})
	if err != nil {
		log.Fatal(err)
	}
	rows := client.Iterate(ctx, page)
	for rows.Next() {
		city := rows.Row().(map[string]any)
		fmt.Println(city["code"])
	}
	if err := rows.Err(); err != nil {
		log.Fatal(err)
	}
}

func (*Client) Me

func (c *Client) Me(ctx context.Context) (map[string]any, error)

Me is the account. Its fields are the server's own; it carries a live proxy password, so do not log it.

func (*Client) Regions

func (c *Client) Regions(ctx context.Context, filters url.Values) (*Page, error)

Regions lists the regions.

func (*Client) ResetSubUserUsage

func (c *Client) ResetSubUserUsage(ctx context.Context, ids []any) (any, error)

ResetSubUserUsage resets the usage counters of the given sub-users.

func (*Client) StatisticsData

func (c *Client) StatisticsData(ctx context.Context, proxyUsername string, filters url.Values) (map[string]any, error)

StatisticsData is traffic over time for one proxy username. Dates are dd-mm-yyyy; give start and end, or period, or the server answers 500.

func (*Client) StatisticsRequests

func (c *Client) StatisticsRequests(ctx context.Context, proxyUsername string, filters url.Values) (map[string]any, error)

StatisticsRequests is request counts over time for one proxy username.

func (*Client) String

func (c *Client) String() string

String does not show the key.

func (*Client) SubUsers

func (c *Client) SubUsers(ctx context.Context, filters url.Values) (*Page, error)

SubUsers lists the sub-users. Each row carries a live proxy password.

func (*Client) UpdateSubUser

func (c *Client) UpdateSubUser(ctx context.Context, id any, changes map[string]any) (any, error)

UpdateSubUser changes the given fields of one sub-user.

func (*Client) UpsertWhitelistIP

func (c *Client) UpsertWhitelistIP(ctx context.Context, ip string, portsCount int, extra map[string]any) (map[string]any, error)

UpsertWhitelistIP creates or replaces a whitelisted address. protocol is always sent, as HTTP unless extra says otherwise, because the server does not apply the default its own document declares.

func (*Client) Validate

func (c *Client) Validate(ctx context.Context, proxy *Proxy) ([]string, error)

Validate checks a proxy's parameters against the live catalogue and returns a sentence per problem, or none. It costs a request per catalogue page.

func (*Client) WhitelistIP

func (c *Client) WhitelistIP(ctx context.Context, ipID any) (map[string]any, error)

WhitelistIP is one whitelisted address.

func (*Client) WhitelistIPs

func (c *Client) WhitelistIPs(ctx context.Context, filters url.Values) (*Page, error)

WhitelistIPs lists the whitelisted addresses.

func (*Client) ZipCodeCities

func (c *Client) ZipCodeCities(ctx context.Context, filters url.Values) (*Page, error)

ZipCodeCities lists the cities that have zip codes.

func (*Client) ZipCodeRegions

func (c *Client) ZipCodeRegions(ctx context.Context, filters url.Values) (*Page, error)

ZipCodeRegions lists the regions that have zip codes.

func (*Client) ZipCodes

func (c *Client) ZipCodes(ctx context.Context, filters url.Values) (*Page, error)

ZipCodes lists the zip codes.

type ClientOption

type ClientOption func(*clientSettings)

ClientOption configures NewClient.

func WithAPIKey

func WithAPIKey(key string) ClientOption

WithAPIKey sets the dashboard API key. Without it, NODEMAVEN_APIKEY is read. This is not the proxy password.

func WithBaseURL

func WithBaseURL(base string) ClientOption

WithBaseURL points the client at another host. Without it, NODEMAVEN_BASE_URL is read, then DefaultBaseURL.

func WithHTTPClient

func WithHTTPClient(client *http.Client) ClientOption

WithHTTPClient sends requests through your own client. The built-in one follows no redirect and reads no proxy from the environment, because the API key travels in a header; a client of your own decides both for itself. A redirect it follows to the dashboard's not-found page still comes back as an error, because that page is not JSON.

func WithTimeout

func WithTimeout(timeout time.Duration) ClientOption

WithTimeout bounds each request made by the built-in HTTP client. It does not apply to a client passed with WithHTTPClient.

type Connect

type Connect struct {
	Server   string
	Username string
	Password string
	// Target is the host:port to tunnel to.
	Target string
	// Timeout bounds each step: resolving, connecting, writing, and each read.
	// Zero is refused rather than read as "no limit".
	Timeout time.Duration
	// ExitIPHeaders are tried in order; the first one present wins.
	ExitIPHeaders []string
	// Reactions maps a status, as text, to what it means on this gateway.
	Reactions map[string]string
}

Connect is one CONNECT request, before it is sent. Proxy.Connect returns one filled in from the proxy and its definition; NewConnect fills in the defaults for a gateway described by hand.

func NewConnect

func NewConnect(server, username, password string) Connect

NewConnect describes a CONNECT to server with the default target and timeout.

func (Connect) GoString

func (c Connect) GoString() string

GoString redacts the password.

func (Connect) Send

func (c Connect) Send(ctx context.Context) (*Check, error)

Send opens one connection to the gateway, writes the CONNECT and reads the response head. It returns an error only when nothing usable came back.

func (Connect) String

func (c Connect) String() string

String redacts the password.

type Error

type Error struct {
	Kind    error
	Status  int
	Message string
	// contains filtered or unexported fields
}

Error is every error this package returns. Kind is one of the Err values above; Status is the HTTP status behind an account API error, or 0 when no status came back.

It carries no response body: two of the account API's endpoints return live proxy passwords, and an error's text goes wherever the caller's logs go.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Is

func (e *Error) Is(target error) bool

Is reports whether e is of the given kind. The three account API kinds are also ErrAPI.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the failure underneath, when there is one: a network error, a timeout, or the context being cancelled.

type Header struct {
	Name  string
	Value string
}

Header is one response header. Name is lower-cased ASCII.

type Option

type Option func(*settings)

Option configures New.

func WithHost

func WithHost(host string) Option

WithHost sets the gateway host. Without it, <ID>_HOST is read, then the definition's own host.

func WithLogin

func WithLogin(login string) Option

WithLogin sets the proxy login. Without it, <ID>_LOGIN is read.

func WithParam

func WithParam(name, value string) Option

WithParam sets one gateway parameter. Parameters go into the username in the order they are first set; setting a name again replaces its value in place.

func WithPassword

func WithPassword(password string) Option

WithPassword sets the proxy password. Without it, <ID>_PASSWORD is read.

func WithPort

func WithPort(port int) Option

WithPort sets the gateway port. Without it, <ID>_PORT is read, then the definition's own port.

func WithProvider

func WithProvider(p *Provider) Option

WithProvider uses a definition other than the shipped NodeMaven one.

type Page

type Page struct {
	Rows []any
	// Count, Next and Previous are the server's, and are empty on every
	// endpoint measured so far.
	Count    *int64
	Next     string
	Previous string
	// contains filtered or unexported fields
}

Page is one answer from a list endpoint. Rows are decoded JSON, numbers as json.Number, objects as map[string]any.

func (*Page) Len

func (p *Page) Len() int

Len is the number of rows on this page.

type Paging

type Paging struct {
	SizeKey          string
	CursorKey        string
	CursorCountsRows bool
	// DefaultSize is sent when the caller sets no size; 0 sends none.
	DefaultSize int
	// FirstCursor is sent when the caller sets no cursor.
	FirstCursor int
	// EndsWithNotFound marks an endpoint that answers 404 past its last page.
	EndsWithNotFound bool
}

Paging is how one endpoint pages: which query parameter sizes a page, which one moves the cursor, and how the cursor counts.

type Param

type Param struct {
	Name  string
	Value string
}

Param is one gateway parameter, as it will be sent.

type Provider

type Provider struct {
	// contains filtered or unexported fields
}

Provider describes one gateway's username dialect: its separators, the parameter names it recognises, how values are folded, and what its CONNECT statuses mean. Build one with Load, LoadFile or LoadString, or with NewProvider for a definition written in code.

func Load

func Load(id string) (*Provider, error)

Load returns a shipped definition.

func LoadFile

func LoadFile(path string) (*Provider, error)

LoadFile reads a definition from a TOML file. Its id is the file name without the extension.

func LoadFileAs

func LoadFileAs(path, id string) (*Provider, error)

LoadFileAs reads a definition from a TOML file under the given id.

func LoadString

func LoadString(text, id string) (*Provider, error)

LoadString reads a definition from TOML text.

func NewProvider

func NewProvider(spec ProviderSpec) (*Provider, error)

NewProvider builds a definition in code and runs the same consistency checks a definition read from a file goes through.

func (*Provider) Allowed

func (p *Provider) Allowed(name string) []string

Allowed lists the legal values of a parameter, or nil when nobody has established them and any value is passed through.

func (*Provider) ExitIPHeaders

func (p *Provider) ExitIPHeaders() []string

ExitIPHeaders lists every response header the exit address may arrive on, in the order they are tried.

func (*Provider) Host

func (p *Provider) Host() string

Host is the gateway host from the definition, or "".

func (*Provider) ID

func (p *Provider) ID() string

ID is the definition's id, which names its environment variables.

func (*Provider) IsMeasured

func (p *Provider) IsMeasured() bool

IsMeasured reports whether Status is "measured".

func (*Provider) KnownParams

func (p *Provider) KnownParams() []string

KnownParams lists the recognised parameter names, sorted.

func (*Provider) Label

func (p *Provider) Label() string

Label is the gateway's display name.

func (*Provider) Normalized

func (p *Provider) Normalized(name, value string) string

Normalized is the wire form of a value: for a folded parameter, trimmed of ASCII whitespace, A-Z lowered to a-z and nothing else, and each space turned into an underscore. Other parameters are returned unchanged.

func (*Provider) Normalizes

func (p *Provider) Normalizes(name string) bool

Normalizes reports whether values of this parameter are folded.

func (*Provider) Notes

func (p *Provider) Notes() string

Notes is the definition's free-text notes.

func (*Provider) PairSeparator

func (p *Provider) PairSeparator() string

PairSeparator joins a parameter's name to its value.

func (*Provider) Port

func (p *Provider) Port() int

Port is the gateway port from the definition, or 0.

func (*Provider) Reaction

func (p *Provider) Reaction(status int) string

Reaction is what a CONNECT status means on this gateway, or "" when nobody has recorded one.

func (*Provider) Separator

func (p *Provider) Separator() string

Separator joins the parameters in a username.

func (*Provider) SessionParam

func (p *Provider) SessionParam() string

SessionParam names the sticky-session parameter, or "" when there is none.

func (*Provider) Spell

func (p *Provider) Spell(name string) string

Spell is the name the gateway uses on the wire for a canonical parameter.

func (*Provider) Status

func (p *Provider) Status() string

Status is "measured" when the dialect was read off the wire and "documented" when it was transcribed and never exercised.

type ProviderSpec

type ProviderSpec struct {
	ID               string
	Label            string
	KnownParams      []string
	Status           string
	Prefix           string
	Separator        string
	PairSeparator    string
	SessionParam     string
	Host             string
	Port             int
	Aliases          map[string]string
	Values           map[string][]string
	Normalize        []string
	ConnectReactions map[int]string
	ExitIPHeaders    []string
	Notes            string
}

ProviderSpec describes a definition written in code. Zero values take the same defaults as a file that leaves the key out.

type Proxy

type Proxy struct {
	// contains filtered or unexported fields
}

Proxy is one gateway identity: credentials, address and parameters. It is immutable; every method that changes something returns a new Proxy. Nothing here opens a connection except Check.

func New

func New(opts ...Option) (*Proxy, error)

New builds a proxy and validates every parameter against the definition. Credentials have to be present, never valid: nothing is sent.

Example (Refusal)
package main

import (
	"errors"
	"fmt"

	"github.com/nodemaven/nodemaven-go"
)

func main() {
	_, err := nodemaven.New(
		nodemaven.WithLogin("your-login"),
		nodemaven.WithPassword("your-password"),
		nodemaven.WithParam("contry", "us"),
	)
	fmt.Println(errors.Is(err, nodemaven.ErrParam))
}
Output:
true

func (*Proxy) Browser

func (p *Proxy) Browser() BrowserProxy

Browser is the proxy for Playwright, chromedp, Rod and the like.

func (*Proxy) Check

func (p *Proxy) Check(ctx context.Context) (*Check, error)

Check opens one CONNECT through the gateway to DefaultTarget and returns its answer. It is the only call on a Proxy that opens a socket.

Example
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/nodemaven/nodemaven-go"
)

func main() {
	proxy, err := nodemaven.New(nodemaven.WithParam("country", "us"))
	if err != nil {
		log.Fatal(err)
	}
	check, err := proxy.Check(context.Background())
	if err != nil {
		log.Fatal(err) // nothing came back at all
	}
	fmt.Println(check) // a refusal is a status, with what it means on this gateway
}

func (*Proxy) Connect

func (p *Proxy) Connect() Connect

Connect is the CONNECT a Check would send, for changing its target or timeout before sending it.

func (*Proxy) GoString

func (p *Proxy) GoString() string

GoString redacts the password, so %#v does not print it either.

func (*Proxy) HTTPProxy

func (p *Proxy) HTTPProxy() func(*http.Request) (*url.URL, error)

HTTPProxy is a value for http.Transport.Proxy that sends every request through this proxy:

client := &http.Client{Transport: &http.Transport{Proxy: proxy.HTTPProxy()}}

func (*Proxy) Param

func (p *Proxy) Param(name string) (string, bool)

Param returns the value of one parameter as it will be sent.

func (*Proxy) Params

func (p *Proxy) Params() []Param

Params are the parameters as they will be sent, already folded. A copy.

func (*Proxy) Provider

func (p *Proxy) Provider() *Provider

Provider is the definition behind this proxy.

func (*Proxy) ProxyURL

func (p *Proxy) ProxyURL() *url.URL

ProxyURL is the proxy as a *url.URL, for anything that takes one.

func (*Proxy) Server

func (p *Proxy) Server() string

Server is host:port, with no credentials in it.

func (*Proxy) Session

func (p *Proxy) Session(id string) (*Proxy, error)

Session returns a copy pinned to one sticky session.

func (*Proxy) Sessions

func (p *Proxy) Sessions(count int) ([]*Proxy, error)

Sessions returns count copies, each pinned to its own random session of 12 hexadecimal characters.

Example
package main

import (
	"fmt"
	"log"

	"github.com/nodemaven/nodemaven-go"
)

func main() {
	proxy, err := nodemaven.New(
		nodemaven.WithLogin("your-login"),
		nodemaven.WithPassword("your-password"),
		nodemaven.WithParam("country", "de"),
	)
	if err != nil {
		log.Fatal(err)
	}
	pool, err := proxy.Sessions(10)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(len(pool))
}
Output:
10

func (*Proxy) SessionsOfLength

func (p *Proxy) SessionsOfLength(count, length int) ([]*Proxy, error)

SessionsOfLength is Sessions with ids of 2*length characters drawn from the operating system's random source. Ids are distinct within one call.

func (*Proxy) String

func (p *Proxy) String() string

String redacts the password.

func (*Proxy) URL

func (p *Proxy) URL() string

URL is http://user:pass@host:port with both credentials percent-encoded.

func (*Proxy) URLWithScheme

func (p *Proxy) URLWithScheme(scheme string) string

URLWithScheme is URL with another scheme, such as socks5.

func (*Proxy) Username

func (p *Proxy) Username() string

Username is the username in the gateway's dialect.

func (*Proxy) With

func (p *Proxy) With(name, value string) (*Proxy, error)

With returns a copy with one parameter set, validated.

func (*Proxy) Without

func (p *Proxy) Without(name string) (*Proxy, error)

Without returns a copy with one parameter removed.

type Rows

type Rows struct {
	// MaxPages bounds the walk. Set it before the first call to Next.
	MaxPages int
	// contains filtered or unexported fields
}

Rows walks a collection row by row from the page given, asking for the following pages as it goes:

rows := client.Iterate(ctx, page)
for rows.Next() {
	use(rows.Row())
}
if err := rows.Err(); err != nil { ... }

It stops with an error rather than loop: past MaxPages pages, on a next link it has already followed, on a page identical to the one before, and on a next link to another host, because that request would carry the API key.

func (*Rows) Err

func (r *Rows) Err() error

Err is what stopped the walk, or nil when it reached the end.

func (*Rows) Next

func (r *Rows) Next() bool

Next advances to the next row, fetching a page when needed.

func (*Rows) Row

func (r *Rows) Row() any

Row is the current row.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL