001/* 002 * ==================================================================== 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 * ==================================================================== 020 * 021 * This software consists of voluntary contributions made by many 022 * individuals on behalf of the Apache Software Foundation. For more 023 * information on the Apache Software Foundation, please see 024 * <http://www.apache.org/>. 025 * 026 */ 027 028package org.apache.http.impl; 029 030import java.io.IOException; 031import java.io.OutputStream; 032import java.net.Socket; 033import java.nio.charset.CharsetDecoder; 034import java.nio.charset.CharsetEncoder; 035 036import org.apache.http.HttpEntity; 037import org.apache.http.HttpEntityEnclosingRequest; 038import org.apache.http.HttpException; 039import org.apache.http.HttpRequest; 040import org.apache.http.HttpResponse; 041import org.apache.http.HttpServerConnection; 042import org.apache.http.config.MessageConstraints; 043import org.apache.http.entity.ContentLengthStrategy; 044import org.apache.http.impl.entity.DisallowIdentityContentLengthStrategy; 045import org.apache.http.impl.io.DefaultHttpRequestParserFactory; 046import org.apache.http.impl.io.DefaultHttpResponseWriterFactory; 047import org.apache.http.io.HttpMessageParser; 048import org.apache.http.io.HttpMessageParserFactory; 049import org.apache.http.io.HttpMessageWriter; 050import org.apache.http.io.HttpMessageWriterFactory; 051import org.apache.http.util.Args; 052 053/** 054 * Default implementation of {@link HttpServerConnection}. 055 * 056 * @since 4.3 057 */ 058public class DefaultBHttpServerConnection extends BHttpConnectionBase implements HttpServerConnection { 059 060 private final HttpMessageParser<HttpRequest> requestParser; 061 private final HttpMessageWriter<HttpResponse> responseWriter; 062 063 /** 064 * Creates new instance of DefaultBHttpServerConnection. 065 * 066 * @param buffersize buffer size. Must be a positive number. 067 * @param fragmentSizeHint fragment size hint. 068 * @param chardecoder decoder to be used for decoding HTTP protocol elements. 069 * If {@code null} simple type cast will be used for byte to char conversion. 070 * @param charencoder encoder to be used for encoding HTTP protocol elements. 071 * If {@code null} simple type cast will be used for char to byte conversion. 072 * @param constraints Message constraints. If {@code null} 073 * {@link MessageConstraints#DEFAULT} will be used. 074 * @param incomingContentStrategy incoming content length strategy. If {@code null} 075 * {@link DisallowIdentityContentLengthStrategy#INSTANCE} will be used. 076 * @param outgoingContentStrategy outgoing content length strategy. If {@code null} 077 * {@link org.apache.http.impl.entity.StrictContentLengthStrategy#INSTANCE} will be used. 078 * @param requestParserFactory request parser factory. If {@code null} 079 * {@link DefaultHttpRequestParserFactory#INSTANCE} will be used. 080 * @param responseWriterFactory response writer factory. If {@code null} 081 * {@link DefaultHttpResponseWriterFactory#INSTANCE} will be used. 082 */ 083 public DefaultBHttpServerConnection( 084 final int buffersize, 085 final int fragmentSizeHint, 086 final CharsetDecoder chardecoder, 087 final CharsetEncoder charencoder, 088 final MessageConstraints constraints, 089 final ContentLengthStrategy incomingContentStrategy, 090 final ContentLengthStrategy outgoingContentStrategy, 091 final HttpMessageParserFactory<HttpRequest> requestParserFactory, 092 final HttpMessageWriterFactory<HttpResponse> responseWriterFactory) { 093 super(buffersize, fragmentSizeHint, chardecoder, charencoder, constraints, 094 incomingContentStrategy != null ? incomingContentStrategy : 095 DisallowIdentityContentLengthStrategy.INSTANCE, outgoingContentStrategy); 096 this.requestParser = (requestParserFactory != null ? requestParserFactory : 097 DefaultHttpRequestParserFactory.INSTANCE).create(getSessionInputBuffer(), constraints); 098 this.responseWriter = (responseWriterFactory != null ? responseWriterFactory : 099 DefaultHttpResponseWriterFactory.INSTANCE).create(getSessionOutputBuffer()); 100 } 101 102 public DefaultBHttpServerConnection( 103 final int buffersize, 104 final CharsetDecoder chardecoder, 105 final CharsetEncoder charencoder, 106 final MessageConstraints constraints) { 107 this(buffersize, buffersize, chardecoder, charencoder, constraints, null, null, null, null); 108 } 109 110 public DefaultBHttpServerConnection(final int buffersize) { 111 this(buffersize, buffersize, null, null, null, null, null, null, null); 112 } 113 114 protected void onRequestReceived(final HttpRequest request) { 115 } 116 117 protected void onResponseSubmitted(final HttpResponse response) { 118 } 119 120 @Override 121 public void bind(final Socket socket) throws IOException { 122 super.bind(socket); 123 } 124 125 @Override 126 public HttpRequest receiveRequestHeader() 127 throws HttpException, IOException { 128 ensureOpen(); 129 final HttpRequest request = this.requestParser.parse(); 130 onRequestReceived(request); 131 incrementRequestCount(); 132 return request; 133 } 134 135 @Override 136 public void receiveRequestEntity(final HttpEntityEnclosingRequest request) 137 throws HttpException, IOException { 138 Args.notNull(request, "HTTP request"); 139 ensureOpen(); 140 final HttpEntity entity = prepareInput(request); 141 request.setEntity(entity); 142 } 143 144 @Override 145 public void sendResponseHeader(final HttpResponse response) 146 throws HttpException, IOException { 147 Args.notNull(response, "HTTP response"); 148 ensureOpen(); 149 this.responseWriter.write(response); 150 onResponseSubmitted(response); 151 if (response.getStatusLine().getStatusCode() >= 200) { 152 incrementResponseCount(); 153 } 154 } 155 156 @Override 157 public void sendResponseEntity(final HttpResponse response) 158 throws HttpException, IOException { 159 Args.notNull(response, "HTTP response"); 160 ensureOpen(); 161 final HttpEntity entity = response.getEntity(); 162 if (entity == null) { 163 return; 164 } 165 final OutputStream outstream = prepareOutput(response); 166 entity.writeTo(outstream); 167 outstream.close(); 168 } 169 170 @Override 171 public void flush() throws IOException { 172 ensureOpen(); 173 doFlush(); 174 } 175 176}