📄 protocol.java
字号:
if (totalbytesread == chunksize) { /* * read the end of the chunk and get the size of the * the next if there is one */ if (!chunkedIn) { /* * non-chucked data is treated as one big chunk so there * is no more data so just return as if there are no * more chunks */ eof = true; return -1; } skipEndOfChunkCRLF(); chunksize = readChunkSize(); if (chunksize == 0) { eof = true; /* * REFERENCE: HTTP1.1 document * SECTION: 3.6.1 Chunked Transfer Coding * in some cases there may be an OPTIONAL trailer * containing entity-header fields. since we don't support * the available() method for TCP socket input streams and * for performance and reuse reasons we do not attempt to * clean up the current connections input stream. * check readResponseMessage() method in this class for * more details */ return -1; } /* * we have not read any bytes from this new chunk */ totalbytesread = 0; } int bytesToRead = chunksize - totalbytesread; if (len >= bytesToRead) { /* * No need to buffer, if the caller has given a big buffer. */ rc = streamInput.read(b, off, bytesToRead); } else if (len >= inputBufferSize) { /* * No need to buffer, if the caller has given a big buffer. */ rc = streamInput.read(b, off, len); } else { if (inputBufferSize >= bytesToRead) { rc = streamInput.read(readbuf, 0, bytesToRead); } else { rc = streamInput.read(readbuf, 0, inputBufferSize); } bytesleft = rc; bytesread = 0; } if (rc == -1) { /* * Network problem or the wrong length was sent by the server. */ eof = true; throw new IOException("unexpected end of stream"); } totalbytesread += rc; if (bytesleft == 0) { /* * The data was read directly into the caller's buffer. */ return rc; } } rc = readFromBuffer(b, off, len); return rc; } /** * Read the chunk size from the input. * It is a hex length followed by optional headers (ignored). * and terminated with CRLF. * * @return size of the buffered read */ private int readChunkSize() throws IOException { int size = -1; try { String chunk = null; try { chunk = readLine(streamInput); } catch (IOException ioe) { /* throw new IOException(ioe.getMessage()); */ } if (chunk == null) { throw new IOException("No Chunk Size"); } int i; for (i = 0; i < chunk.length(); i++) { char ch = chunk.charAt(i); if (Character.digit(ch, 16) == -1) break; } /* look at extensions?.... */ size = Integer.parseInt(chunk.substring(0, i), 16); } catch (NumberFormatException e) { throw new IOException("invalid chunk size number format"); } return size; } /** * Skips the CRLF at the end of each chunk in the InputStream. * * @exception IOException if the LF half of the ending CRLF * is missing. */ private void skipEndOfChunkCRLF() throws IOException { int ch; if (stringbuffer.length() > 1) { /* * readChunkSizeNonBlocking does not leave CRLF in the buffer * so assume that the ending CRLF has been skipped already */ return; } // readChunkSizeNonBlocking could have left a \r single in the buffer if (stringbuffer.length() == 1) { if (stringbuffer.charAt(0) != '\r') { // assume that the ending CRLF has been skipped already return; } // remove the '\r' stringbuffer.setLength(0); ch = streamInput.read(); if (ch != '\n') { throw new IOException("missing the LF of an expected CRLF"); } return; } ch = streamInput.read(); if (ch != '\r') { /* * assume readChunkSizeNonBlocking has read the end of the chunk * and that this is the next chunk size, so put the char in the * buffer for readChunkSize and return */ stringbuffer.append(ch); return; } ch = streamInput.read(); if (ch != '\n') { throw new IOException("missing the LF of an expected CRLF"); } } /** * Writes <code>len</code> bytes from the specified byte array * starting at offset <code>off</code> to this output stream. * * <p> * This method can only be called after an OutputStream setup has be * done. * * @param b the data. * @param off the start offset in the data. * @param len the number of bytes to write. * * @return int number of bytes written to stream * * @exception IOException if an I/O error occurs. In particular, * an <code>IOException</code> is thrown if the output * stream is closed. * * @exception IllegalStateException if an attempt was made to * write after the request has finished. */ protected int writeBytes(byte b[], int off, int len) throws IOException { int bytesToCopy; if (requestFinished) { throw new IllegalStateException( "Write attempted after request finished"); } if (bytesToWrite == outputDataSize) { /* * Send the bytes in the write buffer as a chunk to the server * so more bytes can be put in the buffer. */ sendRequest(true, false); } /* * Our parent class will call this method in a loop until all the bytes * are written. So this method does not have to process all the bytes * in one call. */ bytesToCopy = outputDataSize - bytesToWrite; if (len < bytesToCopy) { bytesToCopy = len; } System.arraycopy(b, off, writebuf, HTTP_OUTPUT_DATA_OFFSET + bytesToWrite, bytesToCopy); bytesToWrite += bytesToCopy; return bytesToCopy; } /** * If any output data, turn on chunking send it to the server. * * @exception IOException if an I/O error occurs * * @exception IllegalStateException if there was an attempt was made to * flush after the request has finished. */ public void flush() throws IOException { if (bytesToWrite <= 0) { return; } if (requestFinished) { throw new IllegalStateException( "Flush attempted after request finished"); } sendRequest(true, false); } /** * Get the original URL used to open the HTTP connection. * * @return HTTP URL used in the current connection */ public String getURL() { return url.toString(); } /** * Get the protocol scheme parsed from the URL. * * @return protocol scheme is "http" */ public String getProtocol() { return protocol; } /** * Get the host name parsed from the URL. * * @return host name from the parsed URL */ public String getHost() { return url.host; } /** * Get the file path name parsed from the URL. * * @return file path name from the parsed URL */ public String getFile() { return url.path; } /** * Get the fragment identifier parsed from the URL. * * @return reference component from the parsed URL */ public String getRef() { return url.fragment; } /** * Get the query string parsed from the URL. * * @return query string from the parsed URL */ public String getQuery() { return url.query; } /** * Get the query string parsed from the URL. * * @return query string from the parsed URL */ public int getPort() { return url.port; } /** * Get the request method of the current connection. * * @return request method is GET, HEAD or POST * @see #setRequestMethod */ public String getRequestMethod() { return method; } /** * Set the request method of the current connection. * * @param method request method is GET, HEAD or POST * @exception IOException is thrown if the connection is already open * @see #getRequestMethod */ public void setRequestMethod(String method) throws IOException { ensureOpen(); if (streamConnection != null) { throw new IOException("connection already open"); } /* * The request method can not be changed once the output * stream has been opened. */ if (maxOStreams == 0) { return; } if (!method.equals(HEAD) && !method.equals(GET) && !method.equals(POST)) { throw new IOException("unsupported method: " + method); } this.method = method; } /** * Get the request header value for the named property. * * @param key property name of specific HTTP 1.1 header field * @return value of the named property, if found, null otherwise. * @see #setRequestProperty */ public String getRequestProperty(String key) { /* https handles the proxy fields in a different way */ if (key.toLowerCase().startsWith("proxy-")) { return proxyHeaders.getPropertyIgnoreCase(key); } return reqProperties.getPropertyIgnoreCase(key); } /** * Set the request header name/value of specific HTTP 1.1 header field. * * @param key property name * @param value property value * @exception IllegalArgumentException is thrown if value contains CRLF. * @exception IOException If some other kind of I/O error occurs. * @see #getRequestProperty */ public void setRequestProperty(String key, String value) throws IOException { int index = 0; ensureOpen(); if (streamConnection != null) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -