{"id":1541,"date":"2017-08-29T16:42:08","date_gmt":"2017-08-29T08:42:08","guid":{"rendered":"http:\/\/coderbee.net\/?p=1541"},"modified":"2019-01-06T20:08:56","modified_gmt":"2019-01-06T12:08:56","slug":"httpurlconnection-%e8%87%aa%e5%8a%a8-%e9%87%8d%e5%a4%8d-%e6%8f%90%e4%ba%a4-post","status":"publish","type":"post","link":"https:\/\/coderbee.net\/index.php\/java\/20170829\/1541","title":{"rendered":"HttpURLConnection \u81ea\u52a8 \u91cd\u590d \u63d0\u4ea4 POST"},"content":{"rendered":"<h2>\u4e00\u3001\u95ee\u9898<\/h2>\n<p>\u6d4b\u8bd5\u73af\u5883\u5076\u5c14\u53cd\u9988\u6709\u4e2a\u670d\u52a1 HTTP \u8bf7\u6c42\u91cd\u590d\u63d0\u4ea4\u3002\u8fd9\u4e2a HTTP \u8bf7\u6c42\u5934\u91cc\u6709\u4e2a UUID \u4f5c\u4e3a\u552f\u4e00\u6807\u8bc6\uff0c\u4f1a\u5b58\u5165\u65e5\u5fd7\u8868\u91cc\u4f5c\u4e3a\u4e3b\u952e\u7684\uff0c\u56e0\u4e3a\u4e3b\u952e\u51b2\u7a81\uff0c\u670d\u52a1\u7aef\u662f\u6709\u6253\u5370\u5f02\u5e38\u4fe1\u606f\u7684\uff0c\u4f46\u5ba2\u6237\u7aef\u5b8c\u5168\u6b63\u5e38\uff0c\u6ca1\u6709\u4efb\u4f55\u9519\u8bef\u4fe1\u606f\uff0c\u4e1a\u52a1\u903b\u8f91\u4e5f\u6b63\u5e38\u5b8c\u6210\u4e86\u3002<\/p>\n<p>\u901a\u8fc7\u67e5\u770b\u5ba2\u6237\u7aef\u3001\u670d\u52a1\u7aef\u4e24\u8fb9\u7684\u65e5\u5fd7\uff0c\u6000\u7591\u662f <code>HttpURLConnection<\/code> \u81ea\u52a8\u8fdb\u884c\u4e86\u8bf7\u6c42\u91cd\u8bd5\u3002\u5728\u7f51\u4e0a\u641c\u7d22\u4e00\u756a\uff0c\u53d1\u73b0\u5df2\u7ecf\u6709\u4eba\u63d0\u4e86 bug <a href=\"http:\/\/bugs.java.com\/bugdatabase\/view_bug.do?bug_id=6427251\">JDK-6427251<\/a> \uff0c\u6309\u7167\u8fd9\u4e2a\u7684\u64cd\u4f5c\u6b65\u9aa4\u662f\u53ef\u4ee5\u590d\u73b0\u7684\uff0c\u5305\u62ec JDK 8 \u7684\u7248\u672c\u3002<\/p>\n<p><code>HttpURLConnection<\/code> \u91c7\u7528 Sun \u79c1\u6709\u7684\u4e00\u4e2a HTTP \u534f\u8bae\u5b9e\u73b0\u7c7b\uff1a <a href=\"http:\/\/www.docjar.com\/html\/api\/sun\/net\/www\/http\/HttpClient.java.html\">HttpClient.java<\/a><\/p>\n<p>\u5173\u952e\u662f\u4e0b\u9762\u8fd9\u6bb5\u53d1\u9001\u8bf7\u6c42\u3001\u89e3\u6790\u54cd\u5e94\u5934\u7684\u65b9\u6cd5\uff1a<\/p>\n<pre><code class=\"java\">  569       \/** Parse the first line of the HTTP request.  It usually looks\n  570           something like: \"HTTP\/1.0 &lt;number&gt; comment\\r\\n\". *\/\n  571   \n  572       public boolean parseHTTP(MessageHeader responses, ProgressSource pi, HttpURLConnection httpuc)\n  573       throws IOException {\n  574           \/* If \"HTTP\/*\" is found in the beginning, return true.  Let\n  575            * HttpURLConnection parse the mime header itself.\n  576            *\n  577            * If this isn't valid HTTP, then we don't try to parse a header\n  578            * out of the beginning of the response into the responses,\n  579            * and instead just queue up the output stream to it's very beginning.\n  580            * This seems most reasonable, and is what the NN browser does.\n  581            *\/\n  582   \n  583           try {\n  584               serverInput = serverSocket.getInputStream();\n  585               if (capture != null) {\n  586                   serverInput = new HttpCaptureInputStream(serverInput, capture);\n  587               }\n  588               serverInput = new BufferedInputStream(serverInput);\n  589               return (parseHTTPHeader(responses, pi, httpuc));\n  590           } catch (SocketTimeoutException stex) {\n  591               \/\/ We don't want to retry the request when the app. sets a timeout\n  592               \/\/ but don't close the server if timeout while waiting for 100-continue\n  593               if (ignoreContinue) {\n  594                   closeServer();\n  595               }\n  596               throw stex;\n  597           } catch (IOException e) {\n  598               closeServer();\n  599               cachedHttpClient = false;\n  600               if (!failedOnce &amp;&amp; requests != null) {\n  601                   failedOnce = true;\n  602                   if (httpuc.getRequestMethod().equals(\"POST\") &amp;&amp; (!retryPostProp || streaming)) {\n  603                       \/\/ do not retry the request\n  604                   }  else {\n  605                       \/\/ try once more\n  606                       openServer();\n  607                       if (needsTunneling()) {\n  608                           httpuc.doTunneling();\n  609                       }\n  610                       afterConnect();\n  611                       writeRequests(requests, poster);\n  612                       return parseHTTP(responses, pi, httpuc);\n  613                   }\n  614               }\n  615               throw e;\n  616           }\n  617   \n  618       }\n<\/code><\/pre>\n<p>\u5728\u7b2c 600 &#8211; 614 \u884c\u7684\u4ee3\u7801\u91cc\uff1a<\/p>\n<ul>\n<li>failedOnce \u9ed8\u8ba4\u662f false\uff0c\u8868\u793a\u662f\u5426\u5df2\u7ecf\u5931\u8d25\u8fc7\u4e00\u6b21\u4e86\u3002\u8fd9\u4e5f\u5c31\u9650\u5236\u4e86\u6700\u591a\u53d1\u9001 2 \u6b21\u8bf7\u6c42\u3002<\/li>\n<li>httpuc \u662f\u8bf7\u6c42\u76f8\u5173\u7684\u4fe1\u606f\u3002<\/li>\n<li>retryPostProp \u9ed8\u8ba4\u662f <code>true<\/code>\uff0c\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4\u884c\u53c2\u6570(<code>-Dsun.net.http.retryPost=false<\/code>)\u6765\u6307\u5b9a\u503c\u3002<\/li>\n<li>streaming\uff1a\u9ed8\u8ba4 <code>false<\/code>\u3002 <code>true<\/code> if we are in streaming mode (fixed length or chunked) \u3002<\/li>\n<\/ul>\n<p>\u901a\u8fc7 Linux \u7684\u547d\u4ee4 <code>socat tcp4-listen:8080,fork,reuseaddr system:\"sleep 1\"\\!\\!stdout<\/code> \u5efa\u7acb\u4e00\u4e2a\u53ea\u63a5\u6536\u8bf7\u6c42\u3001\u4e0d\u8fd4\u56de\u54cd\u5e94\u7684 HTTP \u670d\u52a1\u5668\u3002<br \/>\n\u5bf9\u4e8e POST \u8bf7\u6c42\uff0c\u7b2c\u4e00\u6b21\u8bf7\u6c42\u53d1\u9001\u51fa\u53bb\u540e\u89e3\u6790\u54cd\u5e94\u4f1a\u78b0\u5230\u6d41\u63d0\u524d\u7ed3\u675f\uff0c\u8fd9\u662f\u4e2a <code>SocketException: Unexpected end of file from server<\/code>\uff0c<code>parseHTTP<\/code> \u6355\u83b7\u540e\u53d1\u73b0\u6ee1\u8db3\u4e0a\u9762\u7684\u6761\u4ef6\u5c31\u4f1a\u8fdb\u884c\u91cd\u8bd5\u3002\u670d\u52a1\u7aef\u5c31\u4f1a\u6536\u5230\u7b2c\u4e8c\u4e2a\u8bf7\u6c42\u3002<\/p>\n<p><!--more--><\/p>\n<h2>\u4e8c\u3001\u89e3\u51b3\u65b9\u6848<\/h2>\n<ol>\n<li>\u7981\u7528 HttpURLConnection \u7684\u91cd\u8bd5\u673a\u5236\uff0c\u901a\u8fc7\u547d\u4ee4\u884c\u53c2\u6570 <code>-Dsun.net.http.retryPost=false<\/code> \u3002<\/li>\n<li>\u4f7f\u7528 Apache HttpComponents \u5e93\u3002<br \/>\n\u9ed8\u8ba4\u7684\uff0c <a href=\"http:\/\/hc.apache.org\/httpcomponents-client-ga\/tutorial\/html\/fundamentals.html#d5e279\">HttpClient \u5c1d\u8bd5\u81ea\u52a8\u4ece I\/O \u5f02\u5e38\u6062\u590d<\/a>\u3002\u8fd9\u79cd\u81ea\u52a8\u6062\u590d\u673a\u5236\u4ec5\u9650\u4e8e\u4e00\u4e9b\u88ab\u8ba4\u4e3a\u662f\u5b89\u5168\u7684\u5f02\u5e38\u3002<\/li>\n<\/ol>\n<p>*  HttpClient \u4e0d\u4f1a\u5c1d\u8bd5\u4ece\u4efb\u4f55\u903b\u8f91\u6216 HTTP \u534f\u8bae\u9519\u8bef\u6062\u590d\uff1b<br \/>\n*  HttpClient \u4f1a\u81ea\u52a8\u91cd\u8bd5\u90a3\u4e9b\u88ab\u8ba4\u4e3a\u662f\u5e42\u7b49\u7684\u65b9\u6cd5\uff1b<br \/>\n*  HttpClient \u4f1a\u81ea\u52a8\u91cd\u8bd5\u90a3\u4e9b\u4ecd\u5728\u53d1\u9001 HTTP \u8bf7\u6c42\u5230\u76ee\u6807\u670d\u52a1\u5668\u65f6\u51fa\u9519\u7684\u65b9\u6cd5\u3002\uff08\u4f8b\u5982\uff0c\u8bf7\u6c42\u8fd8\u6ca1\u6709\u5b8c\u6574\u4f20\u8f93\u5230\u670d\u52a1\u5668\uff09\u3002<\/p>\n<h2>\u4e09\u3001HTTP \u534f\u8bae\u7684\u5e42\u7b49\u6027<\/h2>\n<p><a href=\"https:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec9.html#sec9.1.2\">HTTP\/1.1 \u5bf9\u5e42\u7b49\u6027\u65b9\u6cd5\u7684\u5b9a\u4e49<\/a>\u662f\uff1a<\/p>\n<blockquote>\n<p>Methods can also have the property of &#8220;idempotence&#8221; in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request .<\/p>\n<\/blockquote>\n<p>\u5c31\u662f\u8bf4 N > 0 \u6b21\u540c\u4e00\u8bf7\u6c42\u4e0e\u5355\u4e00\u4e00\u6b21\u8bf7\u6c42\u7684\u526f\u4f5c\u7528\u662f\u76f8\u540c\u7684\u3002<\/p>\n<p><code>GET, HEAD, PUT, DELETE, OPTIONS, TRACE<\/code> \u90fd\u662f\u5e42\u7b49\u7684\u3002 <code>POST<\/code> \u662f\u975e\u5e42\u7b49\u7684\u3002<\/p>\n<h2>\u56db\u3001 HTTP \u534f\u8bae\u5b9e\u73b0\u7684\u91cd\u8bd5\u673a\u5236<\/h2>\n<p><a href=\"https:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec8.html#sec8.1.4\">8.1.4 Practical Considerations<\/a><\/p>\n<blockquote>\n<p>This means that clients, servers, and proxies MUST be able to recover from asynchronous close events. Client software SHOULD reopen the transport connection and retransmit the aborted sequence of requests without user interaction so long as the request sequence is idempotent (see section 9.1.2). Non-idempotent methods or sequences MUST NOT be automatically retried, although user agents MAY offer a human operator the choice of retrying the request(s). Confirmation by user-agent software with semantic understanding of the application MAY substitute for user confirmation. The automatic retry SHOULD NOT be repeated if the second sequence of requests fails.<\/p>\n<\/blockquote>\n<p>\u8fd9\u6bb5\u7684\u91cd\u70b9\u662f\uff1a\u5ba2\u6237\u7aef\u3001\u670d\u52a1\u5668\u548c\u4ee3\u7406\u5fc5\u987b\u53ef\u4ee5\u4ece\u5f02\u6b65\u7684\u5173\u95ed\u4e8b\u4ef6\u4e2d\u6062\u590d\u3002\u5ba2\u6237\u7aef\u8f6f\u4ef6\u5bf9\u4e8e\u5e42\u7b49\u7684\u8bf7\u6c42\u5e94\u8be5\u80fd\u591f\u81ea\u52a8\u91cd\u65b0\u6253\u5f00\u4f20\u8f93\u5c42\u8fde\u63a5\u5e76\u91cd\u65b0\u53d1\u9001\u8bf7\u6c42\u3002\u975e\u5e42\u7b49\u7684\u5fc5\u987b\u4e0d\u80fd\u81ea\u52a8\u91cd\u8bd5\u3002<\/p>\n<hr \/>\n<p>\u6b22\u8fce\u5173\u6ce8\u6211\u7684\u5fae\u4fe1\u516c\u4f17\u53f7: <strong>coderbee\u7b14\u8bb0<\/strong>\uff0c\u53ef\u4ee5\u66f4\u53ca\u65f6\u56de\u590d\u4f60\u7684\u8ba8\u8bba\u3002<br \/>\n<img loading=\"lazy\" decoding=\"async\" width=\"258\" height=\"258\" src=\"https:\/\/coderbee.net\/wp-content\/uploads\/2019\/01\/coderbee-note.jpg\" class=\"alignnone size-full wp-image-1707\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u4e00\u3001\u95ee\u9898 \u6d4b\u8bd5\u73af\u5883\u5076\u5c14\u53cd\u9988\u6709\u4e2a\u670d\u52a1 HTTP \u8bf7\u6c42\u91cd\u590d\u63d0\u4ea4\u3002\u8fd9\u4e2a HTTP \u8bf7\u6c42 &hellip; <a href=\"https:\/\/coderbee.net\/index.php\/java\/20170829\/1541\">\u7ee7\u7eed\u9605\u8bfb <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18],"tags":[86,280],"_links":{"self":[{"href":"https:\/\/coderbee.net\/index.php\/wp-json\/wp\/v2\/posts\/1541"}],"collection":[{"href":"https:\/\/coderbee.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coderbee.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coderbee.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/coderbee.net\/index.php\/wp-json\/wp\/v2\/comments?post=1541"}],"version-history":[{"count":4,"href":"https:\/\/coderbee.net\/index.php\/wp-json\/wp\/v2\/posts\/1541\/revisions"}],"predecessor-version":[{"id":1739,"href":"https:\/\/coderbee.net\/index.php\/wp-json\/wp\/v2\/posts\/1541\/revisions\/1739"}],"wp:attachment":[{"href":"https:\/\/coderbee.net\/index.php\/wp-json\/wp\/v2\/media?parent=1541"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coderbee.net\/index.php\/wp-json\/wp\/v2\/categories?post=1541"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coderbee.net\/index.php\/wp-json\/wp\/v2\/tags?post=1541"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}