limits(http2: false) (value: dever.http.Limits) { value = dever.http.defaultLimits() } limits(http2: true) (value: dever.http.Limits) { value = dever.http.defaultLimits() value.http2 = dever.http.defaultHttp2Limits() } append(event: dever.io.ReadEvent.Chunk(bytes), state: Bytes) (value: Bytes) { value = dever.bytes.concat(state, bytes) } append(event: dever.io.ReadEvent.Failed(message), state: Bytes) (value: Bytes) { fail(dever.io.ReadEvent.Failed(message)) } first(event: dever.io.ReadEvent.Chunk(bytes), state: Bytes) (value: Bytes, stop: Bool) { value = bytes stop = true } first(event: dever.io.ReadEvent.Failed(message), state: Bytes) (value: Bytes, stop: Bool) { fail(dever.io.ReadEvent.Failed(message)) } route(request: dever.http.Request, reply: dever.system.HttpReply) () { selected(request.target == "/wait", request, reply) } selected(waiting: false, request: dever.http.Request, reply: dever.system.HttpReply) () { dever.http.start(reply, 200, []) dever.http.write(reply, dever.bytes.fromText("head")) dever.http.write(reply, request.body) dever.task.sleep(20) dever.http.write(reply, dever.bytes.fromText("last")) } selected(waiting: true, request: dever.http.Request, reply: dever.system.HttpReply) () { dever.http.start(reply, 200, []) dever.http.write(reply, dever.bytes.fromText("ready")) dever.task.sleep(60000) } serve(listener: dever.system.Listener, http2: Bool) () { dever.http.serveLive(route, listener, limits(http2), dever.http.defaultLiveLimits()) } signal(event: dever.io.ReadEvent.Chunk(bytes), ready: Channel) () { send(ready, true) } signal(event: dever.io.ReadEvent.Failed(message), ready: Channel) () { fail(dever.io.ReadEvent.Failed(message)) } consume(body: AsyncStream, ready: Channel) () { each(signal, body, ready) } failed(result: dever.http.StreamResponseResult.Read(response)) (value: Bool) recover("验证关闭池的预期失败") { consumed = reduce(append, response.body, dever.bytes.fromText("")) value = false } failed(result: dever.http.StreamResponseResult.Failed(message)) (value: Bool) recover("验证关闭池的预期失败") { value = true } exercise(http2: Bool) (answer: Bool) { listener = dever.net.listen("127.0.0.1", 0) server = run(serve(listener, http2)) protocol = limits(http2) protocol.connections = 1 protocol.body_bytes = 1 pool = dever.http.defaultPoolLimits() pool.chunk_bytes = 3 client = dever.http.client("http://127.0.0.1:" + int.toText(dever.net.port(listener)), dever.tls.system(), protocol, pool) request = dever.http.Request { method = "POST", target = "/echo", headers = [], body = dever.bytes.fromText("") } response = dever.http.open(client, request) plain = reduce(append, response.body, dever.bytes.fromText("")) upload = stream([dever.io.ReadEvent.Chunk(dever.bytes.fromText("abc")), dever.io.ReadEvent.Chunk(dever.bytes.fromText("def"))]) sent = dever.http.openStream(client, dever.http.StreamRequest { method = "POST", target = "/echo", headers = [], body = upload }) echoed = reduce(append, sent.body, dever.bytes.fromText("")) early = dever.http.open(client, request) prefix = reduceUntil(first, early.body, dever.bytes.fromText("")) remainder = reduce(append, early.body, dever.bytes.fromText("")) waiting = dever.http.open(client, dever.http.Request { method = "GET", target = "/wait", headers = [], body = dever.bytes.fromText("") }) ready = channel(Bool, 4) consumer = run(consume(waiting.body, ready)) observed = receive(ready) stop(consumer) cancelled = reduce(append, waiting.body, dever.bytes.fromText("")) reused = dever.http.open(client, request) after = reduce(append, reused.body, dever.bytes.fromText("")) dever.http.closeClient(client) closed = failed(result(dever.http.open(client, request))) close(ready) dever.net.closeListener(listener) stop(server) answer = plain == dever.bytes.fromText("headlast") and echoed == dever.bytes.fromText("headabcdeflast") and prefix == dever.bytes.fromText("hea") and remainder == dever.bytes.fromText("") and observed == true and cancelled == dever.bytes.fromText("") and after == plain and closed } verify() (answer: Bool) { first = exercise(false) second = exercise(true) answer = first and second }