0

I have the problem that the example of the actix web streaming proxy is not working as expected.

You can find my code below.

What I want to achieve: Stream an mp3 from another server from my backend so I can get around CORS and handing over the IP of my e.g. phone to the 3d party server.

I came as far as getting the audio to play event though no cors header is present but I can't get the total time of the podcast and can't fast forward thus.

How to reproduce:

  1. Take the sample actix web server
  2. Add the below endpoint
  3. Use this url in your browser: . The integrated html audio player doesn't show a time. When accessing it with only the query parameter i.e. the original url it works without a problem and I can skip around.
#[get("/proxy/podcast")]
pub(crate) async fn proxy_podcast(
    mut payload: web::Payload,
    params: web::Query<Params>,
    peer_addr: Option<PeerAddr>,
    method: Method,
) -> Result<HttpResponse, Error> {

    let (tx, rx) = mpsc::unbounded_channel();

    actix_web::rt::spawn(async move {
        while let Some(chunk) = payload.next().await {
            tx.send(chunk).unwrap();
        }
    });

    let forwarded_req = reqwest::Client::new()
        .request(method, params.url.clone())
        .body(reqwest::Body::wrap_stream(UnboundedReceiverStream::new(rx)));

    let forwarded_req = match peer_addr {
        Some(PeerAddr(addr)) => forwarded_req.header("x-forwarded-for", addr.ip().to_string()),
        None => forwarded_req,
    };

    let res = forwarded_req
        .send()
        .await
        .map_err(error::ErrorInternalServerError)?;

    println!("{:?}",res.headers());
    let mut client_resp = HttpResponse::build(res.status());
    // Remove `Connection` as per
    // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection#Directives

    for (header_name, header_value) in res.headers().iter() {
        println!("Key: {:?}, Value: {:?}", header_name, header_value);
        client_resp.insert_header((header_name.clone(), header_value.clone()));
    }

    Ok(client_resp.streaming(res.bytes_stream()))
}
kmdreko
  • 42,554
  • 6
  • 57
  • 106
SamTV
  • 147
  • 1
  • 11

1 Answers1

0

I solved this issue. I had the problem that request headers were missing from the initial response. I also had to remove headers that were present in the frontend request to my backend.

This is my result:

    for x in rq.headers() {
        if x.0 == "host"||x.0 == "referer"||x.0 == "sec-fetch-site"||x.0 == "sec-fetch-mode" {
            continue;
        }
        header_map.append(x.0.clone(), x.1.clone());
    }

    // Required to not generate a 302 redirect
    header_map.append("sec-fetch-mode", "no-cors".parse().unwrap());
    header_map.append("sec-fetch-site", "cross-site".parse().unwrap());
SamTV
  • 147
  • 1
  • 11