📄 protocol.java
字号:
} } finally { sendingRequest = false; } } /** * If not connected, connect to the underlying socket transport * and send the HTTP request headers. * <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 */ void startRequest() throws IOException { if (streamConnection != null) { return; } streamConnect(); sendRequestHeader(); } /** * Find a previous connection in the pool or try to connect to the * underlying stream transport. * * @exception IOException is thrown if the connection cannot be opened */ protected void streamConnect() throws IOException { streamConnection = connect(); /* * Because StreamConnection.open*Stream cannot be called twice * the HTTP connect method may have already open the streams * to connect to the proxy and saved them in the field variables * already. */ if (streamOutput != null) { return; } streamOutput = streamConnection.openDataOutputStream(); streamInput = streamConnection.openDataInputStream(); } /** * Gets the underlying stream connection. * * @return underlying stream connection */ protected StreamConnection getStreamConnection() { return streamConnection; } /** * Simplifies the sendRequest() method header functionality into one method * this is extremely helpful for persistent connection support and * retries. * * @exception IOException is thrown if the connection cannot be opened */ private void sendRequestHeader() throws IOException { StringBuffer reqLine; String filename; int numberOfKeys; /* * JTWI security policy for untrusted MIDlets says to add a * user-agent field with the value "UNTRUSTED/1.0" but still include * the applications value. The TCP and SSL protocols will deny the * standard ports to untrusted applications so they cannot get around * this field being added to their HTTP(S) requests. */ if (!ownerTrusted) { String newUserAgentValue; String origUserAgentValue = reqProperties.getPropertyIgnoreCase("User-Agent"); if (origUserAgentValue != null) { /* * HTTP header values can be concatenated, so original value * of the "User-Agent" header field should not be ignored in * this case */ newUserAgentValue = origUserAgentValue; if (-1 == origUserAgentValue.indexOf(UNTRUSTED)) { newUserAgentValue += " " + UNTRUSTED; } } else { String platformUA = Configuration.getProperty("User-Agent"); if (platformUA != null) { newUserAgentValue = platformUA; if (-1 == platformUA.indexOf(UNTRUSTED)) { newUserAgentValue += " " + UNTRUSTED; } } else { newUserAgentValue = UNTRUSTED; } } reqProperties.setPropertyIgnoreCase("User-Agent", newUserAgentValue); } // HTTP 1.0 requests must contain content length for proxies if (getRequestProperty("Content-Length") == null) { setRequestField("Content-Length", Integer.toString(bytesToWrite)); } reqLine = new StringBuffer(256); /* * HTTP RFC and CR#4402149, * if there is no path then add a slash ("/"). */ filename = url.path; if (filename == null) { filename = "/"; } /* * Note: the "ref" or fragment, is not sent to the server. */ reqLine.append(method); reqLine.append(" "); /* * Since we now use a tunnel instead of a proxy, we do not have * to send an absolute URI. The difference is that a proxy will * strip scheme and authority from the URI and a tunnel will not. * * For HTTPS purposes we will use the relative URI. * * Some HTTPS server's do not like to see "https" as the scheme of an * URI and only recognize "http". * examples: www.wellsfargo.com sends back html with not HTTP headers, * e-banking.abbeynational.co.uk sends back a 404 to all requests. * * It is better to not use the absolute URL, than to hardcode the * the scheme to "http" all the time since that did not work with * e-banking.abbeynational.co.uk. * * if (http_proxy != null) { * reqLine.append(protocol); * reqLine.append("://"); * reqLine.append(url.authority); * } */ if (isUseAbsUrl) { reqLine.append(protocol); reqLine.append("://"); reqLine.append(url.authority); } reqLine.append(filename); if (url.query != null) { reqLine.append("?"); reqLine.append(url.query); } reqLine.append(" "); reqLine.append(HTTP_VERSION); reqLine.append("\r\n"); /* * HTTP 1/1 requests require the Host header to distinguish * virtual host locations. */ setRequestField("Host", url.authority); if (chunkedOut) { /* * Signal the server that the body is chunked * by setting the Transfer-Encoding property to "chunked". */ setRequestField("Transfer-Encoding", "chunked"); } /* * Setup the various http header field/values defined and/or * required. */ numberOfKeys = reqProperties.size(); for (int i = 0; i < numberOfKeys; i++) { String key = (String)reqProperties.getKeyAt(i); if (key.equals("Content-Length")) { /* * If its CHUNK data - no content-length: size required. */ if (chunkedOut) { continue; } else { /* * Check that the output stream has been opened. */ if (writebuf == null) { reqLine.append("Content-Length: 0"); } else { reqLine.append("Content-Length: "); reqLine.append(bytesToWrite); } reqLine.append("\r\n"); } } else { reqLine.append(key); reqLine.append(": "); reqLine.append(reqProperties.getValueAt(i)); reqLine.append("\r\n"); } } reqLine.append("\r\n"); streamOutput.write(reqLine.toString().getBytes()); } /** * Write the http request body bytes to the output stream. * * @exception IOException */ protected void sendRequestBody() throws IOException { int start; int endOfData; int length; if ((writebuf == null) || (bytesToWrite == 0)) { return; } start = HTTP_OUTPUT_DATA_OFFSET; endOfData = HTTP_OUTPUT_DATA_OFFSET + bytesToWrite; length = bytesToWrite; /* * If a CHUNKed session then write out the chunk size first * with a trailing CRLF. * * reference: RFC2616 - section 3 protocol parameters * 3.6 transfer coding: * 3.6.1 chunked transfer coding: * chunk-body = chunk / last chunk / trailer / CRLF * * chunk = chunk-size / chunk-data / CRLF * last_chunk = "0" / CRLF * trailer = " " / CRLF * *indicates its done here. */ if (chunkedOut) { /* * For CHUNKed write out the chunk size with CRLF. * Put this before the data in write buffer. */ String temp = Integer.toHexString(bytesToWrite); int tempLen = temp.length(); writebuf[--start] = (byte)'\n'; writebuf[--start] = (byte)'\r'; for (int i = tempLen - 1; i >= 0; i--) { writebuf[--start] = (byte)temp.charAt(i); } length += tempLen + 2; /* * If a CHUNKed session then write out another CRLF and flush(). * Put this after the data in the write buffer. */ writebuf[endOfData++] = (byte)'\r'; writebuf[endOfData++] = (byte)'\n'; length += 2; } streamOutput.write(writebuf, start, length); bytesToWrite = 0; } /** * Finish the http request and reads the response headers. * * @exception IOException is thrown, if an I/O error occurs for final * stream output or on reading the response message line */ protected void finishRequestGetResponseHeader() throws IOException { // Even if we get an exception this request is finished requestFinished = true; /* * if this is a CHUNKed session write out the last set of CRLF */ if (chunkedOut) { /* * reference: RFC2616 - section 3 protocol parameters * 3.6 transfer coding: * 3.6.1 chunked transfer coding: * chunk-body = chunk / last chunk / trailer / CRLF * chunk = chunk-size / chunk-data / CRLF * * last_chunk = "0" / CRLF * * trailer = " " / CRLF * * indicates its done here. */ /* * write the last chunk (size=0 / CRLF) and the dummy trailer */ streamOutput.write("0\r\n\r\n".getBytes()); } streamOutput.flush(); readResponseMessage(streamInput); readHeaders(streamInput); /* * Ignore a continuation header and read the true headers again. * (CR# 4382226 discovered with Jetty HTTP 1.1 web server. */ if (responseCode == 100) { readResponseMessage(streamInput); readHeaders(streamInput); } } /** * Connect to the underlying network TCP transport. * If the proxy is configured, connect to it as tunnel first. * <p> * Warning: A subclass that implements this method, should not call this * method and should implement the disconnect method. * * @return network stream connection * @exception IOException is thrown if the connection cannot be opened */ protected StreamConnection connect() throws IOException { StreamConnection sc; com.sun.midp.io.j2me.socket.Protocol conn; if (!permissionChecked) { throw new SecurityException(); } sc = connectionPool.get(classSecurityToken, protocol, url.host, url.port); if (sc != null) { return sc; } // When no proxy server is set or proxy server supports CONNECT requests // the absolute URL is not used in GET requests isUseAbsUrl = false; if (http_proxy == null || url.host.equals("localhost") || url.host.equals("127.0.0.1")) { /* bypass proxy when trying to connect to the same computer * and not using explicit IP or host name */ conn = createConnection("//" + hostAndPort); return conn; } // connection through proxy server conn = createConnection("//" + http_proxy); // openData*Stream cannot be call twice, so save them for later streamOutput = conn.openDataOutputStream(); streamInput = conn.openDataInputStream(); try { isUseAbsUrl = !doTunnelHandshake(streamOutput, streamInput); } catch (IOException ioe) { String response = ioe.getMessage(); try { disconnect(conn); } catch (Exception e) { // do not over throw the handshake exception } if ((response != null) && (response.indexO
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -