1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.client5.http.impl.async;
29
30 import java.io.IOException;
31 import java.util.List;
32
33 import org.apache.hc.core5.function.Callback;
34 import org.apache.hc.core5.http.Header;
35 import org.apache.hc.core5.http.HttpConnection;
36 import org.apache.hc.core5.http.config.CharCodingConfig;
37 import org.apache.hc.core5.http.nio.AsyncPushConsumer;
38 import org.apache.hc.core5.http.nio.HandlerFactory;
39 import org.apache.hc.core5.http.protocol.HttpProcessor;
40 import org.apache.hc.core5.http2.config.H2Config;
41 import org.apache.hc.core5.http2.frame.FramePrinter;
42 import org.apache.hc.core5.http2.frame.RawFrame;
43 import org.apache.hc.core5.http2.impl.nio.ClientH2PrefaceHandler;
44 import org.apache.hc.core5.http2.impl.nio.ClientH2StreamMultiplexerFactory;
45 import org.apache.hc.core5.http2.impl.nio.H2StreamListener;
46 import org.apache.hc.core5.reactor.IOEventHandler;
47 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
48 import org.apache.hc.core5.reactor.ProtocolIOSession;
49 import org.apache.hc.core5.util.Args;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 class H2AsyncClientProtocolStarter implements IOEventHandlerFactory {
54
55 private static final Logger HEADER_LOG = LoggerFactory.getLogger("org.apache.hc.client5.http.headers");
56 private static final Logger FRAME_LOG = LoggerFactory.getLogger("org.apache.hc.client5.http2.frame");
57 private static final Logger FRAME_PAYLOAD_LOG = LoggerFactory.getLogger("org.apache.hc.client5.http2.frame.payload");
58 private static final Logger FLOW_CTRL_LOG = LoggerFactory.getLogger("org.apache.hc.client5.http2.flow");
59
60 private final HttpProcessor httpProcessor;
61 private final HandlerFactory<AsyncPushConsumer> exchangeHandlerFactory;
62 private final H2Config h2Config;
63 private final CharCodingConfig charCodingConfig;
64 private final Callback<Exception> exceptionCallback;
65
66 H2AsyncClientProtocolStarter(
67 final HttpProcessor httpProcessor,
68 final HandlerFactory<AsyncPushConsumer> exchangeHandlerFactory,
69 final H2Config h2Config,
70 final CharCodingConfig charCodingConfig,
71 final Callback<Exception> exceptionCallback) {
72 this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
73 this.exchangeHandlerFactory = exchangeHandlerFactory;
74 this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
75 this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
76 this.exceptionCallback = exceptionCallback;
77 }
78
79 @Override
80 public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
81 if (HEADER_LOG.isDebugEnabled()
82 || FRAME_LOG.isDebugEnabled()
83 || FRAME_PAYLOAD_LOG.isDebugEnabled()
84 || FLOW_CTRL_LOG.isDebugEnabled()) {
85 final String id = ioSession.getId();
86 final ClientH2StreamMultiplexerFactory http2StreamHandlerFactory = new ClientH2StreamMultiplexerFactory(
87 httpProcessor,
88 exchangeHandlerFactory,
89 h2Config,
90 charCodingConfig,
91 new H2StreamListener() {
92
93 final FramePrinter framePrinter = new FramePrinter();
94
95 private void logFrameInfo(final String prefix, final RawFrame frame) {
96 try {
97 final LogAppendable logAppendable = new LogAppendable(FRAME_LOG, prefix);
98 framePrinter.printFrameInfo(frame, logAppendable);
99 logAppendable.flush();
100 } catch (final IOException ignore) {
101 }
102 }
103
104 private void logFramePayload(final String prefix, final RawFrame frame) {
105 try {
106 final LogAppendable logAppendable = new LogAppendable(FRAME_PAYLOAD_LOG, prefix);
107 framePrinter.printPayload(frame, logAppendable);
108 logAppendable.flush();
109 } catch (final IOException ignore) {
110 }
111 }
112
113 private void logFlowControl(final String prefix, final int streamId, final int delta, final int actualSize) {
114 FLOW_CTRL_LOG.debug("{} stream {} flow control {} -> {}", prefix, streamId, delta, actualSize);
115 }
116
117 @Override
118 public void onHeaderInput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
119 if (HEADER_LOG.isDebugEnabled()) {
120 for (int i = 0; i < headers.size(); i++) {
121 HEADER_LOG.debug("{} << {}", id, headers.get(i));
122 }
123 }
124 }
125
126 @Override
127 public void onHeaderOutput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
128 if (HEADER_LOG.isDebugEnabled()) {
129 for (int i = 0; i < headers.size(); i++) {
130 HEADER_LOG.debug("{} >> {}", id, headers.get(i));
131 }
132 }
133 }
134
135 @Override
136 public void onFrameInput(final HttpConnection connection, final int streamId, final RawFrame frame) {
137 if (FRAME_LOG.isDebugEnabled()) {
138 logFrameInfo(id + " <<", frame);
139 }
140 if (FRAME_PAYLOAD_LOG.isDebugEnabled()) {
141 logFramePayload(id + " <<", frame);
142 }
143 }
144
145 @Override
146 public void onFrameOutput(final HttpConnection connection, final int streamId, final RawFrame frame) {
147 if (FRAME_LOG.isDebugEnabled()) {
148 logFrameInfo(id + " >>", frame);
149 }
150 if (FRAME_PAYLOAD_LOG.isDebugEnabled()) {
151 logFramePayload(id + " >>", frame);
152 }
153 }
154
155 @Override
156 public void onInputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
157 if (FLOW_CTRL_LOG.isDebugEnabled()) {
158 logFlowControl(id + " <<", streamId, delta, actualSize);
159 }
160 }
161
162 @Override
163 public void onOutputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
164 if (FLOW_CTRL_LOG.isDebugEnabled()) {
165 logFlowControl(id + " >>", streamId, delta, actualSize);
166 }
167 }
168
169 });
170 return new ClientH2PrefaceHandler(ioSession, http2StreamHandlerFactory, false, exceptionCallback);
171 }
172 final ClientH2StreamMultiplexerFactory http2StreamHandlerFactory = new ClientH2StreamMultiplexerFactory(
173 httpProcessor,
174 exchangeHandlerFactory,
175 h2Config,
176 charCodingConfig,
177 null);
178 return new ClientH2PrefaceHandler(ioSession, http2StreamHandlerFactory, false, exceptionCallback);
179 }
180
181 }