I've been trying to do this multiple ways and it doesn't seem to work. I'm using NextJS so first I call my Next API:
...
mutateUser(
await fetchJson("/path/to/api", {
method: "POST",
headers: { "Content-Type": "application/pdf" },
body: file, // const [file, setFile] = useState<File | null>(null);
})
);
...
Then I call my Actix Web server using Axios in the API
...
const { token } = req.session.user;
const body = req.body;
const api_url = `${process.env.SERVER_API_URL}/path/to/api` as string;
console.log(body.length);
try {
const response = await axios.post(api_url, body, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/pdf",
},
});
res.json({ ...response.data, isLoggedIn: true });
}
...
Then this is how I handle it in Actix:
pub async fn route_function(db: Data<DatabaseRepository>, mut payload: Payload, auth: AuthorizationService) -> HttpResponse {
let id = auth.id;
let mut bytes = BytesMut::new();
while let Some(item) = payload.next().await {
bytes.extend_from_slice(&item.unwrap());
}
//bytes to string
log::debug!("bytes: {:?}", bytes);
// length of bytes
log::debug!("bytes length: {:?}", bytes.len());
let pdf_text = match pdf_extract::extract_text_from_mem(&bytes) {
Ok(text) => text,
Err(e) => { // PDF parsing error only with Axios
log::error!("Error: {:#?}", e);
return HttpResponse::BadRequest().json(ErrorResponse::new("error parsing pdf".to_string(), e.to_string()));
}
};
...
So basically, what's going wrong is this: When I use Postman or cURL the Rust route works perfectly. Here is my cURL command for reference:
# This works
curl -X POST -H "Content-Type: application/pdf" -H "Authorization: Bearer <TOKEN>" --data-binary "@/path/to/file.pdf" http://localhost:8080/path/to/api
However, when I use Axios, I get a PDF Parsing error. The PDF parser library returns an error when parsing the PDF Trailer. Additionally, I was checking the bytes length of the requests and when I call using Axios it is around 101k bytes but when I call using Postman or cURL it is 58k bytes. Not sure why but I think this has something to do with why it's not working. This also makes me think that I am doing something wrong with either Axios, Next, or Fetch but I can't find where. I also tried using FormData()
but that didn't work either.
If someone has a workaround by changing my Actix route so that it works generally, this is also appreciated. I only found how to read a pdf using the Payload
extractor.
Any help is appreciated. Thanks in advance.
It seems like you have to do this in next
export const config = {
api: {
bodyParser: false,
},
};
to then use req
as a readable stream.
Refer to: https://github.com/vercel/next.js/issues/37735 or https://www.reddit.com/r/nextjs/comments/tt4qbf/getting_the_raw_request_body_according_to_next_is/
Then you can post this using axios. When you encounter further problems, you might want to consider setting the Content-Length
Header.
https://github.com/axios/axios/issues/5223#issuecomment-1690233615