View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.testing.classic;
29  
30  import java.io.IOException;
31  import java.net.Socket;
32  import java.nio.charset.CharsetDecoder;
33  import java.nio.charset.CharsetEncoder;
34  import java.util.concurrent.atomic.AtomicLong;
35  
36  import javax.net.ssl.SSLSocket;
37  
38  import org.apache.hc.core5.http.ClassicHttpRequest;
39  import org.apache.hc.core5.http.ClassicHttpResponse;
40  import org.apache.hc.core5.http.ContentLengthStrategy;
41  import org.apache.hc.core5.http.Header;
42  import org.apache.hc.core5.http.config.Http1Config;
43  import org.apache.hc.core5.http.impl.io.DefaultBHttpServerConnection;
44  import org.apache.hc.core5.http.impl.io.SocketHolder;
45  import org.apache.hc.core5.http.io.HttpMessageParserFactory;
46  import org.apache.hc.core5.http.io.HttpMessageWriterFactory;
47  import org.apache.hc.core5.http.message.RequestLine;
48  import org.apache.hc.core5.http.message.StatusLine;
49  import org.apache.hc.core5.io.CloseMode;
50  import org.apache.hc.core5.util.Identifiable;
51  import org.slf4j.Logger;
52  import org.slf4j.LoggerFactory;
53  public class LoggingBHttpServerConnection extends DefaultBHttpServerConnection implements Identifiable {
54  
55      private static final AtomicLong COUNT = new AtomicLong();
56  
57      private final String id;
58      private final Logger log;
59      private final Logger headerLog;
60      private final Wire wire;
61  
62      public LoggingBHttpServerConnection(
63              final String scheme,
64              final Http1Config http1Config,
65              final CharsetDecoder charDecoder,
66              final CharsetEncoder charEncoder,
67              final ContentLengthStrategy incomingContentStrategy,
68              final ContentLengthStrategy outgoingContentStrategy,
69              final HttpMessageParserFactory<ClassicHttpRequest> requestParserFactory,
70              final HttpMessageWriterFactory<ClassicHttpResponse> responseWriterFactory) {
71          super(scheme, http1Config, charDecoder, charEncoder,
72                  incomingContentStrategy, outgoingContentStrategy,
73                  requestParserFactory, responseWriterFactory);
74          this.id = "http-incoming-" + COUNT.incrementAndGet();
75          this.log = LoggerFactory.getLogger(getClass());
76          this.headerLog = LoggerFactory.getLogger("org.apache.hc.core5.http.headers");
77          this.wire = new Wire(LoggerFactory.getLogger("org.apache.hc.core5.http.wire"), this.id);
78      }
79  
80      @Override
81      public String getId() {
82          return id;
83      }
84  
85      public LoggingBHttpServerConnection(final String scheme, final Http1Config http1Config) {
86          this(scheme, http1Config, null, null, null, null, null, null);
87      }
88  
89      @Override
90      public void close() throws IOException {
91          if (this.log.isDebugEnabled()) {
92              this.log.debug("{}: Close connection", this.id);
93          }
94          super.close();
95      }
96  
97      @Override
98      public void close(final CloseMode closeMode) {
99          if (this.log.isDebugEnabled()) {
100             this.log.debug("{}: Shutdown connection", this.id);
101         }
102         super.close(closeMode);
103     }
104 
105     @Override
106     public void bind(final Socket socket) throws IOException {
107         super.bind(this.wire.isEnabled() ? new LoggingSocketHolder(socket, wire) : new SocketHolder(socket));
108     }
109 
110     /**
111      * @since 5.3
112      */
113     public void bind(final SSLSocket sslSocket, final Socket baseSocket) throws IOException {
114         super.bind(this.wire.isEnabled() ? new LoggingSocketHolder(sslSocket, baseSocket, wire) : new SocketHolder(sslSocket, baseSocket));
115     }
116 
117     @Override
118     protected void onRequestReceived(final ClassicHttpRequest request) {
119         if (request != null && this.headerLog.isDebugEnabled()) {
120             this.headerLog.debug("{} >> {}", id, new RequestLine(request));
121             final Header[] headers = request.getHeaders();
122             for (final Header header : headers) {
123                 this.headerLog.debug("{} >> {}", this.id, header);
124             }
125         }
126     }
127 
128     @Override
129     protected void onResponseSubmitted(final ClassicHttpResponse response) {
130         if (response != null && this.headerLog.isDebugEnabled()) {
131             this.headerLog.debug("{} << {}", this.id, new StatusLine(response));
132             final Header[] headers = response.getHeaders();
133             for (final Header header : headers) {
134                 this.headerLog.debug("{} << {}", this.id, header);
135             }
136         }
137     }
138 
139 }