Hi,
I want to create a node in the declarative style to consume a REST API which has some endpoints that receive multipart/form-data requests.
I didn’t find in the documentation a way to do this but following the answer here and Using the Whatsapp node as reference I’m very close to find a solution but the requests are failing.
Redirecting the request to netcat instead of the original target I can see that the body has some random characters:
POST / HTTP/1.1
Accept: application/json
Content-Type: multipart/form-data
Authorization: Bearer TOKEN
User-Agent: n8n
Host: localhost:8088
Connection: close
Transfer-Encoding: chunked
6b
----------------------------061842126287809763963984
Content-Disposition: form-data; name="first_name"
4
John
2
6a
----------------------------061842126287809763963984
Content-Disposition: form-data; name="last_name"
3
Doe
2
66
----------------------------061842126287809763963984
Content-Disposition: form-data; name="email"
c
[email protected]
3a
----------------------------061842126287809763963984--
0
If I send the request through Insomnia the body doesn’t have these characters:
POST / HTTP/1.1
Host: localhost:8088
User-Agent: insomnia/2023.2.2
Content-Type: multipart/form-data; boundary=X-INSOMNIA-BOUNDARY
Authorization: Bearer TOKEN
Accept: */*
Content-Length: 272
--X-INSOMNIA-BOUNDARY
Content-Disposition: form-data; name="first_name"
John
--X-INSOMNIA-BOUNDARY
Content-Disposition: form-data; name="last_name"
Doe
--X-INSOMNIA-BOUNDARY
Content-Disposition: form-data; name="email"
[email protected]
What I’m doing in my node is the following:
- Define an operation with a
preSend
attribute:
{
name: 'Test',
value: 'testOperation',
action: 'Test',
description: 'Tests the endpoint',
routing: {
send: {
preSend: [setupRequest],
},
request: {
method: 'POST',
url: '',
baseURL: 'http://localhost:8088',
headers: {
'Content-Type': 'multipart/form-data'
},
},
},
},
- The
setupRequest
function is like this:
export async function getUploadFormData(
this: IExecuteSingleFunctions,
): Promise<{ formData: FormData }> {
const lastName = ((this.getNodeParameter('lastName') as string) || '').trim();
const firstName = ((this.getNodeParameter('firstName') as string) || '').trim();
const email = ((this.getNodeParameter('email') as string) || '').trim();
const formData = new FormData();
if (firstName) formData.append('first_name', firstName);
if (lastName) formData.append('last_name', lastName);
if (email) formData.append('email', email);
return { formData };
}
export async function setupRequest(
this: IExecuteSingleFunctions,
requestOptions: IHttpRequestOptions,
) {
const uploadData = await getUploadFormData.call(this);
requestOptions.body = uploadData.formData;
return requestOptions;
}
- The parameters are defined like this:
{
displayName: 'First name',
name: 'firstName',
type: 'string',
default: '',
displayOptions: {
show: {
resource: ['test'],
operation: ['testOperation'],
},
},
routing: {
request: {
body: {
first_name: '={{$value)}}',
},
},
},
},
{
displayName: 'Last name',
name: 'lastName',
type: 'string',
default: '',
displayOptions: {
show: {
resource: ['test'],
operation: ['testOperation'],
},
},
routing: {
request: {
body: {
last_name: '={{$value)}}',
},
},
},
},
{
displayName: 'Email',
name: 'email',
type: 'string',
placeholder: '[email protected]',
default: '',
displayOptions: {
show: {
resource: ['test'],
operation: ['testOperation'],
},
},
routing: {
request: {
body: {
email: '={{$value)}}',
},
},
},
}
Any idea of what I’m doing wrong? A missing option/encoding?
Information on your n8n setup
- n8n version: 0.227.1
- Database (default: SQLite): default
- n8n EXECUTIONS_PROCESS setting (default: own, main): default
- Running n8n via (Docker, npm, n8n cloud, desktop app): npm
- Operating system: Mac OS