What am i doing wrong!(reqwest crate)

I am using reqwest crate to post a file to https://temp.sh/ but every time getting Upload failed: 404 Not Found.
Here is what I have done:

use futures::stream::TryStreamExt;
use reqwest::{Body, Client};
use std::{fs, path::PathBuf};
use tokio::fs::File;
use tokio_util::codec::{BytesCodec, FramedRead};
#[tokio::main]

async fn main() -> Result<(), Box<dyn std::error::Error>> {
   let file = rfd::FileDialog::new()
        .set_title("Select the file")
        .pick_file();

    let file: PathBuf = match file {
        Some(f) => f,
        None => {
            eprintln!("❌ No file selected.");
            return Ok(());
        }
    };

    let data = fs::read(&file)?; // read entire file into memory
    let filename = file.file_name().unwrap().to_string_lossy().to_string();

    let url = format!("https://temp.sh/{}", filename);

    let client = Client::new();
    let res = client
        .put(&url) // temp.sh requires PUT
        .body(data)
        .send()
        .await?;
    if res.status().is_success() {
        println!("✅ Uploaded");
    } else {
        eprintln!("❌ Upload failed: {}", res.status());
    }

    Ok(())
}

Corresponding curl command is curl -F "file=@test.txt" https://temp.sh/upload

What am i doing wrong?

This puts file foo.bar to temp.sh/foo.bar instead of temp.sh/upload.

what is the recommended workaround?
can i add upload to the url for it to work?

Not a workaround, but a fix - make request to the correct URL, that is, to "https://temp.sh/upload".

Getting Error 404:Not Found.

The example curl from their website specifies POST, not PUT. In addition to fixing the URL, you'll need to fix the request method.

 let url = format!("https://temp.sh/upload/{}", filename);

    let client = Client::new();
    let res = client
        .post(&url)
        .body(data)
        .send()
        .await?;

I changed it to post.

The URL is still wrong. It should stop at /upload and not contain a filename. Please review the example curl from the website once more, and verify you can upload a file using their curl example.

curl is working.

But the output of the code:
Error: reqwest::Error { kind: Request, url: "https://temp.sh/upload", source: hyper_util::client::legacy::Error(Connect, ConnectError("tcp connect error", 51.91.79.17:443, Os { code: 101, kind: NetworkUnreachable, message: "Network is unreachable" })) }

The Rust Playground does not allow any network access at all — if it did, it would surely be abused for spam and attacks. (That said, I don't see the playground being mentioned previously in this thread?)

Yeah not using playground.

Notice that the cURL example is using the -F flag, which will send a POST request using multipart/form-data.

Here's an example of doing something similar with Reqwest:

let file = tokio::fs::read(your_file_path).await.unwrap();

    //make form part of file
    let file_part_bytes = multipart::Part::bytes(file.clone())
        .file_name("your_file_name.txt")
        .mime_str("application/octet-stream")
        .unwrap();

    let client = Client::new();

    let response = client
        .post("https://temp.sh/upload")
        .multipart(
           multipart::Form::new()
              .part("file", file_part_bytes)
         )
        .send()
        .await
        .unwrap();
1 Like

This worked for me:

use clap::Parser;
use reqwest::Client;
use reqwest::multipart::Form;
use std::path::PathBuf;

const URL: &str = "https://temp.sh/upload";

#[derive(Debug, Parser)]
struct Args {
    file: PathBuf,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args = Args::parse();
    let form = Form::new().file("file", args.file).await?;
    let url = Client::new()
        .post(URL)
        .multipart(form)
        .send()
        .await?
        .error_for_status()?
        .text()
        .await?;
    println!("{url}");
    Ok(())
}
~/tempshclt> cargo run -- Cargo.toml 
   Compiling tempshclt v0.1.0 (/home/neumann/tempshclt)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 19.20s
     Running `target/debug/tempshclt Cargo.toml`
http://temp.sh/ittdk/Cargo.toml
~/tempshclt>                   
2 Likes

Nice! I just copied my example from one of my tests that sends a multipart request with two parts: bytes and json.

That added some overhead, so your example is simpler and better for the O.P. :smiley:.

Thanks

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.