1 29 30 package com.caucho.server.http; 31 32 import com.caucho.server.cluster.Server; 33 import com.caucho.server.connection.AbstractHttpRequest; 34 import com.caucho.server.connection.AbstractHttpResponse; 35 import com.caucho.util.Alarm; 36 import com.caucho.util.CharBuffer; 37 import com.caucho.vfs.WriteStream; 38 39 import javax.servlet.http.Cookie ; 40 import java.io.IOException ; 41 import java.util.logging.Level ; 42 43 public class HttpResponse extends AbstractHttpResponse { 44 static final byte []_http10ok = "HTTP/1.0 200 OK".getBytes(); 45 static final byte []_http11ok = "HTTP/1.1 200 OK".getBytes(); 46 static final byte []_contentLengthBytes = "\r\nContent-Length: ".getBytes(); 47 static final byte []_contentTypeBytes = "\r\nContent-Type: ".getBytes(); 48 static final byte []_textHtmlBytes = "\r\nContent-Type: text/html".getBytes(); 49 static final byte []_charsetBytes = "; charset=".getBytes(); 50 static final byte []_textHtmlLatin1Bytes = "\r\nContent-Type: text/html; charset=iso-8859-1".getBytes(); 51 52 static final byte []_connectionCloseBytes = "\r\nConnection: close".getBytes(); 53 54 final byte []_resinServerBytes; 55 56 static final char []_connectionCb = "Connection".toCharArray(); 57 static final CharBuffer _closeCb = new CharBuffer("Close"); 58 59 private final HttpRequest _request; 60 61 private final byte []_dateBuffer = new byte[256]; 62 private int _dateBufferLength; 63 private final CharBuffer _dateCharBuffer = new CharBuffer(); 64 private long _lastDate; 65 66 71 HttpResponse(HttpRequest request) 72 { 73 super(request); 74 75 _request = request; 76 77 Server server = (Server) request.getDispatchServer(); 78 79 _resinServerBytes = ("\r\nServer: " + server.getServerHeader()).getBytes(); 80 } 81 82 85 public void switchToRaw() 86 throws IOException 87 { 88 clearBuffer(); 89 90 setStatus(101); 91 92 finish(); } 94 95 98 public WriteStream getRawOutput() 99 throws IOException 100 { 101 return _rawWrite; 102 } 103 104 107 public boolean isTop() 108 { 109 if (! (_request instanceof AbstractHttpRequest)) 110 return false; 111 else { 112 return ((AbstractHttpRequest) _request).isTop(); 113 } 114 } 115 116 119 protected void writeContinueInt(WriteStream os) 120 throws IOException 121 { 122 os.print("HTTP/1.1 100 Continue"); 123 124 if (! containsHeader("Server")) 125 os.write(_resinServerBytes, 0, _resinServerBytes.length); 126 127 os.print("\r\nContent-Length: 0"); 128 129 long now = Alarm.getCurrentTime(); 130 if (_lastDate + 1000 < now) { 131 fillDate(now); 132 } 133 134 os.write(_dateBuffer, 0, _dateBufferLength); 135 os.flush(); 136 } 137 138 148 protected boolean writeHeadersInt(WriteStream os, int length) 149 throws IOException 150 { 151 boolean isChunked = false; 152 153 int version = _request.getVersion(); 154 boolean debug = log.isLoggable(Level.FINE); 155 156 if (version < HttpRequest.HTTP_1_0) { 157 _request.killKeepalive(); 158 return false; 159 } 160 161 int statusCode = _statusCode; 162 if (statusCode == 200) { 163 if (version < HttpRequest.HTTP_1_1) 164 os.write(_http10ok, 0, _http10ok.length); 165 else 166 os.write(_http11ok, 0, _http11ok.length); 167 } else { 168 if (version < HttpRequest.HTTP_1_1) 169 os.print("HTTP/1.0 "); 170 else 171 os.print("HTTP/1.1 "); 172 173 os.write((statusCode / 100) % 10 + '0'); 174 os.write((statusCode / 10) % 10 + '0'); 175 os.write(statusCode % 10 + '0'); 176 os.write(' '); 177 os.print(_statusMessage); 178 } 179 180 if (debug) { 181 log.fine(_request.dbgId() + "HTTP/1.1 " + 182 _statusCode + " " + _statusMessage); 183 } 184 185 if (! containsHeader("Server")) 186 os.write(_resinServerBytes, 0, _resinServerBytes.length); 187 188 if (statusCode >= 400) { 189 removeHeader("ETag"); 190 removeHeader("Last-Modified"); 191 } 192 else if (_isNoCache) { 194 removeHeader("ETag"); 195 removeHeader("Last-Modified"); 196 197 setHeader("Expires", "Thu, 01 Dec 1994 16:00:00 GMT"); 200 os.print("\r\nCache-Control: no-cache"); 201 202 if (debug) { 203 log.fine(_request.dbgId() + "" + 204 "Expires: Thu, 01 Dec 1994 16:00:00 GMT"); 205 } 206 } 207 else if (! isPrivateCache()) { 208 } 209 else if (HttpRequest.HTTP_1_1 <= version) { 210 os.print("\r\nCache-Control: private"); 213 214 if (debug) 215 log.fine(_request.dbgId() + "Cache-Control: private"); 216 } 217 else if (! containsHeader("Cache-Control")) { 218 setHeader("Expires", "Thu, 01 Dec 1994 16:00:00 GMT"); 219 os.print("\r\nCache-Control: no-cache"); 220 221 if (debug) { 222 log.fine(_request.dbgId() + "" + 223 "Expires: Thu, 01 Dec 1994 16:00:00 GMT"); 224 } 225 } 226 227 int size = _headerKeys.size(); 228 for (int i = 0; i < size; i++) { 229 String key = (String ) _headerKeys.get(i); 230 os.write('\r'); 231 os.write('\n'); 232 os.print(key); 233 os.write(':'); 234 os.write(' '); 235 os.print((String ) _headerValues.get(i)); 236 237 if (debug) { 238 log.fine(_request.dbgId() + "" + 239 key + ": " + _headerValues.get(i)); 240 } 241 } 242 243 long now = Alarm.getCurrentTime(); 244 for (int i = 0; i < _cookiesOut.size(); i++) { 245 Cookie cookie = _cookiesOut.get(i); 246 int cookieVersion = cookie.getVersion(); 247 248 CharBuffer cb = _cb; 249 fillCookie(cb, cookie, now, cookieVersion, false); 251 os.print("\r\nSet-Cookie: "); 252 os.print(cb.getBuffer(), 0, cb.getLength()); 253 if (cookieVersion > 0) { 254 fillCookie(cb, cookie, now, cookieVersion, true); 255 os.print("\r\nSet-Cookie2: "); 256 os.print(cb.getBuffer(), 0, cb.getLength()); 257 } 258 259 if (debug) 260 log.fine(_request.dbgId() + "Set-Cookie: " + cb); 261 } 262 263 String contentType = _contentType; 264 265 if (contentType == null) { 266 } 267 else if (contentType != "text/html") { 268 os.write(_contentTypeBytes, 0, _contentTypeBytes.length); 269 os.print(contentType); 270 271 if (_charEncoding != null) { 272 os.write(_charsetBytes, 0, _charsetBytes.length); 273 os.print(_charEncoding); 274 } 275 else if (_hasWriter) { 276 os.write(_charsetBytes, 0, _charsetBytes.length); 277 os.print("iso-8859-1"); 278 } 279 } 280 else if (_charEncoding != null) { 281 os.write(_textHtmlBytes, 0, _textHtmlBytes.length); 282 os.write(_charsetBytes, 0, _charsetBytes.length); 283 os.print(_charEncoding); 284 } 285 else { 286 os.write(_textHtmlLatin1Bytes, 0, _textHtmlLatin1Bytes.length); 287 } 288 289 boolean hasContentLength = false; 290 if (_contentLength >= 0) { 291 os.write(_contentLengthBytes, 0, _contentLengthBytes.length); 292 os.print(_contentLength); 293 hasContentLength = true; 294 295 if (debug) 296 log.fine(_request.dbgId() + "Content-Length: " + _contentLength); 297 } 298 else if (statusCode == SC_NOT_MODIFIED || statusCode == SC_NO_CONTENT) { 299 hasContentLength = true; 300 os.write(_contentLengthBytes, 0, _contentLengthBytes.length); 301 os.print(0); 302 303 if (debug) 304 log.fine(_request.dbgId() + "Content-Length: 0"); 305 } 306 else if (length >= 0) { 307 os.write(_contentLengthBytes, 0, _contentLengthBytes.length); 308 os.print(length); 309 hasContentLength = true; 310 311 if (debug) 312 log.fine(_request.dbgId() + "Content-Length: " + length); 313 } 314 315 if (version < HttpRequest.HTTP_1_1) { 316 _request.killKeepalive(); 317 } 318 else { 319 327 328 if (! _request.allowKeepalive()) { 329 333 os.write(_connectionCloseBytes, 0, _connectionCloseBytes.length); 334 _request.killKeepalive(); 335 336 if (debug) 337 log.fine(_request.dbgId() + "Connection: close"); 338 } 339 } 340 341 if (HttpRequest.HTTP_1_1 <= version && 342 ! hasContentLength && 343 ! isHead()) { 344 os.print("\r\nTransfer-Encoding: chunked"); 345 isChunked = true; 346 347 if (debug) 348 log.fine(_request.dbgId() + "Transfer-Encoding: chunked"); 349 } 350 351 if (_lastDate / 1000 != now / 1000) { 352 fillDate(now); 353 } 354 355 if (isChunked) 356 os.write(_dateBuffer, 0, _dateBufferLength - 2); 357 else 358 os.write(_dateBuffer, 0, _dateBufferLength); 359 360 return isChunked; 361 } 362 363 private void fillDate(long now) 364 { 365 if (_lastDate / 60000 == now / 60000) { 366 _lastDate = now; 367 368 int sec = (int) (now / 1000 % 60); 369 370 int s2 = '0' + (sec / 10); 371 int s1 = '0' + (sec % 10); 372 373 _dateBuffer[31] = (byte) s2; 374 _dateBuffer[32] = (byte) s1; 375 return; 376 } 377 378 _lastDate = now; 379 _calendar.setGMTTime(now); 380 _dateCharBuffer.clear(); 381 _dateCharBuffer.append("\r\nDate: "); 382 _calendar.printDate(_dateCharBuffer); 383 384 char []cb = _dateCharBuffer.getBuffer(); 385 int len = _dateCharBuffer.getLength(); 386 387 for (int i = len - 1; i >= 0; i--) 388 _dateBuffer[i] = (byte) cb[i]; 389 390 _dateBuffer[len] = (byte) '\r'; 391 _dateBuffer[len + 1] = (byte) '\n'; 392 _dateBuffer[len + 2] = (byte) '\r'; 393 _dateBuffer[len + 3] = (byte) '\n'; 394 395 _dateBufferLength = len + 4; 396 } 397 398 public String toString() 399 { 400 return "HttpResponse" + _request.dbgId(); 401 } 402 } 403 | Popular Tags |