Java 11 的新HttpClient
版本不适用于create-react-app
的 React 开发服务器(从 开始npm start
)。客户端无限期挂起,没有任何错误。
它适用于其他 URLhttps://google.com
和其他本地服务器,例如
- Node.js 服务器。例如
http-server
(npm install http-server -g) - Python 服务器 (
python3 -m http.server 3000
)
知道为什么 React 开发服务器会发生这种情况吗?
重现状态:
- 通过创建一个反应应用程序
npx create-react-app my-app
(你只需要Node.js,npx
是它的一部分) - 然后运行它
cd my-app
,npm start
. 开发服务器启动http://localhost:3000/
- 然后打开 Java 控制台:
jshell
当 React 开发服务器工作时,打开jShell
并复制/粘贴以下代码:
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
var httpClient = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("http://localhost:3000")).build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
之后它无限期地挂在那里。
当从 Java 应用程序尝试此操作以查看带-Djdk.internal.httpclient.debug=true
参数的日志时,日志如下:
DEBUG: [http-nio-8080-exec-1] [327ms] HttpClientImpl(1) proxySelector is sun.net.spi.DefaultProxySelector@1ad21384 (user-supplied=false)
DEBUG: [http-nio-8080-exec-1] [453ms] HttpClientImpl(1) ClientImpl (async) send http://localhost:3000/ GET
DEBUG: [http-nio-8080-exec-1] [476ms] Exchange establishing exchange for http://localhost:3000/ GET,
proxy=null
DEBUG: [http-nio-8080-exec-1] [514ms] Http2ClientImpl not found in connection pool
DEBUG: [http-nio-8080-exec-1] [514ms] ExchangeImpl get: Trying to get HTTP/2 connection
DEBUG: [http-nio-8080-exec-1] [515ms] ExchangeImpl handling HTTP/2 connection creation result
DEBUG: [http-nio-8080-exec-1] [515ms] ExchangeImpl new Http1Exchange, try to upgrade
DEBUG: [http-nio-8080-exec-1] [535ms] PlainHttpConnection(?) Initial receive buffer size is: 65536
DEBUG: [http-nio-8080-exec-1] [564ms] Exchange checkFor407: all clear
DEBUG: [http-nio-8080-exec-1] [564ms] Http1Exchange Sending headers only
DEBUG: [http-nio-8080-exec-1] [610ms] Http1AsyncReceiver(SocketTube(1)) Subscribed pending jdk.internal.net.http.Http1Response$HeadersReader@19d6f6a9 queue.isEmpty: true
DEBUG: [http-nio-8080-exec-1] [655ms] Http1AsyncReceiver(SocketTube(1)) delegate is now jdk.internal.net.http.Http1Response$HeadersReader@19d6f6a9, demand=1, canRequestMore=true, queue.isEmpty=true
DEBUG: [http-nio-8080-exec-1] [656ms] Http1AsyncReceiver(SocketTube(1)) downstream subscription demand is 1
DEBUG: [http-nio-8080-exec-1] [667ms] Http1AsyncReceiver(SocketTube(1)) checkRequestMore: canRequestMore=true, hasDemand=true
DEBUG: [http-nio-8080-exec-1] [667ms] Http1AsyncReceiver(SocketTube(1)) downstream subscription demand is 1
DEBUG: [http-nio-8080-exec-1] [667ms] Http1AsyncReceiver(SocketTube(1)) checkRequestMore: canRequestMore=true, hasDemand=true
DEBUG: [http-nio-8080-exec-1] [667ms] Http1Exchange response created in advance
DEBUG: [http-nio-8080-exec-1] [667ms] Http1Exchange initiating connect async
DEBUG: [http-nio-8080-exec-1] [676ms] PlainHttpConnection(SocketTube(1)) registering connect event
DEBUG: [HttpClient-1-SelectorManager] [678ms] SelectorAttachment Registering jdk.internal.net.http.PlainHttpConnection$ConnectEvent@340a1657 for 8 (true)
DEBUG: [HttpClient-1-SelectorManager] [679ms] PlainHttpConnection(SocketTube(1)) ConnectEvent: finishing connect
DEBUG: [HttpClient-1-SelectorManager] [680ms] PlainHttpConnection(SocketTube(1)) ConnectEvent: connect finished: true Local addr: /127.0.0.1:58174
DEBUG: [HttpClient-1-Worker-0] [709ms] PlainHttpConnection(SocketTube(1)) finishConnect, setting connected=true
DEBUG: [HttpClient-1-Worker-0] [710ms] Http1Exchange SocketTube(1) connecting flows
DEBUG: [HttpClient-1-Worker-0] [710ms] SocketTube(1) connecting flows
DEBUG: [HttpClient-1-Worker-0] [711ms] SocketTube(1) read publisher got subscriber
DEBUG: [HttpClient-1-Worker-0] [711ms] SocketTube(1) registering subscribe event
DEBUG: [HttpClient-1-Worker-0] [711ms] SocketTube(1) leaving read.subscribe: Reading: [ops=0, demand=0, stopped=false], Writing: [ops=0, demand=0]
DEBUG: [HttpClient-1-Worker-0] [711ms] Http1Publisher(SocketTube(1)) got subscriber: SocketTube(1)
DEBUG: [HttpClient-1-Worker-0] [712ms] SocketTube(1) subscribed for writing
DEBUG: [HttpClient-1-Worker-0] [712ms] SocketTube(1) write: registering startSubscription event
DEBUG: [HttpClient-1-Worker-0] [712ms] Http1Exchange requestAction.headers
DEBUG: [HttpClient-1-Worker-0] [714ms] Http1Exchange setting outgoing with headers
DEBUG: [HttpClient-1-SelectorManager] [715ms] SocketTube(1) subscribe event raised
DEBUG: [HttpClient-1-SelectorManager] [715ms] SocketTube(1) handling pending subscription for jdk.internal.net.http.Http1AsyncReceiver$Http1TubeSubscriber@4c1c390e
DEBUG: [HttpClient-1-SelectorManager] [716ms] SocketTube(1) read demand reset to 0
DEBUG: [HttpClient-1-SelectorManager] [722ms] SocketTube(1) calling onSubscribe
DEBUG: [HttpClient-1-SelectorManager] [722ms] Http1AsyncReceiver(SocketTube(1)) Received onSubscribed from upstream
DEBUG: [HttpClient-1-SelectorManager] [732ms] SocketTube(1) onSubscribe called
DEBUG: [HttpClient-1-SelectorManager] [732ms] SocketTube(1) pending subscriber subscribed
DEBUG: [HttpClient-1-SelectorManager] [732ms] SocketTube(1) write: starting subscription
DEBUG: [HttpClient-1-SelectorManager] [732ms] SocketTube(1) write: offloading requestMore
DEBUG: [HttpClient-1-Worker-1] [733ms] Http1AsyncReceiver(SocketTube(1)) downstream subscription demand is 1
DEBUG: [HttpClient-1-Worker-1] [734ms] Http1AsyncReceiver(SocketTube(1)) checkRequestMore: canRequestMore=true, hasDemand=true
DEBUG: [HttpClient-1-Worker-1] [734ms] Http1AsyncReceiver(SocketTube(1)) Http1TubeSubscriber: requesting one more from upstream
DEBUG: [HttpClient-1-Worker-1] [734ms] SocketTube(1) got some demand for reading
DEBUG: [HttpClient-1-Worker-1] [734ms] SocketTube(1) resuming read event
DEBUG: [HttpClient-1-Worker-1] [735ms] SocketTube(1) leaving request(1): Reading: [ops=1, demand=1, stopped=false], Writing: [ops=0, demand=0]
DEBUG: [HttpClient-1-SelectorManager] [753ms] SelectorAttachment Registering jdk.internal.net.http.SocketTube$InternalReadPublisher$ReadEvent@3d7cf066 for 1 (true)
DEBUG: [HttpClient-1-Worker-2] [753ms] SocketTube(1) write: requesting more...
DEBUG: [HttpClient-1-Worker-2] [753ms] Http1Publisher(SocketTube(1)) subscription request(1), demand=1
DEBUG: [HttpClient-1-Worker-2] [753ms] Http1Publisher(SocketTube(1)) WriteTask
DEBUG: [HttpClient-1-Worker-0] [754ms] Http1Exchange appending to outgoing DataPair [data=[java.nio.HeapByteBuffer[pos=0 lim=205 cap=205]], throwable=null]
DEBUG: [HttpClient-1-Worker-2] [756ms] Http1Publisher(SocketTube(1)) hasOutgoing = false
DEBUG: [HttpClient-1-Worker-2] [757ms] Http1Exchange initiating completion of headersSentCF
DEBUG: [HttpClient-1-Worker-2] [757ms] Exchange checkFor407: all clear
DEBUG: [HttpClient-1-Worker-2] [757ms] Exchange sendRequestBody
DEBUG: [HttpClient-1-Worker-2] [757ms] Http1Exchange sendBodyAsync
DEBUG: [HttpClient-1-Worker-2] [757ms] Http1Exchange bodySubscriber is null
DEBUG: [HttpClient-1-Worker-2] [758ms] Http1Exchange appending to outgoing DataPair [data=[java.nio.HeapByteBuffer[pos=0 lim=0 cap=0]], throwable=null]
DEBUG: [HttpClient-1-Worker-2] [761ms] Http1Publisher(SocketTube(1)) onNext with 205 bytes
DEBUG: [HttpClient-1-Worker-2] [761ms] SocketTube(1) trying to write: 205
DEBUG: [HttpClient-1-Worker-2] [762ms] SocketTube(1) wrote: 205
DEBUG: [HttpClient-1-Worker-2] [762ms] SocketTube(1) write: requesting more...
DEBUG: [HttpClient-1-Worker-2] [763ms] Http1Publisher(SocketTube(1)) subscription request(1), demand=1
DEBUG: [HttpClient-1-Worker-2] [763ms] SocketTube(1) leaving requestMore: Reading: [ops=1, demand=1, stopped=false], Writing: [ops=0, demand=1]
DEBUG: [HttpClient-1-Worker-2] [763ms] SocketTube(1) leaving w.onNext Reading: [ops=1, demand=1, stopped=false], Writing: [ops=0, demand=1]
DEBUG: [HttpClient-1-Worker-2] [780ms] Http1Exchange initiating completion of bodySentCF
DEBUG: [HttpClient-1-Worker-2] [780ms] Http1Exchange sendBodyAsync completed successfully
DEBUG: [HttpClient-1-Worker-2] [780ms] Http1Exchange reading headers
DEBUG: [HttpClient-1-Worker-2] [814ms] Http1Response(id=1, PlainHttpConnection(SocketTube(1))) Reading Headers: (remaining: 0) READING_HEADERS
DEBUG: [HttpClient-1-Worker-2] [814ms] Http1Response(id=1, PlainHttpConnection(SocketTube(1))) First time around
DEBUG: [HttpClient-1-Worker-2] [815ms] Http1Response(id=1, PlainHttpConnection(SocketTube(1))) headersReader is not yet completed
DEBUG: [HttpClient-1-Worker-2] [816ms] Http1Publisher(SocketTube(1)) completed, stopping jdk.internal.net.http.common.SequentialScheduler@65a12c17
DEBUG: [HttpClient-1-Worker-2] [816ms] SocketTube(1) leaving requestMore: Reading: [ops=1, demand=1, stopped=false], Writing: [ops=0, demand=1]