1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

feat(unstable): remove Deno.upgradeHttp API (#21856)

Closes https://github.com/denoland/deno/issues/21828.

This API is a huge footgun. And given that "Deno.serveHttp" is a
deprecated API that is discouraged to use (use "Deno.serve()" 
instead); it makes no sense to keep this API around.

This is a step towards fully migrating to Hyper 1.
This commit is contained in:
Bartek Iwańczuk 2024-01-22 22:35:39 +01:00 committed by GitHub
parent 69d5f136ba
commit 71551c80a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 43 additions and 589 deletions

View file

@ -9059,12 +9059,27 @@ fn lsp_workspace_symbol() {
"text": "export class B {\n fieldC: string;\n fieldD: string;\n}\n",
}
}));
let res = client.write_request(
let mut res = client.write_request(
"workspace/symbol",
json!({
"query": "field"
}),
);
// Replace `range` fields with `null` values. These are not important
// for assertion and require to be updated if we change unstable APIs.
for obj in res.as_array_mut().unwrap().iter_mut() {
*obj
.as_object_mut()
.unwrap()
.get_mut("location")
.unwrap()
.as_object_mut()
.unwrap()
.get_mut("range")
.unwrap() = Value::Null;
}
assert_eq!(
res,
json!([
@ -9073,16 +9088,7 @@ fn lsp_workspace_symbol() {
"kind": 8,
"location": {
"uri": "file:///a/file.ts",
"range": {
"start": {
"line": 1,
"character": 2
},
"end": {
"line": 1,
"character": 17
}
}
"range": null,
},
"containerName": "A"
},
@ -9091,16 +9097,7 @@ fn lsp_workspace_symbol() {
"kind": 8,
"location": {
"uri": "file:///a/file.ts",
"range": {
"start": {
"line": 2,
"character": 2
},
"end": {
"line": 2,
"character": 17
}
}
"range": null,
},
"containerName": "A"
},
@ -9109,16 +9106,7 @@ fn lsp_workspace_symbol() {
"kind": 8,
"location": {
"uri": "file:///a/file_01.ts",
"range": {
"start": {
"line": 1,
"character": 2
},
"end": {
"line": 1,
"character": 17
}
}
"range": null,
},
"containerName": "B"
},
@ -9127,16 +9115,7 @@ fn lsp_workspace_symbol() {
"kind": 8,
"location": {
"uri": "file:///a/file_01.ts",
"range": {
"start": {
"line": 2,
"character": 2
},
"end": {
"line": 2,
"character": 17
}
}
"range": null,
},
"containerName": "B"
},
@ -9145,16 +9124,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3165,
"character": 4
},
"end": {
"line": 3165,
"character": 55
}
}
"range": null,
},
"containerName": "CalendarProtocol"
},
@ -9163,16 +9133,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3335,
"character": 4
},
"end": {
"line": 3335,
"character": 47
}
}
"range": null,
},
"containerName": "Calendar"
},
@ -9181,16 +9142,7 @@ fn lsp_workspace_symbol() {
"kind": 11,
"location": {
"uri": "deno:/asset/lib.decorators.d.ts",
"range": {
"start": {
"line": 343,
"character": 0
},
"end": {
"line": 385,
"character": 1
}
}
"range": null,
},
"containerName": ""
},
@ -9199,16 +9151,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3143,
"character": 4
},
"end": {
"line": 3146,
"character": 26
}
}
"range": null,
},
"containerName": "CalendarProtocol"
},
@ -9217,16 +9160,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3313,
"character": 4
},
"end": {
"line": 3316,
"character": 26
}
}
"range": null,
},
"containerName": "Calendar"
},
@ -9235,16 +9169,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3439,
"character": 4
},
"end": {
"line": 3439,
"character": 39
}
}
"range": null,
},
"containerName": "PlainDate"
},
@ -9253,16 +9178,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3602,
"character": 4
},
"end": {
"line": 3602,
"character": 43
}
}
"range": null,
},
"containerName": "PlainDateTime"
},
@ -9271,16 +9187,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3651,
"character": 4
},
"end": {
"line": 3651,
"character": 39
}
}
"range": null,
},
"containerName": "PlainMonthDay"
},
@ -9289,16 +9196,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3770,
"character": 4
},
"end": {
"line": 3770,
"character": 39
}
}
"range": null,
},
"containerName": "PlainTime"
},
@ -9307,16 +9205,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3923,
"character": 4
},
"end": {
"line": 3923,
"character": 39
}
}
"range": null,
},
"containerName": "PlainYearMonth"
},
@ -9325,16 +9214,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 4082,
"character": 4
},
"end": {
"line": 4082,
"character": 43
}
}
"range": null,
},
"containerName": "ZonedDateTime"
},
@ -9343,16 +9223,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3166,
"character": 4
},
"end": {
"line": 3169,
"character": 31
}
}
"range": null,
},
"containerName": "CalendarProtocol"
},
@ -9361,16 +9232,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3336,
"character": 4
},
"end": {
"line": 3339,
"character": 31
}
}
"range": null,
},
"containerName": "Calendar"
},
@ -9379,16 +9241,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3151,
"character": 4
},
"end": {
"line": 3154,
"character": 30
}
}
"range": null,
},
"containerName": "CalendarProtocol"
},
@ -9397,16 +9250,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3321,
"character": 4
},
"end": {
"line": 3324,
"character": 30
}
}
"range": null,
},
"containerName": "Calendar"
},
@ -9415,16 +9259,7 @@ fn lsp_workspace_symbol() {
"kind": 5,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3355,
"character": 2
},
"end": {
"line": 3360,
"character": 4
}
}
"range": null,
},
"containerName": "Temporal"
},
@ -9433,16 +9268,7 @@ fn lsp_workspace_symbol() {
"kind": 5,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3466,
"character": 2
},
"end": {
"line": 3477,
"character": 4
}
}
"range": null,
},
"containerName": "Temporal"
},
@ -9451,16 +9277,7 @@ fn lsp_workspace_symbol() {
"kind": 5,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3671,
"character": 2
},
"end": {
"line": 3678,
"character": 4
}
}
"range": null,
},
"containerName": "Temporal"
},
@ -9469,16 +9286,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3147,
"character": 4
},
"end": {
"line": 3150,
"character": 31
}
}
"range": null,
},
"containerName": "CalendarProtocol"
},
@ -9487,16 +9295,7 @@ fn lsp_workspace_symbol() {
"kind": 6,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3317,
"character": 4
},
"end": {
"line": 3320,
"character": 31
}
}
"range": null,
},
"containerName": "Calendar"
},
@ -9505,16 +9304,7 @@ fn lsp_workspace_symbol() {
"kind": 5,
"location": {
"uri": "deno:/asset/lib.deno.unstable.d.ts",
"range": {
"start": {
"line": 3952,
"character": 2
},
"end": {
"line": 3965,
"character": 4
}
}
"range": null,
},
"containerName": "Temporal"
}

View file

@ -4,10 +4,6 @@ main undefined
main undefined
main undefined
main undefined
main undefined
main undefined
worker undefined
worker undefined
worker undefined
worker undefined
worker undefined

View file

@ -3,14 +3,10 @@ main [Function: createHttpClient]
main [class HttpConn]
main Symbol("[[associated_ws]]")
main [Function: serve]
main [Function: upgradeHttp]
main [Function: upgradeWebSocket]
main [Function: upgradeHttp]
worker [class HttpClient]
worker [Function: createHttpClient]
worker [class HttpConn]
worker Symbol("[[associated_ws]]")
worker [Function: serve]
worker [Function: upgradeHttp]
worker [Function: upgradeWebSocket]
worker [Function: upgradeHttp]

View file

@ -5,9 +5,7 @@ console.log(scope, Deno.createHttpClient);
console.log(scope, Deno.http?.HttpConn);
console.log(scope, Deno.http?._ws);
console.log(scope, Deno.http?.serve);
console.log(scope, Deno.http?.upgradeHttp);
console.log(scope, Deno.http?.upgradeWebSocket);
console.log(scope, Deno.upgradeHttp);
if (scope === "worker") {
postMessage("done");

View file

@ -1,7 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { Buffer, BufReader, BufWriter } from "../../../test_util/std/io/mod.ts";
import { TextProtoReader } from "../testdata/run/textproto.ts";
import { serve, serveTls } from "../../../test_util/std/http/server.ts";
import {
assert,
assertEquals,
@ -2181,162 +2180,6 @@ Deno.test({
},
});
Deno.test("upgradeHttp tcp", async () => {
async function client() {
const tcpConn = await Deno.connect({ port: listenPort });
await tcpConn.write(
new TextEncoder().encode(
"CONNECT server.example.com:80 HTTP/1.1\r\n\r\nbla bla bla\nbla bla\nbla\n",
),
);
setTimeout(async () => {
await tcpConn.write(
new TextEncoder().encode(
"bla bla bla\nbla bla\nbla\n",
),
);
tcpConn.close();
}, 500);
}
const abortController = new AbortController();
const signal = abortController.signal;
const server = serve((req) => {
const p = Deno.upgradeHttp(req);
(async () => {
const [conn, firstPacket] = await p;
const buf = new Uint8Array(1024);
const firstPacketText = new TextDecoder().decode(firstPacket);
assertEquals(firstPacketText, "bla bla bla\nbla bla\nbla\n");
const n = await conn.read(buf);
assert(n != null);
const secondPacketText = new TextDecoder().decode(buf.slice(0, n));
assertEquals(secondPacketText, "bla bla bla\nbla bla\nbla\n");
abortController.abort();
conn.close();
})();
return new Response(null, { status: 101 });
}, { port: listenPort, signal });
await Promise.all([server, client()]);
});
Deno.test(
"upgradeHttp tls",
{ permissions: { net: true, read: true } },
async () => {
async function client() {
const caCerts = [
await Deno.readTextFile("cli/tests/testdata/tls/RootCA.pem"),
];
const tlsConn = await Deno.connectTls({
hostname: "localhost",
port: listenPort,
caCerts,
});
await tlsConn.write(
new TextEncoder().encode(
"CONNECT server.example.com:80 HTTP/1.1\r\n\r\nbla bla bla\nbla bla\nbla\n",
),
);
setTimeout(async () => {
await tlsConn.write(
new TextEncoder().encode(
"bla bla bla\nbla bla\nbla\n",
),
);
tlsConn.close();
}, 500);
}
const abortController = new AbortController();
const signal = abortController.signal;
const certFile = "cli/tests/testdata/tls/localhost.crt";
const keyFile = "cli/tests/testdata/tls/localhost.key";
const server = serveTls((req) => {
const p = Deno.upgradeHttp(req);
(async () => {
const [conn, firstPacket] = await p;
const buf = new Uint8Array(1024);
const firstPacketText = new TextDecoder().decode(firstPacket);
assertEquals(firstPacketText, "bla bla bla\nbla bla\nbla\n");
const n = await conn.read(buf);
assert(n != null);
const secondPacketText = new TextDecoder().decode(buf.slice(0, n));
assertEquals(secondPacketText, "bla bla bla\nbla bla\nbla\n");
abortController.abort();
conn.close();
})();
return new Response(null, { status: 101 });
}, { hostname: "localhost", port: listenPort, signal, keyFile, certFile });
await Promise.all([server, client()]);
},
);
Deno.test("upgradeHttp unix", {
permissions: { read: true, write: true },
ignore: Deno.build.os === "windows",
}, async () => {
const filePath = tmpUnixSocketPath();
const { promise, resolve } = Promise.withResolvers<void>();
async function client() {
const unixConn = await Deno.connect({ path: filePath, transport: "unix" });
await unixConn.write(
new TextEncoder().encode(
"CONNECT server.example.com:80 HTTP/1.1\r\n\r\nbla bla bla\nbla bla\nbla\n",
),
);
setTimeout(async () => {
await unixConn.write(
new TextEncoder().encode(
"bla bla bla\nbla bla\nbla\n",
),
);
unixConn.close();
resolve();
}, 500);
await promise;
}
const server = (async () => {
const listener = Deno.listen({ path: filePath, transport: "unix" });
const conn = await listener.accept();
listener.close();
const httpConn = Deno.serveHttp(conn);
const reqEvent = await httpConn.nextRequest();
assert(reqEvent);
const { request, respondWith } = reqEvent;
const p = Deno.upgradeHttp(request);
const promise = (async () => {
const [conn, firstPacket] = await p;
const buf = new Uint8Array(1024);
const firstPacketText = new TextDecoder().decode(firstPacket);
assertEquals(firstPacketText, "bla bla bla\nbla bla\nbla\n");
const n = await conn.read(buf);
assert(n != null);
const secondPacketText = new TextDecoder().decode(buf.slice(0, n));
assertEquals(secondPacketText, "bla bla bla\nbla bla\nbla\n");
conn.close();
})();
const resp = new Response(null, { status: 101 });
await respondWith(resp);
await promise;
httpConn!.close();
})();
await Promise.all([server, client()]);
});
Deno.test(
{ permissions: { net: true } },
async function httpServerReadLargeBodyWithContentLength() {

View file

@ -53,7 +53,6 @@ delete Object.prototype.__proto__;
"listen",
"listenDatagram",
"openKv",
"upgradeHttp",
"umask",
]);
const unstableMsgSuggestion =

View file

@ -1187,34 +1187,6 @@ declare namespace Deno {
*/
export function funlockSync(rid: number): void;
/** **UNSTABLE**: New API, yet to be vetted.
*
* Allows "hijacking" the connection that the request is associated with. This
* can be used to implement protocols that build on top of HTTP (eg.
* {@linkcode WebSocket}).
*
* The returned promise returns underlying connection and first packet
* received. The promise shouldn't be awaited before responding to the
* `request`, otherwise event loop might deadlock.
*
* ```ts
* function handler(req: Request): Response {
* Deno.upgradeHttp(req).then(([conn, firstPacket]) => {
* // ...
* });
* return new Response(null, { status: 101 });
* }
* ```
*
* This method can only be called on requests originating the
* {@linkcode Deno.serveHttp} server.
*
* @category HTTP Server
*/
export function upgradeHttp(
request: Request,
): Promise<[Deno.Conn, Uint8Array]>;
/** **UNSTABLE**: New API, yet to be vetted.
*
* Open a new {@linkcode Deno.Kv} connection to persist data.

View file

@ -154,12 +154,6 @@ class InnerRequest {
throw new Deno.errors.Http("already closed");
}
// upgradeHttp is async
// TODO(mmastrac)
if (upgradeType == "upgradeHttp") {
throw "upgradeHttp is unavailable in Deno.serve at this time";
}
// upgradeHttpRaw is sync
if (upgradeType == "upgradeHttpRaw") {
const external = this.#external;

View file

@ -9,7 +9,6 @@ const {
op_http_accept,
op_http_headers,
op_http_shutdown,
op_http_upgrade,
op_http_upgrade_websocket,
op_http_websocket_accept_header,
op_http_write,
@ -20,7 +19,6 @@ const {
ArrayPrototypeIncludes,
ArrayPrototypeMap,
ArrayPrototypePush,
Error,
ObjectPrototypeIsPrototypeOf,
SafeSet,
SafeSetIterator,
@ -67,10 +65,7 @@ import {
SERVER,
WebSocket,
} from "ext:deno_websocket/01_websocket.js";
import { TcpConn, UnixConn } from "ext:deno_net/01_net.js";
import { TlsConn } from "ext:deno_net/02_tls.js";
import {
Deferred,
getReadableStreamResourceBacking,
readableStreamClose,
readableStreamForRid,
@ -80,7 +75,6 @@ import { serve } from "ext:deno_http/00_serve.js";
import { SymbolDispose } from "ext:deno_web/00_infra.js";
const connErrorSymbol = Symbol("connError");
const _deferred = Symbol("upgradeHttpDeferred");
/** @type {(self: HttpConn, rid: number) => boolean} */
let deleteManagedResource;
@ -174,9 +168,6 @@ class HttpConn {
const respondWith = createRespondWith(
this,
streamRid,
request,
this.#remoteAddr,
this.#localAddr,
abortController,
);
@ -219,9 +210,6 @@ class HttpConn {
function createRespondWith(
httpConn,
streamRid,
request,
remoteAddr,
localAddr,
abortController,
) {
return async function respondWith(resp) {
@ -379,22 +367,6 @@ function createRespondWith(
}
}
const deferred = request[_deferred];
if (deferred) {
const res = await op_http_upgrade(streamRid);
let conn;
if (res.connType === "tcp") {
conn = new TcpConn(res.connRid, remoteAddr, localAddr);
} else if (res.connType === "tls") {
conn = new TlsConn(res.connRid, remoteAddr, localAddr);
} else if (res.connType === "unix") {
conn = new UnixConn(res.connRid, remoteAddr, localAddr);
} else {
throw new Error("unreachable");
}
deferred.resolve([conn, res.readBuf]);
}
const ws = resp[_ws];
if (ws) {
const wsRid = await op_http_upgrade_websocket(
@ -502,16 +474,6 @@ function upgradeWebSocket(request, options = {}) {
return { response, socket };
}
function upgradeHttp(req) {
const inner = toInnerRequest(req);
if (inner._wantsUpgrade) {
return inner._wantsUpgrade("upgradeHttp", arguments);
}
req[_deferred] = new Deferred();
return req[_deferred].promise;
}
const spaceCharCode = StringPrototypeCharCodeAt(" ", 0);
const tabCharCode = StringPrototypeCharCodeAt("\t", 0);
const commaCharCode = StringPrototypeCharCodeAt(",", 0);
@ -589,4 +551,4 @@ function buildCaseInsensitiveCommaValueFinder(checkText) {
internals.buildCaseInsensitiveCommaValueFinder =
buildCaseInsensitiveCommaValueFinder;
export { _ws, HttpConn, serve, upgradeHttp, upgradeWebSocket };
export { _ws, HttpConn, serve, upgradeWebSocket };

View file

@ -203,7 +203,6 @@ denoNsUnstableById[unstableIds.http] = {
createHttpClient: httpClient.createHttpClient,
// TODO(bartlomieju): why is it needed?
http,
upgradeHttp: http.upgradeHttp,
};
denoNsUnstableById[unstableIds.kv] = {
@ -250,7 +249,6 @@ const denoNsUnstable = {
flockSync: fs.flockSync,
funlock: fs.funlock,
funlockSync: fs.funlockSync,
upgradeHttp: http.upgradeHttp,
openKv: kv.openKv,
AtomicOperation: kv.AtomicOperation,
Kv: kv.Kv,

View file

@ -1,38 +1,22 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::cell::RefCell;
use std::rc::Rc;
use deno_core::error::bad_resource;
use deno_core::error::bad_resource_id;
use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::RcRef;
use deno_core::ResourceId;
use deno_core::ToJsBuffer;
use deno_http::http_create_conn_resource;
use deno_http::HttpRequestReader;
use deno_http::HttpStreamResource;
use deno_net::io::TcpStreamResource;
use deno_net::ops_tls::TlsStream;
use deno_net::ops_tls::TlsStreamResource;
use hyper_v014::upgrade::Parts;
use serde::Serialize;
use tokio::net::TcpStream;
#[cfg(unix)]
use deno_net::io::UnixStreamResource;
#[cfg(unix)]
use tokio::net::UnixStream;
pub const UNSTABLE_FEATURE_NAME: &str = "http";
deno_core::extension!(
deno_http_runtime,
ops = [op_http_start, op_http_upgrade],
);
deno_core::extension!(deno_http_runtime, ops = [op_http_start],);
#[op2(fast)]
#[smi]
@ -98,81 +82,3 @@ pub struct HttpUpgradeResult {
conn_type: &'static str,
read_buf: ToJsBuffer,
}
#[op2(async)]
#[serde]
async fn op_http_upgrade(
state: Rc<RefCell<OpState>>,
#[smi] rid: ResourceId,
) -> Result<HttpUpgradeResult, AnyError> {
let stream = state
.borrow_mut()
.resource_table
.get::<HttpStreamResource>(rid)?;
let mut rd = RcRef::map(&stream, |r| &r.rd).borrow_mut().await;
let request = match &mut *rd {
HttpRequestReader::Headers(request) => request,
_ => {
return Err(custom_error(
"Http",
"cannot upgrade because request body was used",
))
}
};
let transport = hyper_v014::upgrade::on(request).await?;
let transport = match transport.downcast::<TcpStream>() {
Ok(Parts {
io: tcp_stream,
read_buf,
..
}) => {
return Ok(HttpUpgradeResult {
conn_type: "tcp",
conn_rid: state
.borrow_mut()
.resource_table
.add(TcpStreamResource::new(tcp_stream.into_split())),
read_buf: read_buf.to_vec().into(),
});
}
Err(transport) => transport,
};
#[cfg(unix)]
let transport = match transport.downcast::<UnixStream>() {
Ok(Parts {
io: unix_stream,
read_buf,
..
}) => {
return Ok(HttpUpgradeResult {
conn_type: "unix",
conn_rid: state
.borrow_mut()
.resource_table
.add(UnixStreamResource::new(unix_stream.into_split())),
read_buf: read_buf.to_vec().into(),
});
}
Err(transport) => transport,
};
match transport.downcast::<TlsStream>() {
Ok(Parts {
io: tls_stream,
read_buf,
..
}) => Ok(HttpUpgradeResult {
conn_type: "tls",
conn_rid: state
.borrow_mut()
.resource_table
.add(TlsStreamResource::new(tls_stream.into_split())),
read_buf: read_buf.to_vec().into(),
}),
Err(_) => Err(custom_error(
"Http",
"encountered unsupported transport while upgrading",
)),
}
}