TcpSocketLink tcpConn = null;
if (_request.getConnection() instanceof TcpSocketLink)
tcpConn = (TcpSocketLink) _request.getConnection();
WebApp webApp = request.getWebApp();
String contentType = response.getContentTypeImpl();
String charEncoding = response.getCharacterEncodingImpl();
WriteStream os = getRawWrite();
int statusCode = response.getStatus();
if (statusCode == 200) {
if (version < HttpRequest.HTTP_1_1)
os.write(_http10ok, 0, _http10ok.length);
else
os.write(_http11ok, 0, _http11ok.length);
} else {
if (version < HttpRequest.HTTP_1_1)
os.printLatin1("HTTP/1.0 ");
else
os.printLatin1("HTTP/1.1 ");
os.write((statusCode / 100) % 10 + '0');
os.write((statusCode / 10) % 10 + '0');
os.write(statusCode % 10 + '0');
os.write(' ');
os.printLatin1(response.getStatusMessage());
}
if (debug) {
log.fine(_request.dbgId() + "HTTP/1.1 " +
statusCode + " " + response.getStatusMessage());
}
boolean isUpgrade = false;
if (tcpConn != null && tcpConn.isDuplex()) {
isUpgrade = true;
String upgrade = getHeader("Upgrade");
if (upgrade != null) {
os.printLatin1("\r\nUpgrade: ");
os.printLatin1NoLf(upgrade);
}
os.printLatin1("\r\nConnection: Upgrade");
_request.killKeepalive("duplex/upgrade");
if (debug)
log.fine(_request.dbgId() + "Connection: Upgrade");
}
if (! containsHeader("Server")) {
os.write(_resinServerBytes, 0, _resinServerBytes.length);
}
if (statusCode >= 400) {
removeHeader("ETag");
removeHeader("Last-Modified");
}
else if (statusCode == HttpServletResponse.SC_NOT_MODIFIED
|| statusCode == HttpServletResponse.SC_NO_CONTENT) {
// php/1b0k
contentType = null;
}
else if (response.isCacheControl()) {
// application manages cache control
}
else if (response.isNoCache()) {
// server/1b15
removeHeader("ETag");
removeHeader("Last-Modified");
// even in case of 302, this may be needed for filters which
// automatically set cache headers
setHeaderImpl("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
os.printLatin1("\r\nCache-Control: no-cache");
if (debug) {
log.fine(_request.dbgId() + "" +
"Cache-Control: no-cache");
}
}
else if (response.isNoCacheUnlessVary()
&& ! containsHeader("Vary")) {
os.printLatin1("\r\nCache-Control: private");
if (debug) {
log.fine(_request.dbgId() + "Cache-Control: private");
}
}
else if (response.isPrivateCache()) {
if (HttpRequest.HTTP_1_1 <= version) {
// technically, this could be private="Set-Cookie,Set-Cookie2"
// but caches don't recognize it, so there's no real extra value
os.printLatin1("\r\nCache-Control: private");
if (debug)
log.fine(_request.dbgId() + "Cache-Control: private");
}
else {
setHeaderImpl("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
os.printLatin1("\r\nCache-Control: no-cache");
if (debug) {
log.fine(_request.dbgId() + "CacheControl: no-cache");
}
}
}
int size = _headerKeys.size();
for (int i = 0; i < size; i++) {
String key = (String) _headerKeys.get(i);
if (isUpgrade && "Upgrade".equalsIgnoreCase(key))
continue;
os.write('\r');
os.write('\n');
os.printLatin1NoLf(key);
os.write(':');
os.write(' ');
os.printLatin1NoLf((String) _headerValues.get(i));
if (debug) {
log.fine(_request.dbgId() + "" +
key + ": " + _headerValues.get(i));
}
}
long now = Alarm.getCurrentTime();
ArrayList<Cookie> cookiesOut = response.getCookies();
if (cookiesOut != null) {
for (int i = 0; i < cookiesOut.size(); i++) {
Cookie cookie = cookiesOut.get(i);
int cookieVersion = cookie.getVersion();
CharBuffer cb = _cb;
// XXX:
fillCookie(cb, cookie, now, cookieVersion, false);
os.printLatin1("\r\nSet-Cookie: ");
os.printLatin1(cb.getBuffer(), 0, cb.getLength());
if (cookieVersion > 0) {
fillCookie(cb, cookie, now, cookieVersion, true);
os.printLatin1("\r\nSet-Cookie2: ");
os.printLatin1(cb.getBuffer(), 0, cb.getLength());
}
if (debug)
log.fine(_request.dbgId() + "Set-Cookie: " + cb);
}
}
if (contentType != null) {
if (charEncoding == null) {
if (webApp != null)
charEncoding = webApp.getCharacterEncoding();
// always use a character encoding to avoid XSS attacks (?)
if (charEncoding == null)
charEncoding = "utf-8";
}