/**
* Sahi - Web Automation and Test Tool
*
* Copyright 2006 V Narayan Raman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.sahi.response;
import net.sf.sahi.StreamHandler;
import net.sf.sahi.config.Configuration;
import net.sf.sahi.util.TrafficLogger;
import net.sf.sahi.util.Utils;
import org.apache.log4j.Logger;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* User: nraman
* Date: May 13, 2005
* Time: 10:25:31 PM
*/
public class HttpResponse extends StreamHandler {
private Logger logger = Logger.getLogger(HttpResponse.class);
protected HttpResponse() {
}
public HttpResponse(InputStream in, HttpURLConnection connection) {
setHeaders(connection);
setFirstLine(connection);
setContentLength(-1);
try {
populateData(in);
} catch (IOException ioe) {
// suppress;
}
}
private void setFirstLine(HttpURLConnection connection) {
Map<String, List<String>> connheaders = connection.getHeaderFields();
List<String> firstLines = connheaders.get(null);
// can have multiple lines, especially if there are unknown connection keys.
// choose the one with HTTP in it.
if (firstLines == null) return;
for (Iterator<String> iterator = firstLines.iterator(); iterator.hasNext(); ) {
String line = iterator.next();
if (line.indexOf("HTTP") != -1)
setFirstLine(line);
}
}
private void setHeaders(HttpURLConnection connection) {
for (int i = 1; true; i++) {
String key = connection.getHeaderFieldKey(i);
if (key == null) break;
addHeader(key, connection.getHeaderField(i));
}
}
public String contentTypeHeader() {
return getLastSetValueOfHeader("Content-Type");
}
public void keepAlive(final boolean keepAliveEnabled) {
setFirstLine(firstLine().replaceAll("HTTP/1.0", "HTTP/1.1"));
removeHeader("Content-length");
int len = data() != null ? getModifiedContentLength() : 0;
setHeader("Content-Length", "" + len);
removeHeader("Connection");
removeHeader("Accept-ranges");
setHeader("Connection", keepAliveEnabled ? "Keep-Alive" : "close");
resetRawHeaders();
}
public void proxyKeepAlive(final boolean keepAliveEnabled) {
setFirstLine(firstLine().replaceAll("HTTP/1.0", "HTTP/1.1"));
removeHeader("Connection");
removeHeader("Accept-ranges");
removeHeader("Accept-Ranges");
setHeader("Accept-Ranges", "none");
setHeader("Proxy-Connection", keepAliveEnabled ? "Keep-Alive" : "close");
}
public boolean isAttachment() {
if (Configuration.downloadIfContentDispositionIsAttachment()) {
String contentDisposition = getLastSetValueOfHeader("Content-Disposition");
if (contentDisposition == null) return false;
return contentDisposition.toLowerCase().indexOf("attachment") != -1;
}
return false;
}
public void sendHeaders(OutputStream out, boolean isKeepAlive) throws IOException {
OutputStream outputStreamToBrowser = new BufferedOutputStream(out);
modifyHeaders(isKeepAlive);
resetRawHeaders();
logger.debug(new String(rawHeaders()));
TrafficLogger.storeResponseHeader(rawHeaders(), "modified");
outputStreamToBrowser.write(rawHeaders());
outputStreamToBrowser.flush();
}
public void modifyHeaders(boolean isKeepAlive) {
proxyKeepAlive(isKeepAlive);
// The Transfer-Encoding should never be chunked, since we are sending it sequentially
removeHeader("Transfer-Encoding");
removeHeader("Transfer-encoding");
removeHeader("Content-Security-Policy");
removeHeader("X-Frame-Options");
removeHeader("X-Content-Type-Options");
removeHeader("X-XSS-Protection");
setContentLength(getModifiedContentLength());
}
int getModifiedContentLength() {
return data() == null ? 0 : data().length;
}
public void sendBody(OutputStream out) throws IOException {
OutputStream bufferedOut = new BufferedOutputStream(out);
final byte[] data = data();
if (data != null) {
int start = 0;
int limit = Utils.BUFFER_SIZE;
int left = data.length;
while (left > 0) {
if (left < limit) limit = left;
bufferedOut.write(data, start, limit);
bufferedOut.flush();
start = start + limit;
left = left - limit;
}
}
bufferedOut.flush();
TrafficLogger.storeResponseBody(data, "modified");
}
public void cleanUp() {
}
}