MCPcopy Create free account
hub / github.com/awslabs/llrt / send_stream

Function send_stream

modules/llrt_fetch/src/fetch.rs:190–299  ·  view source on GitHub ↗
(
    ctx: &Ctx<'js>,
    client: &HyperClient,
    stream: Class<'js, ReadableStream<'js>>,
    method: Method,
    method_string: String,
    uri: Uri,
    headers: Option<&Headers>,
    start: Inst

Source from the content-addressed store, hash-verified

188}
189
190#[allow(clippy::too_many_arguments)]
191async fn send_stream<'js>(
192 ctx: &Ctx<'js>,
193 client: &HyperClient,
194 stream: Class<'js, ReadableStream<'js>>,
195 method: Method,
196 method_string: String,
197 uri: Uri,
198 headers: Option<&Headers>,
199 start: Instant,
200 abort_receiver: Option<mc_oneshot::Receiver<Value<'js>>>,
201) -> Result<Response<'js>> {
202 let (tx, rx) = tokio::sync::mpsc::channel::<Bytes>(128);
203 let (err_tx, err_rx) = tokio::sync::oneshot::channel::<String>();
204 let ctx2 = ctx.clone();
205
206 // Spawn stream reader in JS context
207 ctx.spawn_exit_simple({
208 async move {
209 let get_reader: Function = stream.get("getReader")?;
210 let reader: Object = get_reader.call((This(stream.clone()),))?;
211 let read_fn: Function = reader.get("read")?;
212
213 loop {
214 let promise: rquickjs::Promise = read_fn.call((This(reader.clone()),))?;
215 let read_result = match promise.into_future::<Object>().await.catch(&ctx2) {
216 Ok(r) => r,
217 Err(e) => {
218 let msg = match e {
219 CaughtError::Exception(ex) => ex.message().unwrap_or_default(),
220 CaughtError::Value(v) => v
221 .as_string()
222 .and_then(|s| s.to_string().ok())
223 .unwrap_or_else(|| "Stream error".into()),
224 CaughtError::Error(e) => e.to_string(),
225 };
226 let _ = err_tx.send(msg);
227 break;
228 },
229 };
230 let done: bool = read_result.get("done").unwrap_or(true);
231 if done {
232 break;
233 }
234 if let Ok(value) = read_result.get::<_, Value>("value") {
235 // Per fetch spec, stream chunks must be Uint8Array. Anything
236 // else (ArrayBuffer, Blob, String, null, etc.) is an error.
237 let bytes = match rquickjs::TypedArray::<u8>::from_value(value) {
238 Ok(typed_array) => typed_array.as_bytes().map(Bytes::copy_from_slice),
239 Err(_) => {
240 let _ = err_tx
241 .send("Failed to read body: chunk is not a Uint8Array".into());
242 break;
243 },
244 };
245 if let Some(bytes) = bytes {
246 if tx.send(bytes).await.is_err() {
247 break;

Callers 1

initFunction · 0.85

Calls 14

apply_default_headersFunction · 0.85
spawn_exit_simpleMethod · 0.80
messageMethod · 0.80
okMethod · 0.80
methodMethod · 0.80
or_throwMethod · 0.80
cloneMethod · 0.45
getMethod · 0.45
callMethod · 0.45
to_stringMethod · 0.45
sendMethod · 0.45
as_bytesMethod · 0.45

Tested by

no test coverage detected