Closed ajmeese7 closed 1 year ago
How are you sending the form ?
@GrosSacASac these functions are the parents of the function above:
/**
* Middleware for handling HTTP requests
*/
const parseFields = (config) => (req, res) => {
if (["get", "head"].indexOf(req.method.toLowerCase()) !== -1) {
return Promise.resolve(parseGet(req));
}
const json = parseJson(req);
if (json) {
return Promise.resolve(json);
}
return parseFormData(req, config);
};
/**
* Creates the middleware
*/
const createMiddleware = (core) => {
const parse = parseFields(core.config("express"));
return (req, res, next) =>
parse(req, res)
.then(({ fields, files }) => {
req.fields = fields;
req.files = files;
next();
})
.catch((error) => {
core.logger.warn(error);
req.fields = {};
req.files = {};
next(error);
});
};
const middleware = createMiddleware(core);
That is not what I asked
Could you elaborate?
You wanted to know how the form is sent, and it is sent via parseFields
in the code above. The middleware
variable is used by the Express Router, which sends the form:
const router = express.Router();
router.use(middleware);
parseFields is server side, how are you sending the form client side
This is the client-side code that is used:
/**
* Writes a file.
*
* @param {String|VFSFile} path The path to write
* @param {ArrayBuffer|Blob|String} data The data
* @param {VFSMethodOptions} [options] Options
* @returns {Promise<Number>} File size
*/
export const writefile = (adapter, mount) =>
(path, data, options = {}) => {
const binary = data instanceof ArrayBuffer || data instanceof Blob
? data
: new Blob([data], { type: "application/octet-stream" });
return adapter.writefile(pathToObject(path), binary, options, mount);
};
// NOTE: This is the `adapter` function that is referenced above,
// it is in another file but it is called appropriately. It is in a JSON
// format because it is exported as part of an object
writefile: ({ path }, data, options = {}) => {
const formData = new FormData();
formData.append("upload", data);
formData.append("path", path);
formData.append("options", options);
// This is where the server-side code above is called
return request("writefile", formData, undefined, {
onProgress: options.onProgress,
xhr: Boolean(options.onProgress),
});
},
The error means the content type is not recognized amongst the 3 that can be parsed by formidable.
So I don't know what your 'request' function does but it probably does not set the correct content type header
Inside parseFormData , what do you get if you console.log(req.headers) ?
This issue is just started in my next.js project by self. I think another library cause this bug but I still couldn't find the conflict.
@oarsoy that was my problem, the issue is the deepmerge
library, which merges a FormData
object into an empty object, thus losing all the data. Transitioning to the merge-deep
library solved my issue, so this repository isn't the underlying cause!
Although I do recommend having some more informative warning when this is the case @GrosSacASac, just from a user's perspective. It took me a LONG time to figure out what was going wrong, only to realize that the issue wasn't even in my code.
Noted. @oarsoy , what do you get with console.log(req.headers) ?
@GrosSacASac Can you please check what's wrong in my case? I get the same error and I've realized that as you've said, this is due to content-type: text/plain (among request headers in devtools network section). However, even adding app.use(express.text())
to my express code doesn't resolve it, so I wonder what else I should do?
This is frontend:
const response = await axios.patch("http://localhost:1233/items/tempid", "Hi Tom", {
headers: { "Content-Type": "text/plain" },
});
(Although this is a patch call, I've changed the endpoint to POST too and made a request with text/plain content-type and again got this same error, so is not an issue with patch vs post).
For some reasons, in the http://localhost:1233/items/:id
endpoint, I both do uploads (using Formidable) and also process text data:
app.patch("/items/:id", (req, res, next) => {
//...
form.parse(req, (err, fields, files) => {
console.log({ err }); // <---
//...
})
});
[0] { [0] err: FormidableError: no parser found [0] at IncomingForm.writeHeaders (D:\...
I want Formidable to skip/ignore the request when there are no files/fields and request is not a form-data at all. But I don't know how to get it to do that. Maybe I should check the content-type manually? Thanks in advance.
Yeah it wasn't an issue, I could both check content-type, and also I could just wrap the text in formData too using a field.
@oarsoy that was my problem, the issue is the
deepmerge
library, which merges aFormData
object into an empty object, thus losing all the data. Transitioning to themerge-deep
library solved my issue, so this repository isn't the underlying cause!Although I do recommend having some more informative warning when this is the case @GrosSacASac, just from a user's perspective. It took me a LONG time to figure out what was going wrong, only to realize that the issue wasn't even in my code.
how did you transition to the merge-deep library
Support plan
Context
What are you trying to achieve or the steps to reproduce?
What was the result you got?
FormidableError: no parser found
, with a code of 1003 and an httpCode of 415.This then gives the Express error:
What result did you expect?
I expect to be able to parse the passed file, although I am currently unsure of how to do so. I am working on an inherited project and this seems to have worked before, and researching the error message has not lead to a solution.
Any help would be greatly appreciated!