abstracthttpresponse.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 2,408 行 · 第 1/4 页
JAVA
2,408 行
_request.killKeepalive(); // close, but don't force a flush finish(); } /** * Sends a redirect to the browser. If the URL is relative, it gets * combined with the current url. * * @param url the possibly relative url to send to the browser */ public void sendRedirect(String url) throws IOException { if (url == null) throw new NullPointerException(); if (_originalResponseStream.isCommitted()) throw new IllegalStateException(L.l("Can't sendRedirect() after data has committed to the client.")); _responseStream.clearBuffer(); _originalResponseStream.clearBuffer(); _responseStream = _originalResponseStream; resetBuffer(); setStatus(SC_MOVED_TEMPORARILY); String path = getAbsolutePath(url); CharBuffer cb = new CharBuffer(); for (int i = 0; i < path.length(); i++) { char ch = path.charAt(i); if (ch == '<') cb.append("%3c"); else if (ch < 0x80) cb.append(ch); else if (_charEncoding == null) { addHex(cb, ch); } else if (ch < 0x800) { int d1 = 0xc0 + ((ch >> 6) & 0x1f); int d2 = 0x80 + (ch & 0x3f); addHex(cb, d1); addHex(cb, d2); } else if (ch < 0x8000) { int d1 = 0xe0 + ((ch >> 12) & 0xf); int d2 = 0x80 + ((ch >> 6) & 0x3f); int d3 = 0x80 + (ch & 0x3f); addHex(cb, d1); addHex(cb, d2); addHex(cb, d3); } } path = cb.toString(); setHeader("Location", path); setHeader("Content-Type", "text/html"); // The data is required for some WAP devices that can't handle an // empty response. ServletOutputStream out = getOutputStream(); out.println("The URL has moved <a href=\"" + path + "\">here</a>"); // closeConnection(); if (_request instanceof AbstractHttpRequest) { AbstractHttpRequest request = (AbstractHttpRequest) _request; request.saveSession(); // #503 } close(); } private void addHex(CharBuffer cb, int hex) { int d1 = (hex >> 4) & 0xf; int d2 = (hex) & 0xf; cb.append('%'); cb.append(d1 < 10 ? (char) (d1 + '0') : (char) (d1 - 10 + 'a')); cb.append(d2 < 10 ? (char) (d2 + '0') : (char) (d2 - 10 + 'a')); } /** * Switch to raw socket mode. */ public void switchToRaw() throws IOException { throw new UnsupportedOperationException(L.l("raw mode is not supported in this configuration")); } /** * Switch to raw socket mode. */ public WriteStream getRawOutput() throws IOException { throw new UnsupportedOperationException(L.l("raw mode is not supported in this configuration")); } /** * Returns the absolute path for a given relative path. * * @param path the possibly relative url to send to the browser */ private String getAbsolutePath(String path) { int slash = path.indexOf('/'); int len = path.length(); for (int i = 0; i < len; i++) { char ch = path.charAt(i); if (ch == ':') return path; else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') continue; else break; } WebApp app = getRequest().getWebApp(); String hostPrefix = null; String host = _request.getHeader("Host"); String serverName = app.getHostName(); if (serverName == null || serverName.equals("")) serverName = _request.getServerName(); int port = _request.getServerPort(); if (hostPrefix != null && ! hostPrefix.equals("")) { } else if (serverName.startsWith("http:") || serverName.startsWith("https:")) hostPrefix = serverName; else if (host != null) { hostPrefix = _request.getScheme() + "://" + host; } else { hostPrefix = _request.getScheme() + "://" + serverName; if (serverName.indexOf(':') < 0 && port != 0 && port != 80 && port != 443) hostPrefix += ":" + port; } if (slash == 0) return hostPrefix + path; String uri = _request.getRequestURI(); String queryString = null; int p = path.indexOf('?'); if (p > 0) { queryString = path.substring(p + 1); path = path.substring(0, p); } p = uri.lastIndexOf('/'); if (p >= 0) path = uri.substring(0, p + 1) + path; try { if (queryString != null) return hostPrefix + InvocationDecoder.normalizeUri(path) + '?' + queryString; else return hostPrefix + InvocationDecoder.normalizeUri(path); } catch (IOException e) { throw new RuntimeException(e); } } /** * Returns true if the response already contains the named header. * * @param name name of the header to test. */ public boolean containsHeader(String name) { for (int i = 0; i < _headerKeys.size(); i++) { String oldKey = _headerKeys.get(i); if (oldKey.equalsIgnoreCase(name)) return true; } if (name.equalsIgnoreCase("content-type")) return _contentType != null; if (name.equalsIgnoreCase("content-length")) return _contentLength >= 0; return false; } /** * Returns the value of an already set output header. * * @param name name of the header to get. */ public String getHeader(String name) { ArrayList<String> keys = _headerKeys; int headerSize = keys.size(); for (int i = 0; i < headerSize; i++) { String oldKey = (String) keys.get(i); if (oldKey.equalsIgnoreCase(name)) return (String) _headerValues.get(i); } if (name.equalsIgnoreCase("content-type")) return _contentType; if (name.equalsIgnoreCase("content-length")) return _contentLength >= 0 ? String.valueOf(_contentLength) : null; return null; } /** * Sets a header, replacing an already-existing header. * * @param key the header key to set. * @param value the header value to set. */ public void setHeader(String key, String value) { if (_disableHeaders) return; else if (value == null) throw new NullPointerException(); if (setSpecial(key, value)) return; int i = 0; boolean hasHeader = false; ArrayList<String> keys = _headerKeys; ArrayList<String> values = _headerValues; for (i = keys.size() - 1; i >= 0; i--) { String oldKey = keys.get(i); if (oldKey.equalsIgnoreCase(key)) { if (hasHeader) { keys.remove(i); values.remove(i); } else { hasHeader = true; values.set(i, value); } } } if (! hasHeader) { keys.add(key); values.add(value); } } /** * Adds a new header. If an old header with that name exists, * both headers are output. * * @param key the header key. * @param value the header value. */ public void addHeader(String key, String value) { if (_disableHeaders) return; if (setSpecial(key, value)) return; _headerKeys.add(key); _headerValues.add(value); } /** * Special processing for a special value. */ protected boolean setSpecial(String key, String value) { int length = key.length(); if (256 <= length) return false; key.getChars(0, length, _headerBuffer, 0); switch (_headerCodes.get(_headerBuffer, length)) { case HEADER_CACHE_CONTROL: if (value.startsWith("max-age")) { } else if (value.equals("x-anonymous")) { } else _hasCacheControl = true; return false; case HEADER_CONNECTION: if ("close".equalsIgnoreCase(value)) _request.killKeepalive(); return true; case HEADER_CONTENT_TYPE: setContentType(value); return true; case HEADER_CONTENT_LENGTH: _contentLength = Long.parseLong(value); return true; case HEADER_DATE: return true; case HEADER_SERVER: return false; default: return false; } } public void removeHeader(String key) { if (_disableHeaders) return; ArrayList<String> keys = _headerKeys; ArrayList<String> values = _headerValues; for (int i = keys.size() - 1; i >= 0; i--) { String oldKey = keys.get(i); if (oldKey.equalsIgnoreCase(key)) { keys.remove(i); values.remove(i); return; } } } /** * Convenience for setting an integer header. An old header with the * same name will be replaced. * * @param name the header name. * @param value an integer to be converted to a string for the header. */ public void setIntHeader(String name, int value) { _cb.clear(); _cb.append(value); setHeader(name, _cb.toString()); } /** * Convenience for adding an integer header. If an old header already * exists, both will be sent to the browser. * * @param key the header name. * @param value an integer to be converted to a string for the header. */ public void addIntHeader(String key, int value) { _cb.clear(); _cb.append(value); addHeader(key, _cb.toString()); } /** * Convenience for setting a date header. An old header with the * same name will be replaced. * * @param name the header name. * @param value an time in milliseconds to be converted to a date string. */ public void setDateHeader(String name, long value) { _calendar.setGMTTime(value); setHeader(name, _calendar.printDate()); } /** * Convenience for adding a date header. If an old header with the * same name exists, both will be displayed. * * @param key the header name. * @param value an time in milliseconds to be converted to a date string. */ public void addDateHeader(String key, long value) { _calendar.setGMTTime(value); addHeader(key, _calendar.printDate()); } /** * Sets the content length of the result. In general, Resin will handle * the content length, but for things like long downloads adding the * length will give a valuable hint to the browser. * * @param length the length of the content. */ public void setContentLength(int length) { _contentLength = length; } /** * Returns the value of the content-length header. */ public long getContentLengthHeader() { return _contentLength; } /** * Sets the browser content type. If the value contains a charset, * the output encoding will be changed to match. * * <p>For example, to set the output encoding to use UTF-8 instead of * the default ISO-8859-1 (Latin-1), use the following: * <code><pre> * setContentType("text/html; charset=UTF-8"); * </pre></code> */ public void setContentType(String value) { if (isCommitted()) return; if (_disableHeaders || value == null) { _contentType = null; return; } else if (value == "text/html" || value.equals("text/html")) { _contentType = "text/html"; return; } _contentType = value; int length = value.length(); int i; int ch; for (i = 0; i < length && value.charAt(i) != ';' && ! Character.isWhitespace(value.charAt(i)); i++) { } if (i < length) _contentPrefix = _contentType.substring(0, i); else _contentPrefix = _contentType; while ((i = value.indexOf(';', i)) > 0) { int semicolon = i; for (i++; i < length && XmlChar.isWhitespace(value.charAt(i)); i++) { } int j; for (j = i + 1; j < length && ! XmlChar.isWhitespace((ch = value.charAt(j))) && ch != '='; j++) { } if (length <= j) break; else if ((ch = value.charAt(i)) != 'c' && ch != 'C') { } else if (value.substring(i, j).equalsIgnoreCase("charset")) { for (; j < length && XmlChar.isWhitespace(value.charAt(j)); j++) { } if (length <= j || value.charAt(j) != '=') continue; for (j++; j < length && XmlChar.isWhitespace(value.charAt(j)); j++) { } String encoding; if (j < length && value.charAt(j) == '"') { int k = ++j; for (; j < length && value.charAt(j) != '"'; j++) { } encoding = value.substring(k, j); } else { int k = j; for (k = j; j < length && ! XmlChar.isWhitespace(ch = value.charAt(j)) && ch != ';'; j++) { } encoding = value.substring(k, j); } int tail = value.indexOf(';', semicolon + 1); StringBuilder sb = new StringBuilder(); sb.append(value, 0, semicolon); if (tail > 0) sb.append(value, tail, value.length()); _contentType = sb.toString(); if (! _hasWriter) { _hasCharEncoding = true; _charEncoding = encoding; } break; } else i = j; } // XXX: conflict with servlet exception throwing order? try { _responseStream.setEncoding(_charEncoding); } catch (Exception e) { log.log(Level.WARNING, e.toString(), e); } } /** * Gets the content type. */ public String getContentType() { if (_contentType == null) return null; String charEncoding = getCharacterEncoding(); if (charEncoding != null) return _contentType + "; charset=" + charEncoding; else return _contentType; } /** * Gets the character encoding. */ public String getCharacterEncoding() { if (_charEncoding != null) return _charEncoding; WebApp app = _request.getWebApp(); String encoding = null; if (app != null) encoding = app.getCharacterEncoding(); if (encoding != null) return encoding; else return "iso-8859-1"; } /** * Sets the character encoding. */ public void setCharacterEncoding(String encoding) { if (isCommitted()) return; if (_hasWriter) return; _hasCharEncoding = true; if (encoding == null || encoding.equals("ISO-8859-1") || encoding.equals("")) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?