- Direct Known Subclasses:
EepHead, EepPost, I2PSocketEepGet, PartialEepGet, SSLEepGet
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static enumAuthentication mode enumeration.protected classManage the authentication parameters Ref: RFC 2617 Supports both Basic and Digest, however i2ptunnel HTTP proxy has migrated all previous Basic support to Digest.protected classReports fetch progress to the command line, one mark per markSize bytes and a summary line every lineSize marks.(package private) static final classParsed Content-Range header value.protected classDecompressor thread.static interfaceCallback interface for monitoring EepGet transfer progress.Field Summary
FieldsModifier and TypeFieldDescriptionprotected booleanWhether the fetch was aborted due to timeout or user request.protected StringAccept-Ranges header value from the response.protected StringThe URL we actually fetch from (may differ from _url in case of redirect).private booleanWhether to allow caching of the fetched response.protected longTotal bytes transferred across all attempts, including resumed content.protected EepGet.AuthStateAuthentication state for proxy digest/basic auth; created viaaddAuthorization(String, String).protected longRemaining bytes on the current attempt, -1 if unknown (chunked or no Content-Length).protected longBody bytes transferred in the currentfetch(), summed across attempts.protected StringCache-Control header value from the response.protected StringContent-Encoding header value from the response.protected StringContent-Language header value from the response.protected StringContent-Range header value from the response, for validating 206/416 resumes.protected StringContent-Type header value from the response.protected final I2PAppContextI2P application context for configuration, logging, and random number generation.protected StringSet-Cookie header value from the response.protected StringContent-Security-Policy header value from the response.protected intZero-based attempt counter for the current fetch; read by the watchdog command.protected IOExceptionIOException from the background decompressor thread, if any.protected booleanWhether the response is using chunked transfer encoding.protected StringETag received from the server (for conditional requests).protected final StringOriginal ETag passed in constructor, preserved across redirects.protected StringExpires header value from the response.Additional HTTP headers to include in the request.private longAbsolute deadline (System.currentTimeMillis()) for the whole fetch operation, or 0 for none.private intGeneration of the current fetch() call, incremented at each entry so a watchdog command from a previous fetch can never abort a reused instance.protected intTimeout in ms for receiving the HTTP response headers.protected intInactivity timeout in ms between data packets.protected intTotal timeout in ms for the entire fetch operation.protected booleanWhether the response body is gzip-compressed.protected booleanWhether to continue fetching; set false to abort.protected StringLast-Modified header received from the server.protected final StringOriginal Last-Modified passed in constructor, preserved across redirects.protected final List<EepGet.StatusListener> Registered status listeners for progress callbacks.protected final LogLogger for this instance.protected intMaximum number of complete (zero-byte) failures before giving up.private final longMaximum acceptable response size in bytes, -1 signifies unlimited, applied both against whole responses and chunks.private final longMinimum acceptable response size in bytes, -1 signifies unlimited, applied both against whole responses and chunks.protected booleanWhether the server returned 304 Not Modified.protected final intMaximum number of retry attempts per fetch.protected OutputStreamOutput stream for writing fetched data (file or pipe).protected final StringPath to the output file for saving the fetched content.protected final OutputStreamOutput stream destination, overrides outputFile when non-null.private byte[]POST data as raw binary bytes.private StringPOST data as a string body (for application/x-www-form-urlencoded).private FilePOST data read from a file.protected SocketThe socket connection to the proxy or the target server (if not proxied).protected final StringProxy hostname or IP address.protected InputStreamInput stream from the proxy/server socket.protected OutputStreamOutput stream to the proxy/server socket.protected final intProxy port number.protected StringLocation header value from redirect or 407 proxy auth response.protected AtomicIntegerCounter tracking the number of HTTP redirects followed.protected StringReferrer-Policy header value from the response.protected intHTTP response status code, -1 if no response received.protected StringHTTP response status text (e.g.protected final longFixed retry delay in ms, -1 selects the jittered default @since 0.9.71+.protected StringServer header value from the response.protected final booleanWhether to route requests through an HTTP proxy.protected booleanWhether to write error response bodies to the output.protected StringStatus header value from the response.protected StringTransfer-Encoding header value from the response.protected booleanWhether the current transfer attempt failed (non-2xx response code).protected final StringThe URL we were asked to fetch.protected StringVary header value from the response.protected StringX-Content-Type-Options header value from the response.protected StringX-Frame-Options header value from the response.protected StringX-Powered-By header value from the response.protected StringX-XSS-Protection header value from the response.protected static final intDefault connect timeout in milliseconds (90 seconds).protected static final intDefault inactivity timeout in milliseconds (5 minutes).protected static final intMaximum times to try without getting any data at all, even if numRetries is higher @since 0.7.14.protected static final intDefault number of retry attempts.protected static final intBase retry delay in milliseconds when the jittered default is used @since 0.9.71+.protected static final intMaximum additional jitter in milliseconds added to the base retry delay @since 0.9.71+.(package private) static final StringSuffix of the sidecar marker file recording that the output file holds transparently-decompressed (gunzipped) bytes rather than raw response bytes, so its length must not be used as a Range resume offset.private static final char[]Characters forbidden in filenames, including control characters (borrowed from snark).private static final StringData-phase stall abort message, thrown when the SocketTimeout watchdog fires mid-body @since 0.9.71+.private static final PatternPattern matching paths consisting only of slashes.private static final byteThe line terminator byte.(package private) static final StringProperty name for connect timeout configuration.(package private) static final StringProperty name for default retries configuration.(package private) static final StringProperty name for inactivity timeout configuration.(package private) static final StringProperty name for max complete fails configuration.(package private) static final StringProperty name for the fixed retry delay in milliseconds.protected static final StringDefault User-Agent header value.Constructor Summary
ConstructorsConstructorDescriptionEepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) Creates a new EepGet instance with size limits, output stream, and POST data.EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String lastModified, String postData) Full constructor for EepGet with all parameters.EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url) Creates a new EepGet instance with explicit proxy control, defaulting to allow caching.EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching, String etag) Creates a new EepGet instance with conditional fetch via ETag.EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching, String etag, String lastModified) Creates a new EepGet instance with conditional fetch via ETag and Last-Modified.EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, String postData) Creates a new EepGet instance with POST data support.EepGet(I2PAppContext ctx, int numRetries, String outputFile, String url) Creates a new EepGet instance without a proxy, defaulting to allow caching.EepGet(I2PAppContext ctx, int numRetries, String outputFile, String url, boolean allowCaching) Creates a new EepGet instance without a proxy, with configurable caching.EepGet(I2PAppContext ctx, String proxyHost, int proxyPort, int numRetries, String outputFile, String url) Creates a new EepGet instance with proxy support, defaulting to allow caching.EepGet(I2PAppContext ctx, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching) Creates a new EepGet instance with proxy support and configurable caching.Method Summary
Modifier and TypeMethodDescriptionvoidaddAuthorization(String userName, String password) Add basic authorization header for the proxy.voidAdd an extra header to the request.voidAdd a status listener.private static voidclearGzipMarker(File outFile) Drop the gunzip marker; called when the output file is rewritten from scratch.protected voiddoFetch(SocketTimeout timeout) Read response body for a single fetch.(package private) static StringfailureReason(Throwable t, long inactivityMs) The failure reason for a transfer-failed log line.(package private) static booleanfatalAbort(boolean aborted, boolean strictSize, long remaining, boolean sawEof) Decide whether a watchdog abort observed after the body loop must fail the attempt.booleanfetch()Blocking fetch, returning true if the URL was retrieved, false if all retries failed.booleanfetch(long fetchHeaderTimeout) Blocking fetch, timing out individual attempts if the HTTP response headers don't come back in the time given.booleanfetch(long fetchHeaderTimeout, long totalTimeout, long inactivityTimeout) Blocking fetch.private voidfollowRedirect(SocketTimeout timeout) Handles a redirect or proxy-auth response, either transferring control to a new (possibly https) fetch or fixing up the URL and retrying.Show the Accept-Ranges field.Show the Cache-Control field.Show the Content-Encoding field.Show the Content-Language field.After fetch, the received value from the server, or null if none.Show the Set-Cookie field.getCSP()Content-Security-Policy header.getEtag()After fetch, the received value from the server, or null if none.Show the Expires field.After fetch, the received value from the server, or null if none.booleanWhether the server returned 304.Referrer-Policy header.protected StringBuild the HTTP request string for the current URL and state.protected longgetResumeOffset(File outFile) Byte offset to resume from for a file-based fetch, accounting for the persisted gunzip state: a marker means the file holds decompressed bytes, whose length is not a valid offset into the compressed representation, so the fetch restarts instead of resuming.Show the Server field.Combined server status message e.g.intThe server response (200, etc).The server text ("OK", "Not Found", etc).Show the Transfer-Encoding field.getVary()Vary header.X-Content-Type-Options header.X-Frame-Options header.X-Powered-By header.X-XSS-Protection header.(package private) booleanWhether this fetch's output file was written by the transparent gunzipper, so its length is a decompressed size that must not be used as a Range resume offset.private static FilegzipMarkerFor(File outFile) The sidecar marker file recording gunzipped state for outFile.private voidHandles one header from the response.private inthandleStatus(String line) Parse the first status line and extract the response code.private static booleanWhether the exception (or any cause within a bounded depth) is a read timeout: SocketTimeoutException, or the canonical watchdog abort message.private longThe inactivity timeout in force for a fetch, the default when none was configured.private static voidincrement(byte[] lookahead, int cur) Adds one to the counter in the lookahead buffer.private static booleanisEndOfHeaders(byte[] lookahead) Checks whether the headers have ended.(package private) static booleanisStalledButProgressing(IOException ioe, boolean aborted, long attemptStartBytes, long bytesTransferred) Whether a failed attempt was a data-phase stall on an otherwise working path: the read timed out or our SocketTimeout watchdog aborted the transfer (which closes the socket first, surfacing as a raw SocketException, so the explicitabortedsignal.(package private) static booleanisTotalBudgetExhausted(long totalTimeoutMs, long attemptStartMs, long nowMs) Whether an attempt has already consumed its total-timeout budget.private static Stringlc8hex(int nc) Low 8 hex digits of the nonce.static voidCommand-line entry point for EepGet.(package private) voidmarkGzipPartial(File outFile) Record that the output file now holds decompressed bytes.private voidOpens the connection to the proxy or the destination host.parseAuthArgs(String args) Parse the args in an authentication header.(package private) static longparseChunkLength(String line) Extract the chunk size from a chunk-size line, dropping any chunk extensions.(package private) static EepGet.ContentRangeparseContentRange(String val) Parse a Content-Range header value.private static longParse an unsigned decimal byte count.private static longParse the start of a Range header value.protected longParse a chunk length from the HTTP response stream.protected voidRead and parse HTTP response headers.(package private) static StringredactedUrl(String url) The request URL for log output.(package private) static longrequestedRangeStart(long alreadyTransferred, List<String> extraHeaders) Determine the start offset this fetch requested, so a 206's Content-Range can be validated against what was actually asked for.private static StringRemoves characters unsafe for filenames, replacing them with underscores.(package private) static Stringseconds(long ms) Render a millisecond duration in seconds for log output, keeping milliseconds only for sub-second or non-whole-second values.protected voidsendRequest(SocketTimeout timeout) Open connection and send HTTP request.protected voidsetPostData(String contentType, byte[] data) Set post data (binary body).protected voidsetPostData(String contentType, File data) Set post data (file body).protected voidsetPostData(String contentType, String data) Set post data (string body).voidIf called (before calling fetch()), data from the server or proxy will be written to the output file or stream even on an error response code (4xx, 5xx, etc).protected booleanWhether to read the response body.voidStop the fetch in progress.static StringsuggestName(String url) Parse URL for a viable filename.private static voidusage()Print the command-line help to stdout.(package private) static StringThe command-line help text, listing every option accepted bymain(String[]).(package private) booleanValidate a resume-sensitive response once all headers are parsed.
Field Details
_context
I2P application context for configuration, logging, and random number generation._log
Logger for this instance._retryDelayMs
protected final long _retryDelayMsFixed retry delay in ms, -1 selects the jittered default @since 0.9.71+._shouldProxy
protected final boolean _shouldProxyWhether to route requests through an HTTP proxy._proxyHost
Proxy hostname or IP address._proxyPort
protected final int _proxyPortProxy port number._numRetries
protected final int _numRetriesMaximum number of retry attempts per fetch._minSize
private final long _minSizeMinimum acceptable response size in bytes, -1 signifies unlimited, applied both against whole responses and chunks._maxSize
private final long _maxSizeMaximum acceptable response size in bytes, -1 signifies unlimited, applied both against whole responses and chunks._outputFile
Path to the output file for saving the fetched content._outputStream
Output stream destination, overrides outputFile when non-null._url
The URL we were asked to fetch._actualURL
The URL we actually fetch from (may differ from _url in case of redirect)._postData
POST data as a string body (for application/x-www-form-urlencoded)._postBinaryData
private byte[] _postBinaryDataPOST data as raw binary bytes._postDataFile
POST data read from a file._allowCaching
private boolean _allowCachingWhether to allow caching of the fetched response._listeners
Registered status listeners for progress callbacks._extraHeaders
_keepFetching
protected volatile boolean _keepFetchingWhether to continue fetching; set false to abort._proxy
The socket connection to the proxy or the target server (if not proxied). Warning - null when extended by I2PSocketEepGet._proxyOut
Output stream to the proxy/server socket._proxyIn
Input stream from the proxy/server socket._out
Output stream for writing fetched data (file or pipe)._alreadyTransferred
protected long _alreadyTransferredTotal bytes transferred across all attempts, including resumed content._bytesTransferred
protected long _bytesTransferredBody bytes transferred in the currentfetch(), summed across attempts._bytesRemaining
protected long _bytesRemainingRemaining bytes on the current attempt, -1 if unknown (chunked or no Content-Length)._currentAttempt
protected volatile int _currentAttemptZero-based attempt counter for the current fetch; read by the watchdog command._responseCode
protected volatile int _responseCodeHTTP response status code, -1 if no response received._responseText
HTTP response status text (e.g. "OK", "Not Found")._shouldWriteErrorToOutput
protected volatile boolean _shouldWriteErrorToOutputWhether to write error response bodies to the output._etag
ETag received from the server (for conditional requests)._lastModified
Last-Modified header received from the server._etagOrig
Original ETag passed in constructor, preserved across redirects._lastModifiedOrig
Original Last-Modified passed in constructor, preserved across redirects._encodingChunked
protected volatile boolean _encodingChunkedWhether the response is using chunked transfer encoding._notModified
protected volatile boolean _notModifiedWhether the server returned 304 Not Modified._contentType
Content-Type header value from the response._server
Server header value from the response._status
Status header value from the response._transferEncoding
Transfer-Encoding header value from the response._contentEncoding
Content-Encoding header value from the response._contentLanguage
Content-Language header value from the response._cacheControl
Cache-Control header value from the response._acceptRanges
Accept-Ranges header value from the response._vary
Vary header value from the response._expiryDate
Expires header value from the response._cookie
Set-Cookie header value from the response._referrerPolicy
Referrer-Policy header value from the response._xframeOptions
X-Frame-Options header value from the response._csp
Content-Security-Policy header value from the response._xssProtection
X-XSS-Protection header value from the response._xContentTypeOptions
X-Content-Type-Options header value from the response._xPoweredBy
X-Powered-By header value from the response._contentRange
Content-Range header value from the response, for validating 206/416 resumes._transferFailed
protected volatile boolean _transferFailedWhether the current transfer attempt failed (non-2xx response code)._aborted
protected volatile boolean _abortedWhether the fetch was aborted due to timeout or user request._fetchHeaderTimeout
protected volatile int _fetchHeaderTimeoutTimeout in ms for receiving the HTTP response headers._fetchTotalTimeout
protected volatile int _fetchTotalTimeoutTotal timeout in ms for the entire fetch operation._fetchInactivityTimeout
protected volatile int _fetchInactivityTimeoutInactivity timeout in ms between data packets._fetchGeneration
private volatile int _fetchGenerationGeneration of the current fetch() call, incremented at each entry so a watchdog command from a previous fetch can never abort a reused instance._fetchDeadlineMs
private volatile long _fetchDeadlineMsAbsolute deadline (System.currentTimeMillis()) for the whole fetch operation, or 0 for none. Set once at fetch() entry._maxCompleteFails
protected volatile int _maxCompleteFailsMaximum number of complete (zero-byte) failures before giving up._redirects
Counter tracking the number of HTTP redirects followed._redirectLocation
Location header value from redirect or 407 proxy auth response._isGzippedResponse
protected boolean _isGzippedResponseWhether the response body is gzip-compressed._decompressException
IOException from the background decompressor thread, if any._authState
Authentication state for proxy digest/basic auth; created viaaddAuthorization(String, String).USER_AGENT
Default User-Agent header value. This will be replaced by the HTTP Proxy if we are using it.- See Also:
PROP_CONNECT_TIMEOUT
Property name for connect timeout configuration.- See Also:
PROP_INACTIVITY_TIMEOUT
Property name for inactivity timeout configuration.- See Also:
PROP_MAX_COMPLETE_FAILS
Property name for max complete fails configuration.- See Also:
PROP_DEFAULT_RETRIES
Property name for default retries configuration.- See Also:
PROP_RETRY_DELAY
Property name for the fixed retry delay in milliseconds. A value of -1 (the default) selects the jittered delay; 0 retries immediately (test suites) and any positive value sets an exact delay.- See Also:
DEFAULT_CONNECT_TIMEOUT
protected static final int DEFAULT_CONNECT_TIMEOUTDefault connect timeout in milliseconds (90 seconds).- See Also:
DEFAULT_INACTIVITY_TIMEOUT
protected static final int DEFAULT_INACTIVITY_TIMEOUTDefault inactivity timeout in milliseconds (5 minutes).- See Also:
DEFAULT_MAX_COMPLETE_FAILS
protected static final int DEFAULT_MAX_COMPLETE_FAILSMaximum times to try without getting any data at all, even if numRetries is higher @since 0.7.14.- See Also:
DEFAULT_NUM_RETRIES
protected static final int DEFAULT_NUM_RETRIESDefault number of retry attempts.- See Also:
DEFAULT_RETRY_DELAY
protected static final int DEFAULT_RETRY_DELAYBase retry delay in milliseconds when the jittered default is used @since 0.9.71+.- See Also:
DEFAULT_RETRY_JITTER
protected static final int DEFAULT_RETRY_JITTERMaximum additional jitter in milliseconds added to the base retry delay @since 0.9.71+.- See Also:
MSG_DATA_TIMEOUT
Data-phase stall abort message, thrown when the SocketTimeout watchdog fires mid-body @since 0.9.71+.- See Also:
GZIP_PARTIAL_MARKER_SUFFIX
Suffix of the sidecar marker file recording that the output file holds transparently-decompressed (gunzipped) bytes rather than raw response bytes, so its length must not be used as a Range resume offset.- See Also:
MULTI_SLASHES
Pattern matching paths consisting only of slashes.ILLEGAL
private static final char[] ILLEGALCharacters forbidden in filenames, including control characters (borrowed from snark).NL
Constructor Details
EepGet
public EepGet(I2PAppContext ctx, String proxyHost, int proxyPort, int numRetries, String outputFile, String url) Creates a new EepGet instance with proxy support, defaulting to allow caching.- Parameters:
ctx- I2P app contextproxyHost- hostname of the HTTP proxy, reached over anInternalSocket; null or empty disables proxyingproxyPort- the proxy's listening port; must be positive for proxying to be enablednumRetries- number of retriesoutputFile- output file pathurl- URL to fetch
EepGet
public EepGet(I2PAppContext ctx, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching) Creates a new EepGet instance with proxy support and configurable caching.- Parameters:
ctx- I2P app contextproxyHost- hostname of the HTTP proxy, reached over anInternalSocket; null or empty disables proxyingproxyPort- the proxy's listening port; must be positive for proxying to be enablednumRetries- number of retriesoutputFile- output file pathurl- URL to fetchallowCaching- whether to allow caching
EepGet
Creates a new EepGet instance without a proxy, defaulting to allow caching.- Parameters:
ctx- I2P app contextnumRetries- number of retriesoutputFile- output file pathurl- URL to fetch
EepGet
public EepGet(I2PAppContext ctx, int numRetries, String outputFile, String url, boolean allowCaching) Creates a new EepGet instance without a proxy, with configurable caching.- Parameters:
ctx- I2P app contextnumRetries- number of retriesoutputFile- output file pathurl- URL to fetchallowCaching- whether to allow caching
EepGet
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url) Creates a new EepGet instance with explicit proxy control, defaulting to allow caching.- Parameters:
ctx- I2P app contextshouldProxy- whether to use a proxyproxyHost- hostname of the HTTP proxy, reached over anInternalSocket; null or empty disables proxyingproxyPort- the proxy's listening port; must be positive for proxying to be enablednumRetries- number of retriesoutputFile- output file pathurl- URL to fetch
EepGet
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, String postData) Creates a new EepGet instance with POST data support.- Parameters:
ctx- I2P app contextshouldProxy- whether to use a proxyproxyHost- hostname of the HTTP proxy, reached over anInternalSocket; null or empty disables proxyingproxyPort- the proxy's listening port; must be positive for proxying to be enablednumRetries- number of retriesoutputFile- output file pathurl- URL to fetchpostData- POST data string
EepGet
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching, String etag) Creates a new EepGet instance with conditional fetch via ETag.- Parameters:
ctx- I2P app contextshouldProxy- whether to use a proxyproxyHost- hostname of the HTTP proxy, reached over anInternalSocket; null or empty disables proxyingproxyPort- the proxy's listening port; must be positive for proxying to be enablednumRetries- number of retriesoutputFile- output file pathurl- URL to fetchallowCaching- whether to allow cachingetag- ETag for conditional fetch
EepGet
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching, String etag, String lastModified) Creates a new EepGet instance with conditional fetch via ETag and Last-Modified.- Parameters:
ctx- I2P app contextshouldProxy- whether to use a proxyproxyHost- hostname of the HTTP proxy, reached over anInternalSocket; null or empty disables proxyingproxyPort- the proxy's listening port; must be positive for proxying to be enablednumRetries- number of retriesoutputFile- output file pathurl- URL to fetchallowCaching- whether to allow cachingetag- ETag for conditional fetchlastModified- last-modified for conditional fetch
EepGet
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) Creates a new EepGet instance with size limits, output stream, and POST data.- Parameters:
ctx- I2P app contextshouldProxy- whether to use a proxyproxyHost- hostname of the HTTP proxy, reached over anInternalSocket; null or empty disables proxyingproxyPort- the proxy's listening port; must be positive for proxying to be enablednumRetries- number of retriesminSize- minimum acceptable response size, -1 for unlimitedmaxSize- maximum acceptable response size, -1 for unlimitedoutputFile- not used if outputStream is non-nulloutputStream- takes precedence over outputFileurl- URL to fetchallowCaching- whether to allow cachingetag- ETag for conditional fetchpostData- POST data string
EepGet
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String lastModified, String postData) Full constructor for EepGet with all parameters.- Parameters:
ctx- I2P app contextshouldProxy- whether to use a proxyproxyHost- hostname of the HTTP proxy, reached over anInternalSocket; null or empty disables proxyingproxyPort- the proxy's listening port; must be positive for proxying to be enablednumRetries- number of retriesminSize- minimum acceptable response size, -1 for unlimitedmaxSize- maximum acceptable response size, -1 for unlimitedoutputFile- not used if outputStream is non-nulloutputStream- takes precedence over outputFileurl- URL to fetchallowCaching- whether to allow cachingetag- ETag for conditional fetchlastModified- last-modified for conditional fetchpostData- POST data string
Method Details
main
Command-line entry point for EepGet.Usage: eepget [-p 127.0.0.1:4444 | -c] [-n #retries] [-e etag] [-o outputFile] [-t inactivityTimeout] [-u username] [-x password] [-h name=value] [-m markSize] [-l lineLen] url
All timeouts are in seconds. The header timeout is not settable from the command line; it comes from the eepget.connectTimeout property, and the -t option sets the inactivity timeout instead (eepget.inactivityTimeout).
As of 0.9.45, supports https and redirect to https.
- Parameters:
args- command-line arguments, parsed by this method against the usage above
suggestName
sanitize
usageText
The command-line help text, listing every option accepted bymain(String[]). The defaults shown must match the constants and properties read in main().- Returns:
- the usage help text
usage
addStatusListener
Add a status listener.- Parameters:
lsnr- the listener to add
stopFetching
public void stopFetching()Stop the fetch in progress.fetch
public boolean fetch()Blocking fetch, returning true if the URL was retrieved, false if all retries failed.Uses the timeouts configured when this instance was created: the header timeout defaults to
DEFAULT_CONNECT_TIMEOUT(90 seconds), the total timeout to none, and the inactivity timeout toDEFAULT_INACTIVITY_TIMEOUT(5 minutes).- Returns:
- whether the URL was retrieved; false if every attempt failed
fetch
public boolean fetch(long fetchHeaderTimeout) Blocking fetch, timing out individual attempts if the HTTP response headers don't come back in the time given. If the timeout is zero or less, this will wait indefinitely.Total timeout default none, inactivity timeout default
DEFAULT_INACTIVITY_TIMEOUT(5 minutes).- Parameters:
fetchHeaderTimeout- timeout in ms- Returns:
- whether the URL was retrieved; false if every attempt failed
fetch
public boolean fetch(long fetchHeaderTimeout, long totalTimeout, long inactivityTimeout) Blocking fetch.The three timeouts are independent: the header timeout covers the wait for the response status line and headers of each attempt, the total timeout covers the whole operation including retries and backoff, and the inactivity timeout covers the wait between bytes once the body has started.
- Parameters:
fetchHeaderTimeout- <= 0 for none (proxy will timeout if none, none isn't recommended if no proxy) forced to totalTimeout if totalTimeout is set and this is <= 0totalTimeout- operation-wide deadline for the whole fetch, including retries and backoff between attempts; <= 0 for default noneinactivityTimeout- <= 0 for defaultDEFAULT_INACTIVITY_TIMEOUT(5 minutes)- Returns:
- whether the URL was retrieved; false if every attempt failed
inactivityBudget
private long inactivityBudget()The inactivity timeout in force for a fetch, the default when none was configured. Matches what doFetch() installs as the socket soTimeout.- Returns:
- the inactivity budget in milliseconds
failureReason
The failure reason for a transfer-failed log line. Socket exceptions frequently carry no message at all, and "-> null" tells the reader nothing. A bare read timeout is named together with the inactivity budget that expired, so the line says how long the peer stayed quiet; any other message-less exception falls back to its class name - or its full name, which an anonymous or local class leaves blank as a simple name.- Parameters:
t- the failure, non-nullinactivityMs- the inactivity timeout in force on the failed read- Returns:
- a non-empty reason for the log line
seconds
Render a millisecond duration in seconds for log output, keeping milliseconds only for sub-second or non-whole-second values.- Parameters:
ms- the duration in milliseconds- Returns:
- the duration as "30s", or "1500ms" when it is not a whole number of seconds
redactedUrl
The request URL for log output. Magnet-style URLs carrying an info_hash are cut before the hash, or at an earlier first parameter when one precedes it, and the http:// prefix is dropped, so the hash never reaches the logs; other URLs pass through unchanged.- Parameters:
url- the request URL, not null- Returns:
- the URL, redacted when it carries an info_hash
isStalledButProgressing
static boolean isStalledButProgressing(IOException ioe, boolean aborted, long attemptStartBytes, long bytesTransferred) Whether a failed attempt was a data-phase stall on an otherwise working path: the read timed out or our SocketTimeout watchdog aborted the transfer (which closes the socket first, surfacing as a raw SocketException, so the explicitabortedsignal. Flag set or socket closed by the watchdog — not exception shape, identifies that path) but the attempt still appended bytes. Wrapped timeout causes are walked so a single hop of context cannot hide a socket timeout. Header-phase timeouts make no progress within the attempt and non-timeout failures return false, so callers only skip the default backoff for one immediate Range-resume retry.- Parameters:
ioe- failure raised by the attemptaborted- whether our SocketTimeout watchdog aborted this attemptattemptStartBytes- body bytes transferred when the attempt started; header and connect phases advance no body bytesbytesTransferred- body bytes transferred now, after the failure- Returns:
- true when the attempt timed out after making progress
isTotalBudgetExhausted
static boolean isTotalBudgetExhausted(long totalTimeoutMs, long attemptStartMs, long nowMs) Whether an attempt has already consumed its total-timeout budget. The budget is operation-wide: SocketTimeout's total period and fetch()'s deadline both start at fetch() entry, so a failure at or past that deadline is the caller's overall timeout, not a transient stall. It must take the default retry backoff instead of an immediate Range-resume retry.- Parameters:
totalTimeoutMs- total timeout for the fetch, <= 0 for noneattemptStartMs- when fetch() started the operationnowMs- when the failure was classified- Returns:
- true if the total budget is exhausted
hasTimeoutCause
Whether the exception (or any cause within a bounded depth) is a read timeout: SocketTimeoutException, or the canonical watchdog abort message. A bare InterruptedIOException is not classified; modern socket reads do not throw it on interrupt, so it cannot be attributed to our watchdog without the explicit abort signal.- Parameters:
t- exception or cause chain head, may be null- Returns:
- true when a timeout cause is found
doFetch
Read response body for a single fetch. Call aftersendRequest(SocketTimeout).- Parameters:
timeout- may be null- Throws:
IOException- on IO error
readHeaders
Read and parse HTTP response headers.- Throws:
IOException- on IO error
shouldReadBody
protected boolean shouldReadBody()Whether to read the response body.- Returns:
- true always, overridden in
EepHead
readChunkLength
Parse a chunk length from the HTTP response stream. The chunk-size line is read whole, so any chunk extensions (RFC 9112 sec. 7.1.1, "chunk-ext") come along with it and are discarded rather than rejected. A trailer section after the terminating zero-length chunk is not consumed.- Returns:
- the chunk length
- Throws:
IOException- on IO error, or if the chunk-size line is not hex
parseChunkLength
Extract the chunk size from a chunk-size line, dropping any chunk extensions. Only the hex digits before the first ';' are significant, per RFC 9112 sec. 7.1, so a negative size, which is outside that grammar, is rejected rather than silently ending the transfer early.- Parameters:
line- the raw chunk-size line, without the trailing CRLF- Returns:
- the chunk length, never negative
- Throws:
IOException- if the chunk size is not a hex number
fatalAbort
static boolean fatalAbort(boolean aborted, boolean strictSize, long remaining, boolean sawEof) Decide whether a watchdog abort observed after the body loop must fail the attempt. A transfer whose declared body completed — fixed length reached, chunked terminator read, or EOF on an unknown-length body — carries all its bytes, so an abort landing between the last read and finalization must not report failure; anything less is a genuine abort.- Parameters:
aborted- the watchdog aborted this attemptstrictSize- whether Content-Length framed the bodyremaining- declared bytes still unread after the loopsawEof- the body stream reached end of stream- Returns:
- true when the abort must fail the attempt
validateResumeResponse
Validate a resume-sensitive response once all headers are parsed. A 206 must carry a Content-Range whose start matches the start we requested — our resume offset or a caller-supplied Range — and whose span matches the declared Content-Length, or appending its body would corrupt the output. A 416 to a partial fetch is only a success when the server proves our offset equals the complete length; anything else fails without a retry, since the same Range would produce the same answer. Other responses are untouched here.- Returns:
- true when the response body must be skipped
- Throws:
IOException- when the response cannot safely be applied
requestedRangeStart
Determine the start offset this fetch requested, so a 206's Content-Range can be validated against what was actually asked for. A resume Range generated by this class (alreadyTransferred > 0) is written before any caller-supplied headers and wins; otherwise a caller-supplied "Range: bytes=N-..." header (webseed piece fetches) provides the offset; with no Range at all a 206 must start at zero. A present but unparseable Range yields -1, leaving the start check to the caller's own contract.- Parameters:
alreadyTransferred- resume offset; greater than zero when this class generated the Range headerextraHeaders- caller headers as "Name: value", may be null- Returns:
- the expected Content-Range start, or -1 when unknown
parseRangeHeaderStart
Parse the start of a Range header value. Only a simple single range ("bytes=start-end" or "bytes=start-") is usable here; multi-ranges and suffix ranges yield -1.- Parameters:
val- Range header value without the field name, may be null- Returns:
- the requested start, or -1 if not a simple single range
parseContentRange
Parse a Content-Range header value. Accepts the satisfiable form ("bytes start-end/total") and the unsatisfied form sent with 416 ("bytes star/total"), with the total optionally a star.- Parameters:
val- header value, may be null- Returns:
- the parsed range, or null if missing or invalid
parseDigits
Parse an unsigned decimal byte count.- Parameters:
s- digits, non-null- Returns:
- the value, or -1 if empty, non-digit, or too large
handleStatus
Parse the first status line and extract the response code. Side effect: stores status text in _responseText.- Parameters:
line- the first line of the HTTP response- Returns:
- HTTP response code (200, 206, other)
handle
increment
private static void increment(byte[] lookahead, int cur) Adds one to the counter in the lookahead buffer.- Parameters:
lookahead- the buffer holding the countercur- the position of the counter
isEndOfHeaders
private static boolean isEndOfHeaders(byte[] lookahead) Checks whether the headers have ended.- Parameters:
lookahead- the buffer to check- Returns:
- true if the blank line was seen
followRedirect
Handles a redirect or proxy-auth response, either transferring control to a new (possibly https) fetch or fixing up the URL and retrying.Also reached after a 407 proxy-auth response, to retry through the proxy.
- Parameters:
timeout- the fetch timeout, may be null- Throws:
IOException- on invalid redirect or auth failure
openConnection
Opens the connection to the proxy or the destination host.- Throws:
IOException- on connect failure
gzipMarkerFor
gzipMarkerExists
boolean gzipMarkerExists()Whether this fetch's output file was written by the transparent gunzipper, so its length is a decompressed size that must not be used as a Range resume offset.- Returns:
- true when a gzip marker exists for the output file
markGzipPartial
Record that the output file now holds decompressed bytes. Called before the first decompressed byte is written, so an interrupted fetch cannot leave decompressed content without its marker.- Parameters:
outFile- output file being written by the gunzipper, non-null- Throws:
IOException- if the marker cannot be persisted
clearGzipMarker
Drop the gunzip marker; called when the output file is rewritten from scratch.- Parameters:
outFile- output file, non-null
getResumeOffset
Byte offset to resume from for a file-based fetch, accounting for the persisted gunzip state: a marker means the file holds decompressed bytes, whose length is not a valid offset into the compressed representation, so the fetch restarts instead of resuming.- Parameters:
outFile- output file, may be absent- Returns:
- resume offset; 0 when the file is absent or must be restarted
sendRequest
Open connection and send HTTP request.- Parameters:
timeout- may be null- Throws:
IOException- on IO error
getRequest
Build the HTTP request string for the current URL and state.- Returns:
- the HTTP request string
- Throws:
IOException- on bad URL
getEtag
After fetch, the received value from the server, or null if none. Before fetch, and after some errors, may be the value passed in the constructor.- Returns:
- the ETag from the server's response, or null if none was sent
getLastModified
After fetch, the received value from the server, or null if none. Before fetch, and after some errors, may be the value passed in the constructor.- Returns:
- the last modified date
getNotModified
public boolean getNotModified()Whether the server returned 304.- Returns:
- true if the server returned 304
getContentType
After fetch, the received value from the server, or null if none.- Returns:
- the content type
getServer
Show the Server field.- Returns:
- the Server header from the response, or null if none was sent
getContentLanguage
getTransferEncoding
getContentEncoding
getCacheControl
getAcceptRanges
getExpiryDate
getCookie
Show the Set-Cookie field.- Returns:
- the Set-Cookie header from the response, or null if none was sent
getReferrerPolicy
getVary
getXframeOptions
getCSP
getXSSProtection
getXContentTypeOptions
X-Content-Type-Options header.- Returns:
- the content type options, or null
getXPoweredBy
getStatusCode
public int getStatusCode()The server response (200, etc).- Returns:
- -1 if invalid, or if the proxy never responded, or if no proxy was used and the server never responded. If a non-proxied request partially succeeded (for example a redirect followed by a fail, or a partial fetch followed by a fail), this will be the last status code received. Note that fetch() may return false even if this returns 200.
getStatusText
The server text ("OK", "Not Found", etc). Note that the text may contain % encoding.- Returns:
- null if invalid, or if the proxy never responded, or if no proxy was used and the server never responded. If a non-proxied request partially succeeded (for example a redirect followed by a fail, or a partial fetch followed by a fail), this will be the last status code received. Note that fetch() may return false even if this returns "OK".
getStatus
setWriteErrorToOutput
public void setWriteErrorToOutput()If called (before calling fetch()), data from the server or proxy will be written to the output file or stream even on an error response code (4xx, 5xx, etc). The error data will only be written if no previous data was written on an earlier try. Caller must of course checkgetStatusCode()or the fetch() return value.addHeader
Add an extra header to the request. Must be called before fetch(). Not supported by EepHead. As of 0.9.10, If name is User-Agent, this will replace the default User-Agent header. As of 0.9.14, If name is If-None-Match or If-Modified-Since, this will replace the etag or last-modified value given in the constructor. Note that headers may be subsequently modified or removed in the I2PTunnel HTTP Client proxy.In proxied SSLEepGet, these headers are sent to the remote server, NOT the proxy.
- Parameters:
name- header namevalue- header value
addAuthorization
Add basic authorization header for the proxy. Only added if the request is going through a proxy. Must be called before fetch().- Parameters:
userName- username offered in the proxy's Basic or Digest challengepassword- the matching password, or null if the challenge offers none
setPostData
Set post data (string body). Must be called before fetch().- Parameters:
contentType- Content-Type header valuedata- the request body, sent verbatim after the headers- Throws:
IllegalStateException- if already set
setPostData
Set post data (file body). Must be called before fetch().- Parameters:
contentType- Content-Type header valuedata- file containing POST body- Throws:
IllegalStateException- if already set
setPostData
Set post data (binary body). Must be called before fetch().- Parameters:
contentType- Content-Type header valuedata- POST body bytes- Throws:
IllegalStateException- if already set
parseAuthArgs
Parse the args in an authentication header.Modified from LoadClientAppsJob. All keys are mapped to lower case. Double quotes around values are stripped. Ref: RFC 2617
Public for I2PTunnelHTTPClientBase; use outside of tree at own risk, subject to change or removal.
- Parameters:
args- non-null, starting after "Digest " or "Basic "- Returns:
- parsed key-value pairs
lc8hex
Low 8 hex digits of the nonce.- Parameters:
nc- the nonce value to format- Returns:
- 8 hex chars, lower case, e.g. 00000001