📄 protocol.java
字号:
throw new IOException("connection already open"); } /* * The request headers can not be changed once the output * stream has been opened. */ if (maxOStreams == 0) { return; } // Look to see if a programmer embedded any extra fields. for (; ; ) { index = value.indexOf("\r\n", index); if (index == -1) { break; } // Allow legal header value continuations. CRLF + (SP|HT) index += 2; if (index >= value.length() || (value.charAt(index) != ' ' && value.charAt(index) != '\t')) { // illegal values passed for properties - raise an exception throw new IllegalArgumentException("illegal value found"); } } setRequestField(key, value); } /** * Add the named field to the list of request fields. * This method is where a subclass should override properties. * * @param key key for the request header field. * @param value the value for the request header field. */ protected void setRequestField(String key, String value) { /* https handles the proxy fields in a different way */ if (key.toLowerCase().startsWith("proxy-")) { proxyHeaders.setPropertyIgnoreCase(key, value); return; } /* * If application setRequestProperties("Connection", "close") * then we need to know this & take appropriate default close action */ if ((key.equalsIgnoreCase("connection")) && (value.equalsIgnoreCase("close"))) { ConnectionCloseFlag = true; } /* * Ref . Section 3.6 of RFC2616 : * All transfer-coding values are case-insensitive. */ if ((key.equalsIgnoreCase("transfer-encoding")) && (value.equalsIgnoreCase("chunked"))) { chunkedOut = true; } reqProperties.setPropertyIgnoreCase(key, value); } /** * Get the response code of the current request. * * @return numeric value of the parsed response code * @exception IOException is thrown if a network error occurs */ public int getResponseCode() throws IOException { ensureOpen(); sendRequest(); return responseCode; } /** * Get the response message of the current request. * * @return message associated with the current response header * @exception IOException is thrown if a network error occurs */ public String getResponseMessage() throws IOException { ensureOpen(); sendRequest(); return responseMsg; } /** * Get the Content-Length for the current response. * * @return length of data to be transmitted after the response headers */ public long getLength() { try { ensureOpen(); sendRequest(); } catch (IOException ioe) { // Fall through to return -1 for length } return contentLength; } /** * Get the Content-Type for the current response. * * @return MIME type of data to be transmitted after the response header */ public String getType() { try { return getHeaderField("content-type"); } catch (IOException x) { return null; } } /** * Get the Content-Encoding for the current response. * * @return encoding type of data to be transmitted after the * response headers */ public String getEncoding() { try { return getHeaderField("content-encoding"); } catch (IOException x) { return null; } } /** * Get the Expires header for the current response. * * @return expiration data for the transmitted data * * @exception IOException is thrown if a network error occurs */ public long getExpiration() throws IOException { return getHeaderFieldDate("expires", 0); } /** * Get the Date header for the current response. * * @return timestamp for the data transmission event * * @exception IOException is thrown if a network error occurs */ public long getDate() throws IOException { return getHeaderFieldDate("date", 0); } /** * Get the Last-Modified date header for the current response. * * @return timestamp for the transmitted data last modification * * @exception IOException is thrown if a network error occurs */ public long getLastModified() throws IOException { return getHeaderFieldDate("last-modified", 0); } /** * Get the named header field for the current response. * * @param name header field to be examined * @return value of requested header, if found, otherwise null * * @exception IOException is thrown if a network error occurs */ public String getHeaderField(String name) throws IOException { ensureOpen(); sendRequest(); return (headerFields.getPropertyIgnoreCase(name)); } /** * Get the indexed header field for the current response. * * @param index header field offset to be examined * @return key name of requested header, if found, otherwise null * * @exception IOException is thrown if a network error occurs */ public String getHeaderField(int index) throws IOException { ensureOpen(); sendRequest(); if (index >= headerFields.size()) { return null; } return (headerFields.getValueAt(index)); } /** * Get the indexed header field value for the current response. * * @param index header field value offset to be examined * @return value of requested header, if found, otherwise null * * @exception IOException is thrown if a network error occurs */ public String getHeaderFieldKey(int index) throws IOException { ensureOpen(); sendRequest(); if (index >= headerFields.size()) return null; return ((String)(headerFields.getKeyAt(index))); } /** * Get the named header field for the current response and return a * numeric value for the parsed field, with a supplied default value * if the field does not exist or can not be parsed cleanly. * * @param name of the field to be examined * @param def default value to use, if field is not parsable * @return numeric value of requested header, if found, otherwise * supplied default is returned * * @exception IOException is thrown if a network error occurs */ public int getHeaderFieldInt(String name, int def) throws IOException { ensureOpen(); sendRequest(); try { return Integer.parseInt(getHeaderField(name)); } catch (IllegalArgumentException iae) { // fall through } catch (NullPointerException npe) { // fall through } return def; } /** * Get the named header field for the current response and return a date * value for the parsed field,with a supplied default value if the field * does not exist or can not be parsed cleanly. * * @param name of the field to be examined * @param def default value to use, if field is not parsable * @return date value of requested header, if found, otherwise * supplied default is returned * * @exception IOException is thrown if a network error occurs */ public long getHeaderFieldDate(String name, long def) throws IOException { ensureOpen(); sendRequest(); try { return DateParser.parse(getHeaderField(name)); } catch (NumberFormatException nfe) { // fall through } catch (IllegalArgumentException iae) { // fall through } catch (NullPointerException npe) { // fall through } return def; } /** * If not connected, connect to the underlying socket transport * and send the HTTP request and get the response header. * <P> * If an http_proxy was specified the socket connection will be made to * the proxy server and the requested URL will include the full http URL. * <P> * On output the Content-Length header is included in the request based * on the size of the buffered output array. * <P> * This routine inserts the Host header needed for HTTP 1.1 virtual host * addressing. * <P> * This routine also receives the reply response and parses the headers * for easier access. After the headers are parsed the application has * access to the raw data from the socket stream connection. * * @exception IOException is thrown if the connection cannot be opened */ protected void sendRequest() throws IOException { sendRequest(false, true); } /** * If not connected, connect to the underlying socket transport * and send the HTTP request and get the response header. * <P> * If an http_proxy was specified the socket connection will be made to * the proxy server and the requested URL will include the full http URL. * <P> * On output the Content-Length header is included in the request based * on the size of the buffered output array. * <P> * This routine inserts the Host header needed for HTTP 1.1 virtual host * addressing. * <P> * This routine also receives the reply response and parses the headers * for easier access. After the headers are parsed the application has * access to the raw data from the socket stream connection. * * @param chunkData if true chunk data sent to the server * @param readResponseHeader if true, read the response header * * @exception IOException is thrown if the connection cannot be opened */ private void sendRequest(boolean chunkData, boolean readResponseHeader) throws IOException { int bytesToRetry; if (sendingRequest || requestFinished) { return; } sendingRequest = true; try { if (chunkData) { chunkedOut = true; } bytesToRetry = bytesToWrite; try { startRequest(); sendRequestBody(); if (readResponseHeader) { finishRequestGetResponseHeader(); } } catch (IOException ioe) { if (!(streamConnection instanceof StreamConnectionElement)) { /* * This was a connection opened during this transaction. * So do not try to recover. */ throw ioe; } try { connectionPool.remove( (StreamConnectionElement)streamConnection); } catch (Exception e) { // do not over throw the previous exception } if (firstChunkSent) { // can't retry since we do not have the previous chunk throw new IOException("Persistent connection dropped " + "after first chunk sent, cannot retry"); } streamConnection = null; streamInput = null; streamOutput = null; bytesToWrite = bytesToRetry; startRequest(); sendRequestBody(); if (readResponseHeader) { finishRequestGetResponseHeader(); } } if (chunkedOut) { firstChunkSent = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -