abstracthttpresponse.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 2,408 行 · 第 1/4 页
JAVA
2,408 行
((SessionImpl) session).saveBeforeHeaders(); if (_sessionId != null && ! _hasSessionCookie) { _hasSessionCookie = true; SessionManager manager = webApp.getSessionManager(); String cookieName; if (_request.isSecure()) cookieName = manager.getSSLCookieName(); else cookieName = manager.getCookieName(); CookieImpl cookie = new CookieImpl(cookieName, _sessionId); cookie.setVersion(manager.getCookieVersion()); String domain = manager.getCookieDomain(); if (domain != null) cookie.setDomain(domain); long maxAge = manager.getCookieMaxAge(); if (maxAge > 0) cookie.setMaxAge((int) (maxAge / 1000)); cookie.setPath("/"); cookie.setPort(manager.getCookiePort()); if (manager.getCookieSecure()) { cookie.setSecure(_request.isSecure()); /* else if (manager.getCookiePort() == null) cookie.setPort(String.valueOf(_request.getServerPort())); */ } addCookie(cookie); } _isChunked = writeHeadersInt(os, length, isHead); return _isChunked; } /** * Called to start caching. */ protected boolean startCaching(boolean isByte) { if (_isHeaderWritten) return false; _isHeaderWritten = true; if (_statusCode == SC_OK && ! _disableCaching) // && getBufferSize() > 0) return startCaching(_headerKeys, _headerValues, _contentType, _charEncoding, isByte); else return false; } /** * Tests to see if the response is cacheable. * * @param keys the header keys of the response * @param values the header values of the response * @param contentType the contentType of the response * @param charEncoding the character encoding of the response * * @return true if caching has started */ boolean startCaching(ArrayList<String> keys, ArrayList<String> values, String contentType, String charEncoding, boolean isByte) { if (_cacheInvocation == null) return false; /* // jsp/17ah else if (_responseStream != _originalResponseStream) { return false; } */ else if (! isCauchoResponseStream()) { return false; } else if (! (_originalRequest instanceof CauchoRequest)) { return false; } else if (! _allowCache) { return false; } else { CauchoRequest request = (CauchoRequest) _originalRequest; _newCacheEntry = _cacheInvocation.startCaching(request, this, keys, values, contentType, charEncoding, _contentLength); if (_newCacheEntry == null) { return false; } else if (isByte) { _cacheStream = _newCacheEntry.openOutputStream(); if (_cacheStream != null) _originalResponseStream.setByteCacheStream(_cacheStream); return _cacheStream != null; } else { _cacheWriter = _newCacheEntry.openWriter(); if (_cacheWriter != null) _originalResponseStream.setCharCacheStream(_cacheWriter); return _cacheWriter != null; } } } /** * Handle a SC_NOT_MODIFIED response. If we've got a cache, fill the * results from the cache. * * @param isTop if true, this is the top-level request. * * @return true if we filled from the cache */ private boolean handleNotModified(boolean isTop) throws IOException { if (_statusCode != SC_NOT_MODIFIED) { return false; } else if (_matchCacheEntry != null) { if (_originalResponseStream.isCommitted()) return false; // need to unclose because the not modified might be detected only // when flushing the data _originalResponseStream.clearClosed(); _isClosed = false; /* XXX: complications with filters */ if (_cacheInvocation != null && _cacheInvocation.fillFromCache((CauchoRequest) _originalRequest, this, _matchCacheEntry, isTop)) { _matchCacheEntry.updateExpiresDate(); _cacheInvocation = null; _matchCacheEntry = null; finish(); // Don't force a flush to avoid extra TCP packet return true; } } // server/13dh else if (_cacheInvocation != null) { CauchoRequest req = (CauchoRequest) _originalRequest; WebApp app = req.getWebApp(); long maxAge = app.getMaxAge(req.getRequestURI()); if (maxAge > 0 && ! containsHeader("Expires")) { setDateHeader("Expires", maxAge + Alarm.getCurrentTime()); } } return false; } abstract protected boolean writeHeadersInt(WriteStream os, int length, boolean isHead) throws IOException; /** * Sets true if the cache is only for the browser, but not * Resin's cache or proxies. * * <p>Since proxy caching also caches headers, cached pages with * session ids can't be cached in the browser. * * XXX: but doesn't this just mean that Resin shouldn't * send the session information back if the page is cached? * Because a second request where everything is identical * would see the same response except for the cookies. */ public void setPrivateCache(boolean isPrivate) { // XXX: let the webApp override this? _isPrivateCache = isPrivate; // server/12dm _allowCache = false; } /** * Sets true if the cache is only for the browser and * Resin's cache but not proxies. */ public void setPrivateOrResinCache(boolean isPrivate) { // XXX: let the webApp override this? _isPrivateCache = isPrivate; } /** * Returns the value of the private cache. */ public boolean getPrivateCache() { return _isPrivateCache; } /** * Returns true if the response should contain a Cache-Control: private */ protected boolean isPrivateCache() { return ! _hasCacheControl && _isPrivateCache; } /** * Set if the page is non-cacheable. */ public void setNoCache(boolean isNoCache) { _isNoCache = isNoCache; } /** * Returns true if the page is non-cacheable */ public boolean isNoCache() { return _isNoCache; } /** * Set if the page is non-cacheable. */ public void killCache() { _allowCache = false; // server/1b15 // setNoCache(true); } /** * Fills the response for a cookie * * @param cb result buffer to contain the generated string * @param cookie the cookie * @param date the current date * @param version the cookies version */ public boolean fillCookie(CharBuffer cb, Cookie cookie, long date, int version, boolean isCookie2) { // How to deal with quoted values? Old browsers can't deal with // the quotes. cb.clear(); cb.append(cookie.getName()); if (isCookie2) { cb.append("=\""); cb.append(cookie.getValue()); cb.append("\""); } else { cb.append("="); cb.append(cookie.getValue()); } String domain = cookie.getDomain(); if (domain != null && ! domain.equals("")) { if (isCookie2) { cb.append("; Domain="); cb.append('"'); cb.append(domain); cb.append('"'); } else { cb.append("; domain="); cb.append(domain); } } String path = cookie.getPath(); if (path != null && ! path.equals("")) { if (isCookie2) { cb.append("; Path="); cb.append('"'); cb.append(path); cb.append('"'); } else { // Caps from TCK test if (version > 0) cb.append("; Path="); else cb.append("; path="); cb.append(path); } } if (cookie.getSecure()) { if (version > 0) cb.append("; Secure"); else cb.append("; secure"); } int maxAge = cookie.getMaxAge(); if (version > 0) { if (maxAge >= 0) { cb.append("; Max-Age="); cb.append(maxAge); } cb.append("; Version="); cb.append(version); if (cookie.getComment() != null) { cb.append("; Comment=\""); cb.append(cookie.getComment()); cb.append("\""); } if (cookie instanceof CookieImpl) { CookieImpl extCookie = (CookieImpl) cookie; String port = extCookie.getPort(); if (port != null && isCookie2) { cb.append("; Port=\""); cb.append(port); cb.append("\""); } } } if (isCookie2) { } else if (maxAge == 0) { cb.append("; expires=Thu, 01-Dec-1994 16:00:00 GMT"); } else if (maxAge >= 0) { _calendar.setGMTTime(date + 1000L * (long) maxAge); cb.append("; expires="); cb.append(_calendar.format("%a, %d-%b-%Y %H:%M:%S GMT")); } WebApp app = _request.getWebApp(); if (app.getCookieHttpOnly()) { cb.append("; HttpOnly"); } return true; } protected ConnectionController getController() { if (_originalRequest instanceof AbstractHttpRequest) { AbstractHttpRequest request = (AbstractHttpRequest) _originalRequest; Connection conn = request.getConnection(); return conn.getController(); } else return null; } public TcpDuplexController upgradeProtocol(TcpDuplexHandler handler) { throw new IllegalStateException(L.l("'{0}' does not support upgrading", this)); } /** * Complete the request. Flushes the streams, completes caching * and writes the appropriate logs. */ public void finish() throws IOException { finish(false); } /** * Complete the request. Flushes the streams, completes caching * and writes the appropriate logs. * * @param isClose true if the response should be flushed. */ private void finish(boolean isClose) throws IOException { if (_isClosed) return; ConnectionController controller = null; try { if (_originalRequest instanceof AbstractHttpRequest) { AbstractHttpRequest request = (AbstractHttpRequest) _originalRequest; Connection conn = request.getConnection(); controller = conn.getController(); try { request.skip(); } catch (BadRequestException e) { log.warning(e.toString()); log.log(Level.FINE, e.toString(), e); } catch (Exception e) { log.log(Level.WARNING, e.toString(), e); } } if (_statusCode == SC_NOT_MODIFIED) { handleNotModified(_isTopCache); } if (controller != null && ! controller.isClosed()) isClose = false; // include() files finish too, but shouldn't force a flush, hence // flush is false // Never send flush? if (isClose) _responseStream.close(); else if (_responseStream != _originalResponseStream) _responseStream.finish(); else if (controller == null) _responseStream.finish(); else _responseStream.flush(); if (_responseStream != _originalResponseStream) { if (isClose) _originalResponseStream.close(); else if (controller == null) _originalResponseStream.finish(); } if (controller == null) _isClosed = true; if (_rawWrite == null) { } // server/0550 // else if (isClose) // _rawWrite.close(); else _rawWrite.flushBuffer(); if (_cacheInvocation == null) { } else if (_newCacheEntry != null) { OutputStream cacheStream = _cacheStream; _cacheStream = null; Writer cacheWriter = _cacheWriter; _cacheWriter = null; if (cacheStream != null) cacheStream.close(); if (cacheWriter != null) cacheWriter.close(); WebApp webApp = _request.getWebApp(); if (_statusCode == 200 && _allowCache && webApp != null && webApp.isActive()) { AbstractCacheFilterChain cache = _cacheInvocation; _cacheInvocation = null; AbstractCacheEntry cacheEntry = _newCacheEntry; _newCacheEntry = null; cache.finishCaching(cacheEntry); } } } catch (ClientDisconnectException e) { _request.killKeepalive(); if (isIgnoreClientDisconnect()) log.fine(e.toString()); else throw e; } catch (IOException e) { _request.killKeepalive(); throw e; } finally { if (controller == null) _isClosed = true; AbstractCacheFilterChain cache = _cacheInvocation; _cacheInvocation = null; AbstractCacheEntry cacheEntry = _newCacheEntry; _newCacheEntry = null; _cacheStream = null; _cacheWriter = null; if (cacheEntry != null) cache.killCaching(cacheEntry); } } public void killCaching() { AbstractCacheFilterChain cache = _cacheInvocation; _cacheInvocation = null; AbstractCacheEntry cacheEntry = _newCacheEntry; _newCacheEntry = null; if (cacheEntry != null) cache.killCaching(cacheEntry); } TempBuffer getBuffer() { return _tempBuffer; } protected final QDate getCalendar() { return _calendar; } protected void free() { _request = null; _originalRequest = null; _cacheInvocation = null; _newCacheEntry = null; _matchCacheEntry = null; _cacheStream = null; _cacheWriter = null; } static { _errors = new HashMap<String,String>(); _errors.put("100", "Continue"); _errors.put("101", "Switching Protocols"); _errors.put("200", "OK"); _errors.put("201", "Created"); _errors.put("202", "Accepted"); _errors.put("203", "Non-Authoritative Information"); _errors.put("204", "No Content"); _errors.put("205", "Reset Content"); _errors.put("206", "Partial Content"); _errors.put("300", "Multiple Choices"); _errors.put("301", "Moved Permanently"); _errors.put("302", "Found"); _errors.put("303", "See Other"); _errors.put("304", "Not Modified"); _errors.put("305", "Use Proxy"); _errors.put("307", "Temporary Redirect"); _errors.put("400", "Bad Request"); _errors.put("401", "Unauthorized"); _errors.put("402", "Payment Required"); _errors.put("403", "Forbidden"); _errors.put("404", "Not Found"); _errors.put("405", "Method Not Allowed"); _errors.put("406", "Not Acceptable"); _errors.put("407", "Proxy Authentication Required"); _errors.put("408", "Request Timeout"); _errors.put("409", "Conflict"); _errors.put("410", "Gone"); _errors.put("411", "Length Required"); _errors.put("412", "Precondition Failed"); _errors.put("413", "Request Entity Too Large"); _errors.put("414", "Request-URI Too Long"); _errors.put("415", "Unsupported Media Type"); _errors.put("416", "Requested Range Not Satisfiable"); _errors.put("417", "Expectation Failed"); _errors.put("500", "Internal Server Error"); _errors.put("501", "Not Implemented"); _errors.put("502", "Bad Gateway"); _errors.put("503", "Service Temporarily Unavailable"); _errors.put("504", "Gateway Timeout"); _errors.put("505", "Http Version Not Supported"); _headerCodes = new CaseInsensitiveIntMap(); _headerCodes.put("cache-control", HEADER_CACHE_CONTROL); _headerCodes.put("connection", HEADER_CONNECTION); _headerCodes.put("content-type", HEADER_CONTENT_TYPE); _headerCodes.put("content-length", HEADER_CONTENT_LENGTH); _headerCodes.put("date", HEADER_DATE); _headerCodes.put("server", HEADER_SERVER); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?