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