Class StatusCapturingDraft
Draft_6455 that records the HTTP status of the upgrade response, so the agent socket
can tell a refused upgrade (401, 402, 426, 429, ...) from a lost connection (as of 6.3.1).
Why an override of translateHandshake. Measured with javap -c on
Java-WebSocket 1.6.0: for a client, WebSocketImpl.decodeHandshake calls the public,
non-final Draft.translateHandshake(ByteBuffer); its private
translateHandshakeHttpClient throws InvalidHandshakeException("Invalid status code
received: ...") as soon as the status line is complete and the status is not 101, and
WebSocketImpl turns that into flushAndClose(1002, message, false) -- no accept
hook (acceptHandshakeAsClient) runs for a refused upgrade, so the status is visible only
here. The client's WebSocketImpl copies its draft with copyInstance(), which is
why that is overridden too: the copy shares this instance's sink.
The response is read from a duplicate of the buffer, so the parent sees it untouched. Nothing is recorded until the status line's CRLF has arrived; the parent then throws its incomplete-handshake exception and the library calls again with more bytes.
Refusal bodies in later segments. The parent rejects a non-101 status as soon as the
status line is complete, so on its own the library never reads past the bytes of the first
read. A server, proxy or TLS layer may send the head and the body in separate segments, and the
body (a 402's reason, grace end and manage link) would then be lost. So for a non-101 status this
draft throws IncompleteHandshakeException itself, before the parent sees the response,
while the response is still incomplete: until the head's terminating blank line has arrived
(within 16 KiB), and then until the bytes after the head hold the whole body per
Content-Length (at most 8 KiB). WebSocketImpl.decodeHandshake answers that
exception by buffering the bytes and calling again when more arrive -- the same path the
library uses for a head that is not yet complete. The sink holds the status (and the headers
once the head is complete) while the body is awaited, so a connection that ends first is still
reported as that refusal, status-only. The wait is bounded three ways: by the byte caps, by the
end of the stream, and by the caller's handshake deadline, which closes an attempt that has not
opened (AgentConnection.HANDSHAKE_DEADLINE_MS). A body over the cap, a refusal without
Content-Length and a head over 16 KiB are not waited for: the status alone decides.
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final Stringprivate static final intprivate static final intprivate final AtomicReference<UpgradeRejection> (package private) static final intStatus recorded for an accepted upgrade.Fields inherited from class org.java_websocket.drafts.Draft
continuousFrameType, role -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate intcapture(ByteBuffer view) Records what the response says so far.private static longcontentLength(String raw) org.java_websocket.drafts.Draftprivate static intindexOf(byte[] data, int from, int to, byte[] pattern) parseHeaders(String block) private static intparseStatus(String statusLine) (package private) AtomicReference<UpgradeRejection> sink()org.java_websocket.handshake.HandshakedataMethods inherited from class org.java_websocket.drafts.Draft_6455
acceptHandshakeAsClient, acceptHandshakeAsServer, createBinaryFrame, createFrames, createFrames, equals, getCloseHandshakeType, getExtension, getKnownExtensions, getKnownProtocols, getMaxFrameSize, getProtocol, hashCode, postProcessHandshakeRequestAsClient, postProcessHandshakeResponseAsServer, processFrame, reset, toString, translateFrameMethods inherited from class org.java_websocket.drafts.Draft
basicAccept, checkAlloc, continuousFrame, createHandshake, createHandshake, createHandshake, createHandshake, getRole, readLine, readStringLine, setParseMode, translateHandshakeHttp
-
Field Details
-
SWITCHING_PROTOCOLS
static final int SWITCHING_PROTOCOLSStatus recorded for an accepted upgrade.- See Also:
-
MAX_BODY_BYTES
private static final int MAX_BODY_BYTES- See Also:
-
MAX_HEAD_BYTES
private static final int MAX_HEAD_BYTES- See Also:
-
HTTP_PREFIX
- See Also:
-
sink
-
-
Constructor Details
-
StatusCapturingDraft
StatusCapturingDraft(AtomicReference<UpgradeRejection> sink) - Parameters:
sink- where the parsed response is stored; shared with every copy of this draft
-
-
Method Details
-
sink
AtomicReference<UpgradeRejection> sink()- Returns:
- the sink this draft writes to
-
translateHandshake
public org.java_websocket.handshake.Handshakedata translateHandshake(ByteBuffer buf) throws org.java_websocket.exceptions.InvalidHandshakeException - Overrides:
translateHandshakein classorg.java_websocket.drafts.Draft- Throws:
org.java_websocket.exceptions.InvalidHandshakeException
-
copyInstance
public org.java_websocket.drafts.Draft copyInstance()- Overrides:
copyInstancein classorg.java_websocket.drafts.Draft_6455
-
capture
Records what the response says so far.- Parameters:
view- a duplicate of the handshake bytes received so far- Returns:
0when the parent should decide now; otherwise the refusal is still arriving: a positive value is the total byte count the complete refusal needs,-1means the head is not yet complete
-
parseStatus
-
parseHeaders
-
contentLength
-
indexOf
private static int indexOf(byte[] data, int from, int to, byte[] pattern)
-