httpstream.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 868 行 · 第 1/2 页
JAVA
868 行
/** * Read data from the connection. If the request hasn't yet been sent * to the server, send it. */ public int read(byte []buf, int offset, int length) throws IOException { try { return readInt(buf, offset, length); } catch (IOException e) { _isKeepalive = false; throw e; } catch (RuntimeException e) { _isKeepalive = false; throw e; } } /** * Read data from the connection. If the request hasn't yet been sent * to the server, send it. */ public int readInt(byte []buf, int offset, int length) throws IOException { if (! _didGet) getConnInput(); if (_isRequestDone) return -1; try { int len = length; if (_isChunked) { if (_chunkLength == 0) { int ch; for (ch = _rs.read(); ch >= 0 && (ch == '\r' || ch == '\n' || ch == ' '); ch = _rs.read()) { } for (; ch >= 0 && ch != '\n'; ch = _rs.read()) { if (ch >= '0' && ch <= '9') _chunkLength = 16 * _chunkLength + ch - '0'; else if (ch >= 'a' && ch <= 'f') _chunkLength = 16 * _chunkLength + ch - 'a' + 10; else if (ch >= 'A' && ch <= 'F') _chunkLength = 16 * _chunkLength + ch - 'A' + 10; } if (_chunkLength == 0) { _isRequestDone = true; return -1; } } else if (_chunkLength < 0) return -1; if (_chunkLength < len) len = _chunkLength; } else if (_contentLength < 0) { } else if (_contentLength == 0) { _isRequestDone = true; return -1; } else if (_contentLength < len) len = _contentLength; len = _rs.read(buf, offset, len); if (len < 0) { } else if (_isChunked) _chunkLength -= len; else if (_contentLength > 0) _contentLength -= len; return len; } catch (IOException e) { _isKeepalive = false; throw e; } catch (RuntimeException e) { _isKeepalive = false; throw e; } } /** * Sends the request and initializes the response. */ private void getConnInput() throws IOException { if (_didGet) return; try { getConnInputImpl(); } catch (IOException e) { _isKeepalive = false; throw e; } catch (RuntimeException e) { _isKeepalive = false; throw e; } } /** * Send the request to the server, wait for the response and parse * the headers. */ private void getConnInputImpl() throws IOException { if (_didGet) return; _didGet = true; if (_method != null) { _ws.print(_method); _ws.print(' '); } else if (_isPost) _ws.print("POST "); else if (_isHead) _ws.print("HEAD "); else _ws.print("GET "); // Not splitting query? Also fullpath? _ws.print(_path.getPath()); if (_path.getQuery() != null) { _ws.print("?"); _ws.print(_path.getQuery()); } _ws.print(" HTTP/1.1\r\n"); Object host = getAttribute("host"); _ws.print("Host: "); if (host != null) { _ws.print(host); } else if (_virtualHost != null) _ws.print(_virtualHost); else { _ws.print(_path.getHost()); if (_path.getPort() != 80) { _ws.print(":"); _ws.print(String.valueOf(_path.getPort())); } } _ws.print("\r\n"); Object userAgent = getAttribute("User-Agent"); if (userAgent == null) _ws.print("User-Agent: Mozilla/4.0 (compatible; Resin 1.0; JDK)\r\n"); else _ws.print("User-Agent: " + userAgent + "\r\n"); Iterator iter = getAttributeNames(); while (iter.hasNext()) { String name = (String) iter.next(); if (_reserved.get(name.toLowerCase()) == null) { Object value = getAttribute(name); if (value instanceof String[]) { String []values = (String []) value; for (int i = 0; i < values.length; i++) { _ws.print(name + ": " + values[i] + "\r\n"); } } else _ws.print(name + ": " + value + "\r\n"); } } if (! _isKeepalive) _ws.print("Connection: close\r\n"); if (_isPost) { int length = 0; if (_tempStream != null) length = _tempStream.getLength(); _ws.print("Content-Length: "); _ws.print(length); _ws.print("\r\n"); } _ws.print("\r\n"); if (_isPost) { MemoryStream tempStream = _tempStream; _tempStream = null; if (tempStream != null) { tempStream.writeToStream(_ws); tempStream.destroy(); } } _attributes.clear(); parseHeaders(); if (_isHead) _isRequestDone = true; } /** * Parse the headers returned from the server. */ private void parseHeaders() throws IOException { CharBuffer line = new CharBuffer(); // Skip blank lines int count = 0; do { line.clear(); if (! _rs.readln(line)) { _isKeepalive = false; return; } } while (line.length() == 0 && ++count < 10); if (line.length() == 0) { _isKeepalive = false; return; } if (line.startsWith("HTTP/1.1 100")) { count = 100; do { line.clear(); if (! _rs.readln(line)) { _isKeepalive = false; return; } } while (line.length() != 0 && count-- > 0); count = 100; do { line.clear(); if (! _rs.readln(line)) { _isKeepalive = false; return; } } while (line.length() == 0 && count-- > 0); } if (line.length() == 0) { _isKeepalive = false; return; } int i = 0; for (i = 0; i < line.length() && line.charAt(i) != ' '; i++) { } for (; i < line.length() && line.charAt(i) == ' '; i++) { } int status = 0; for (; i < line.length(); i++) { char ch = line.charAt(i); if (ch >= '0' && ch <= '9') status = 10 * status + ch - '0'; else break; } if (status != 200) _isKeepalive = false; else if (! line.startsWith("HTTP/1.1 ")) _isKeepalive = false; _attributes.put("status", String.valueOf(status)); CharBuffer key = new CharBuffer(); while (true) { line.clear(); if (! _rs.readln(line) || line.length() == 0) break; int lineLength = line.length(); for (i = 0; i < lineLength && Character.isWhitespace(line.charAt(i)); i++) { } key.clear(); for (; i < lineLength && ! Character.isWhitespace(line.charAt(i)) && line.charAt(i) != ':'; i++) { key.append((char) line.charAt(i)); } for (; i < lineLength && Character.isWhitespace(line.charAt(i)); i++) { } if (key.length() == 0 || lineLength <= i || line.charAt(i) != ':') continue; for (i++; i < lineLength && Character.isWhitespace(line.charAt(i)); i++) { } key.toLowerCase(); String value = line.substring(i); if (log.isLoggable(Level.FINE)) log.fine(key + ": " + value); if (key.matchesIgnoreCase("content-length")) { _contentLength = Integer.parseInt(value); } else if (key.matchesIgnoreCase("connection") && value.equalsIgnoreCase("close")) { _isKeepalive = false; } else if (key.matchesIgnoreCase("transfer-encoding") && value.equalsIgnoreCase("chunked")) { _isChunked = true; _chunkLength = 0; } _attributes.put(key.toLowerCase().toString(), value); } } /** * Returns the bytes still available. */ public int getAvailable() throws IOException { if (! _didGet) getConnInput(); if (_contentLength > 0) return _contentLength; else return _rs.getAvailable(); } /** * Close the connection. */ public void close() throws IOException { if (_isKeepalive) { // If recycling, read any unread data if (! _didGet) getConnInput(); if (! _isRequestDone) { if (_tempBuffer == null) _tempBuffer = new byte[256]; try { while (read(_tempBuffer, 0, _tempBuffer.length) > 0) { } } catch (IOException e) { _isKeepalive = false; } } } if (com.caucho.util.Alarm.isTest()) _isKeepalive = false; // XXX: if (_isKeepalive) { HttpStream oldSaved; long now = Alarm.getCurrentTime(); synchronized (LOCK) { oldSaved = _savedStream; _savedStream = this; _saveTime = now; } if (oldSaved != null && oldSaved != this) { oldSaved._isKeepalive = false; oldSaved.close(); } return; } try { try { if (_ws != null) _ws.close(); } catch (Throwable e) { } _ws = null; try { if (_rs != null) _rs.close(); } catch (Throwable e) { } _rs = null; try { if (_os != null) _os.close(); } catch (Throwable e) { } _os = null; try { if (_is != null) _is.close(); } catch (Throwable e) { } _is = null; } finally { if (_s != null) _s.close(); _s = null; } } static { _reserved = new HashMap<String,String>(); _reserved.put("user-agent", ""); _reserved.put("content-length", ""); _reserved.put("content-encoding", ""); _reserved.put("connection", ""); _reserved.put("host", ""); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?