first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,185 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import nock from 'nock';
import { parse as parseUrl } from 'url';
describe('Test HTTP Request Node', () => {
const baseUrl = 'https://dummyjson.com';
beforeAll(async () => {
function getPaginationReturnData(this: nock.ReplyFnContext, limit = 10, skip = 0) {
const nextUrl = `${baseUrl}/users?skip=${skip + limit}&limit=${limit}`;
const response = [];
for (let i = skip; i < skip + limit; i++) {
if (i > 14) {
break;
}
response.push({
id: i,
});
}
if (!response.length) {
return [
404,
response,
{
'next-url': nextUrl,
'content-type': this.req.headers['content-type'] || 'application/json',
},
];
}
return [
200,
response,
{
'next-url': nextUrl,
'content-type': this.req.headers['content-type'] || 'application/json',
},
];
}
//GET
nock(baseUrl).get('/todos/1').reply(200, {
id: 1,
todo: 'Do something nice for someone I care about',
completed: true,
userId: 26,
});
nock(baseUrl).get('/todos/1').reply(200, {
id: 1,
todo: 'Do something nice for someone I care about',
completed: true,
userId: 26,
});
nock(baseUrl).matchHeader('Authorization', 'Bearer 12345').get('/todos/3').reply(200, {
id: 3,
todo: 'Watch a classic movie',
completed: false,
userId: 4,
});
nock(baseUrl)
.get('/todos?limit=2&skip=10')
.reply(200, {
todos: [
{
id: 11,
todo: "Text a friend I haven't talked to in a long time",
completed: false,
userId: 39,
},
{
id: 12,
todo: 'Organize pantry',
completed: true,
userId: 39,
},
],
total: 150,
skip: 10,
limit: 2,
});
//POST
nock(baseUrl)
.post('/todos/add', {
todo: 'Use DummyJSON in the project',
completed: false,
userId: '5',
})
.reply(200, {
id: 151,
todo: 'Use DummyJSON in the project',
completed: false,
userId: '5',
});
nock(baseUrl)
.post('/todos/add2', {
todo: 'Use DummyJSON in the project',
completed: false,
userId: 15,
})
.reply(200, {
id: 151,
todo: 'Use DummyJSON in the project',
completed: false,
userId: 15,
});
nock(baseUrl).get('/html').reply(200, '<html><body><h1>Test</h1></body></html>');
//PUT
nock(baseUrl).put('/todos/10', { userId: '42' }).reply(200, {
id: 10,
todo: 'Have a football scrimmage with some friends',
completed: false,
userId: '42',
});
//PATCH
nock(baseUrl)
.patch('/products/1', '{"title":"iPhone 12"}')
.reply(200, {
id: 1,
title: 'iPhone 12',
price: 549,
stock: 94,
rating: 4.69,
images: [
'https://i.dummyjson.com/data/products/1/1.jpg',
'https://i.dummyjson.com/data/products/1/2.jpg',
'https://i.dummyjson.com/data/products/1/3.jpg',
'https://i.dummyjson.com/data/products/1/4.jpg',
'https://i.dummyjson.com/data/products/1/thumbnail.jpg',
],
thumbnail: 'https://i.dummyjson.com/data/products/1/thumbnail.jpg',
description: 'An apple mobile which is nothing like apple',
brand: 'Apple',
category: 'smartphones',
});
//DELETE
nock(baseUrl).delete('/todos/1').reply(200, {
id: 1,
todo: 'Do something nice for someone I care about',
completed: true,
userId: 26,
isDeleted: true,
deletedOn: '2023-02-09T05:37:31.720Z',
});
// Pagination - GET
nock(baseUrl)
.persist()
.get('/users')
.query(true)
.reply(function (uri) {
const data = parseUrl(uri, true);
const limit = parseInt((data.query.limit as string) || '10', 10);
const skip = parseInt((data.query.skip as string) || '0', 10);
return getPaginationReturnData.call(this, limit, skip);
});
// Pagination - POST
nock(baseUrl)
.persist()
.post('/users')
.reply(function (_uri, body) {
let skip = 0;
let limit = 10;
if (typeof body === 'string') {
// Form data
skip = parseInt(body.split('name="skip"')[1].split('---')[0] ?? '0', 10);
limit = parseInt(body.split('name="limit"')[1].split('---')[0] ?? '0', 10);
} else {
skip = parseInt(body.skip ?? '0', 10);
limit = parseInt(body.limit ?? '10', 10);
}
return getPaginationReturnData.call(this, limit, skip);
});
});
new NodeTestHarness().setupTests();
});
@@ -0,0 +1,163 @@
import type { IExecuteFunctions, INodeTypeBaseDescription } from 'n8n-workflow';
import { HttpRequestV2 } from '../../V2/HttpRequestV2.node';
describe('HttpRequestV2', () => {
let node: HttpRequestV2;
let executeFunctions: IExecuteFunctions;
const baseUrl = 'http://example.com';
const options = {
redirect: '',
batching: { batch: { batchSize: 1, batchInterval: 1 } },
proxy: '',
timeout: '',
allowUnauthorizedCerts: '',
queryParameterArrays: '',
response: '',
lowercaseHeaders: '',
};
beforeEach(() => {
const baseDescription: INodeTypeBaseDescription = {
displayName: 'HTTP Request',
name: 'httpRequest',
description: 'Makes an HTTP request and returns the response data',
group: [],
};
node = new HttpRequestV2(baseDescription);
executeFunctions = {
getInputData: jest.fn(),
getNodeParameter: jest.fn(),
getNode: jest.fn(() => {
return {
type: 'n8n-nodes-base.httpRequest',
typeVersion: 2,
};
}),
getCredentials: jest.fn(),
helpers: {
request: jest.fn(),
requestOAuth1: jest.fn(
async () =>
await Promise.resolve({
success: true,
}),
),
requestOAuth2: jest.fn(
async () =>
await Promise.resolve({
success: true,
}),
),
requestWithAuthentication: jest.fn(),
requestWithAuthenticationPaginated: jest.fn(),
assertBinaryData: jest.fn(),
getBinaryStream: jest.fn(),
getBinaryMetadata: jest.fn(),
binaryToString: jest.fn((buffer: Buffer) => {
return buffer.toString();
}),
prepareBinaryData: jest.fn(),
},
getContext: jest.fn(),
sendMessageToUI: jest.fn(),
continueOnFail: jest.fn(),
getMode: jest.fn(),
} as unknown as IExecuteFunctions;
});
describe('Authentication Handling', () => {
const authenticationTypes = [
{
genericCredentialType: 'httpBasicAuth',
credentials: { user: 'username', password: 'password' },
authField: 'auth',
authValue: { user: 'username', pass: 'password' },
},
{
genericCredentialType: 'httpBearerAuth',
credentials: { token: 'bearerToken123' },
authField: 'headers',
authValue: { Authorization: 'Bearer bearerToken123' },
},
{
genericCredentialType: 'httpDigestAuth',
credentials: { user: 'username', password: 'password' },
authField: 'auth',
authValue: { user: 'username', pass: 'password', sendImmediately: false },
},
{
genericCredentialType: 'httpHeaderAuth',
credentials: { name: 'Authorization', value: 'Bearer token' },
authField: 'headers',
authValue: { Authorization: 'Bearer token' },
},
{
genericCredentialType: 'httpQueryAuth',
credentials: { name: 'Token', value: 'secretToken' },
authField: 'qs',
authValue: { Token: 'secretToken' },
},
{
genericCredentialType: 'oAuth1Api',
credentials: { oauth_token: 'token', oauth_token_secret: 'secret' },
authField: 'oauth',
authValue: { oauth_token: 'token', oauth_token_secret: 'secret' },
},
{
genericCredentialType: 'oAuth2Api',
credentials: { access_token: 'accessToken' },
authField: 'auth',
authValue: { bearer: 'accessToken' },
},
];
it.each(authenticationTypes)(
'should handle $genericCredentialType authentication',
async ({ genericCredentialType, credentials, authField, authValue }) => {
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return baseUrl;
case 'authentication':
return 'genericCredentialType';
case 'genericAuthType':
return genericCredentialType;
case 'options':
return options;
case 'bodyParametersUi':
case 'headerParametersUi':
case 'queryParametersUi':
return { parameter: [] };
default:
return undefined;
}
});
(executeFunctions.getCredentials as jest.Mock).mockResolvedValue(credentials);
const response = {
success: true,
};
(executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response);
const result = await node.execute.call(executeFunctions);
expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]);
if (genericCredentialType === 'oAuth1Api') {
expect(executeFunctions.helpers.requestOAuth1).toHaveBeenCalled();
} else if (genericCredentialType === 'oAuth2Api') {
expect(executeFunctions.helpers.requestOAuth2).toHaveBeenCalled();
} else {
expect(executeFunctions.helpers.request).toHaveBeenCalledWith(
expect.objectContaining({
[authField]: expect.objectContaining(authValue),
}),
);
}
},
);
});
});
@@ -0,0 +1,427 @@
import type { IExecuteFunctions, INodeTypeBaseDescription } from 'n8n-workflow';
import { HttpRequestV3 } from '../../V3/HttpRequestV3.node';
describe('HttpRequestV3', () => {
let node: HttpRequestV3;
let executeFunctions: IExecuteFunctions;
const baseUrl = 'http://example.com';
const options = {
redirect: '',
batching: { batch: { batchSize: 1, batchInterval: 1 } },
proxy: '',
timeout: '',
allowUnauthoridCerts: '',
queryParameterArrays: '',
response: '',
lowercaseHeaders: '',
};
beforeEach(() => {
const baseDescription: INodeTypeBaseDescription = {
displayName: 'HTTP Request',
name: 'httpRequest',
description: 'Makes an HTTP request and returns the response data',
group: [],
};
node = new HttpRequestV3(baseDescription);
executeFunctions = {
getInputData: jest.fn(),
getNodeParameter: jest.fn(),
getNode: jest.fn(() => {
return {
type: 'n8n-nodes-base.httpRequest',
typeVersion: 3,
};
}),
getCredentials: jest.fn(),
helpers: {
request: jest.fn(),
requestOAuth1: jest.fn(
async () =>
await Promise.resolve({
statusCode: 200,
headers: { 'content-type': 'application/json' },
body: Buffer.from(JSON.stringify({ success: true })),
}),
),
requestOAuth2: jest.fn(
async () =>
await Promise.resolve({
statusCode: 200,
headers: { 'content-type': 'application/json' },
body: Buffer.from(JSON.stringify({ success: true })),
}),
),
requestWithAuthentication: jest.fn(),
requestWithAuthenticationPaginated: jest.fn(),
assertBinaryData: jest.fn(),
getBinaryStream: jest.fn(),
getBinaryMetadata: jest.fn(),
binaryToString: jest.fn((buffer: Buffer) => {
return buffer.toString();
}),
prepareBinaryData: jest.fn(),
},
getContext: jest.fn(),
sendMessageToUI: jest.fn(),
continueOnFail: jest.fn(),
getMode: jest.fn(),
} as unknown as IExecuteFunctions;
});
it('should make a GET request', async () => {
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return baseUrl;
case 'authentication':
return 'none';
case 'options':
return options;
default:
return undefined;
}
});
const response = {
headers: { 'content-type': 'application/json' },
body: Buffer.from(JSON.stringify({ success: true })),
};
(executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response);
const result = await node.execute.call(executeFunctions);
expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]);
});
it('should handle authentication', async () => {
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return baseUrl;
case 'authentication':
return 'genericCredentialType';
case 'genericAuthType':
return 'httpBasicAuth';
case 'options':
return options;
default:
return undefined;
}
});
(executeFunctions.getCredentials as jest.Mock).mockResolvedValue({
user: 'username',
password: 'password',
});
const response = {
headers: { 'content-type': 'application/json' },
body: Buffer.from(JSON.stringify({ success: true })),
};
(executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response);
const result = await node.execute.call(executeFunctions);
expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]);
expect(executeFunctions.helpers.request).toHaveBeenCalledWith(
expect.objectContaining({
auth: {
user: 'username',
pass: 'password',
},
}),
);
});
describe('Authentication Handling', () => {
const authenticationTypes = [
{
genericCredentialType: 'httpBasicAuth',
credentials: { user: 'username', password: 'password' },
authField: 'auth',
authValue: { user: 'username', pass: 'password' },
},
{
genericCredentialType: 'httpBearerAuth',
credentials: { token: 'bearerToken123' },
authField: 'headers',
authValue: { Authorization: 'Bearer bearerToken123' },
},
{
genericCredentialType: 'httpDigestAuth',
credentials: { user: 'username', password: 'password' },
authField: 'auth',
authValue: { user: 'username', pass: 'password', sendImmediately: false },
},
{
genericCredentialType: 'httpHeaderAuth',
credentials: { name: 'Authorization', value: 'Bearer token' },
authField: 'headers',
authValue: { Authorization: 'Bearer token' },
},
{
genericCredentialType: 'httpQueryAuth',
credentials: { name: 'Token', value: 'secretToken' },
authField: 'qs',
authValue: { Token: 'secretToken' },
},
{
genericCredentialType: 'oAuth1Api',
credentials: { oauth_token: 'token', oauth_token_secret: 'secret' },
authField: 'oauth',
authValue: { oauth_token: 'token', oauth_token_secret: 'secret' },
},
{
genericCredentialType: 'oAuth2Api',
credentials: { access_token: 'accessToken' },
authField: 'auth',
authValue: { bearer: 'accessToken' },
},
];
it.each(authenticationTypes)(
'should handle $genericCredentialType authentication',
async ({ genericCredentialType, credentials, authField, authValue }) => {
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return baseUrl;
case 'authentication':
return 'genericCredentialType';
case 'genericAuthType':
return genericCredentialType;
case 'options':
return options;
default:
return undefined;
}
});
(executeFunctions.getCredentials as jest.Mock).mockResolvedValue(credentials);
const response = {
headers: { 'content-type': 'application/json' },
body: Buffer.from(JSON.stringify({ success: true })),
};
(executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response);
const result = await node.execute.call(executeFunctions);
expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]);
if (genericCredentialType === 'oAuth1Api') {
expect(executeFunctions.helpers.requestOAuth1).toHaveBeenCalled();
} else if (genericCredentialType === 'oAuth2Api') {
expect(executeFunctions.helpers.requestOAuth2).toHaveBeenCalled();
} else {
expect(executeFunctions.helpers.request).toHaveBeenCalledWith(
expect.objectContaining({
[authField]: expect.objectContaining(authValue),
}),
);
}
},
);
});
describe('URL Parameter Validation', () => {
it('should throw error when URL is undefined', async () => {
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return undefined;
case 'authentication':
return 'none';
case 'options':
return options;
default:
return undefined;
}
});
await expect(node.execute.call(executeFunctions)).rejects.toThrow(
'URL parameter must be a string, got undefined',
);
});
it('should throw error when URL is null', async () => {
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return null;
case 'authentication':
return 'none';
case 'options':
return options;
default:
return undefined;
}
});
await expect(node.execute.call(executeFunctions)).rejects.toThrow(
'URL parameter must be a string, got null',
);
});
it('should throw error when URL is a number', async () => {
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return 42;
case 'authentication':
return 'none';
case 'options':
return options;
default:
return undefined;
}
});
await expect(node.execute.call(executeFunctions)).rejects.toThrow(
'URL parameter must be a string, got number',
);
});
});
describe('Cross-Origin Redirects', () => {
it('should pass sendCredentialsOnCrossOriginRedirect = true to the request by default for node versions < 4.4', async () => {
(executeFunctions.getNode as jest.Mock).mockReturnValue({
typeVersion: 4.3,
});
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return baseUrl;
case 'authentication':
return 'genericCredentialType';
case 'genericAuthType':
return 'httpBasicAuth';
case 'options':
return options;
default:
return undefined;
}
});
(executeFunctions.getCredentials as jest.Mock).mockResolvedValue({
user: 'username',
password: 'password',
});
const response = {
headers: { 'content-type': 'application/json' },
body: Buffer.from(JSON.stringify({ success: true })),
};
(executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response);
const result = await node.execute.call(executeFunctions);
expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]);
expect(executeFunctions.helpers.request).toHaveBeenCalledWith(
expect.objectContaining({
sendCredentialsOnCrossOriginRedirect: true,
}),
);
});
it('should pass sendCredentialsOnCrossOriginRedirect = false to the request by default for node versions >= 4.4', async () => {
(executeFunctions.getNode as jest.Mock).mockReturnValue({
typeVersion: 4.4,
});
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return baseUrl;
case 'authentication':
return 'genericCredentialType';
case 'genericAuthType':
return 'httpBasicAuth';
case 'options':
return options;
default:
return undefined;
}
});
(executeFunctions.getCredentials as jest.Mock).mockResolvedValue({
user: 'username',
password: 'password',
});
const response = {
headers: { 'content-type': 'application/json' },
body: Buffer.from(JSON.stringify({ success: true })),
};
(executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response);
const result = await node.execute.call(executeFunctions);
expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]);
expect(executeFunctions.helpers.request).toHaveBeenCalledWith(
expect.objectContaining({
sendCredentialsOnCrossOriginRedirect: false,
}),
);
});
it('should use the sendCredentialsOnCrossOriginRedirect parameter to the request if provided', async () => {
(executeFunctions.getNode as jest.Mock).mockReturnValue({
typeVersion: 4.4,
});
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return baseUrl;
case 'authentication':
return 'genericCredentialType';
case 'genericAuthType':
return 'httpBasicAuth';
case 'options':
return { ...options, sendCredentialsOnCrossOriginRedirect: true };
default:
return undefined;
}
});
(executeFunctions.getCredentials as jest.Mock).mockResolvedValue({
user: 'username',
password: 'password',
});
const response = {
headers: { 'content-type': 'application/json' },
body: Buffer.from(JSON.stringify({ success: true })),
};
(executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response);
const result = await node.execute.call(executeFunctions);
expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]);
expect(executeFunctions.helpers.request).toHaveBeenCalledWith(
expect.objectContaining({
sendCredentialsOnCrossOriginRedirect: true,
}),
);
});
});
});
@@ -0,0 +1,60 @@
{
"name": "http request test",
"nodes": [
{
"parameters": {},
"id": "12433cfb-74d9-4bf1-9afd-0ab9afc9ef19",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [820, 360]
},
{
"parameters": {
"method": "DELETE",
"url": "https://dummyjson.com/todos/1",
"options": {}
},
"id": "312e64ca-00bf-40e6-b21d-1f73930ef98c",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [1100, 360]
}
],
"pinData": {
"HTTP Request": [
{
"json": {
"id": 1,
"todo": "Do something nice for someone I care about",
"completed": true,
"userId": 26,
"isDeleted": true,
"deletedOn": "2023-02-09T05:37:31.720Z"
}
}
]
},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"versionId": "b1c4f6ef-0d15-49f3-b46d-447671b1583e",
"id": "108",
"meta": {
"instanceId": "36203ea1ce3cef713fa25999bd9874ae26b9e4c2c3a90a365f2882a154d031d0"
},
"tags": []
}
@@ -0,0 +1,188 @@
{
"name": "HTTP Request test",
"nodes": [
{
"parameters": {},
"id": "3db51d12-a71b-4d0d-84db-1d4c46454c40",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
160,
720
]
},
{
"parameters": {
"url": "https://dummyjson.com/todos/1",
"options": {}
},
"id": "96f38d87-0bdd-420c-b981-26fd55d11cb2",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
460,
460
]
},
{
"parameters": {
"url": "https://dummyjson.com/todos/3",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer 12345"
}
]
},
"options": {}
},
"id": "85ca0a5b-3ff4-491d-ba51-990fdf2b757f",
"name": "HTTP Request fake header",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
460,
800
]
},
{
"parameters": {
"url": "https://dummyjson.com/todos",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "limit",
"value": "2"
},
{
"name": "skip",
"value": "10"
}
]
},
"options": {}
},
"id": "68d6e51a-66ea-45bf-928c-55efd2493cf0",
"name": "HTTP Request with query",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
460,
980
]
},
{
"parameters": {
"url": "https://dummyjson.com/todos/1",
"sendHeaders": true,
"options": {}
},
"id": "38ec1a50-7f0e-4749-822d-f26370b00694",
"name": "HTTP Request empty header",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
460,
640
]
}
],
"pinData": {
"HTTP Request": [
{
"json": {
"id": 1,
"todo": "Do something nice for someone I care about",
"completed": true,
"userId": 26
}
}
],
"HTTP Request with query": [
{
"json": {
"todos": [
{
"id": 11,
"todo": "Text a friend I haven't talked to in a long time",
"completed": false,
"userId": 39
},
{
"id": 12,
"todo": "Organize pantry",
"completed": true,
"userId": 39
}
],
"total": 150,
"skip": 10,
"limit": 2
}
}
],
"HTTP Request fake header": [
{
"json": {
"id": 3,
"todo": "Watch a classic movie",
"completed": false,
"userId": 4
}
}
],
"HTTP Request empty header": [
{
"json": {
"id": 1,
"todo": "Do something nice for someone I care about",
"completed": true,
"userId": 26
}
}
]
},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
},
{
"node": "HTTP Request with query",
"type": "main",
"index": 0
},
{
"node": "HTTP Request fake header",
"type": "main",
"index": 0
},
{
"node": "HTTP Request empty header",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "27cc9b56542ad45b38725555722c50a1c3fee1670bbb67980558314ee08517c4"
},
"tags": []
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,73 @@
{
"name": "http request test",
"nodes": [
{
"parameters": {},
"id": "12433cfb-74d9-4bf1-9afd-0ab9afc9ef19",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [820, 360]
},
{
"parameters": {
"method": "PATCH",
"url": "https://dummyjson.com/products/1",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\"title\":\"iPhone 12\"}",
"options": {}
},
"id": "312e64ca-00bf-40e6-b21d-1f73930ef98c",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [1100, 360]
}
],
"pinData": {
"HTTP Request": [
{
"json": {
"id": 1,
"title": "iPhone 12",
"price": 549,
"stock": 94,
"rating": 4.69,
"images": [
"https://i.dummyjson.com/data/products/1/1.jpg",
"https://i.dummyjson.com/data/products/1/2.jpg",
"https://i.dummyjson.com/data/products/1/3.jpg",
"https://i.dummyjson.com/data/products/1/4.jpg",
"https://i.dummyjson.com/data/products/1/thumbnail.jpg"
],
"thumbnail": "https://i.dummyjson.com/data/products/1/thumbnail.jpg",
"description": "An apple mobile which is nothing like apple",
"brand": "Apple",
"category": "smartphones"
}
}
]
},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"versionId": "a49ffcc8-e61f-4fcd-93c0-c1c422d14b6c",
"id": "108",
"meta": {
"instanceId": "36203ea1ce3cef713fa25999bd9874ae26b9e4c2c3a90a365f2882a154d031d0"
},
"tags": []
}
@@ -0,0 +1,105 @@
{
"name": "http request test",
"nodes": [
{
"parameters": {},
"id": "12433cfb-74d9-4bf1-9afd-0ab9afc9ef19",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [820, 360]
},
{
"parameters": {
"method": "POST",
"url": "https://dummyjson.com/todos/add",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "todo",
"value": "Use DummyJSON in the project"
},
{
"name": "completed",
"value": "={{ false }}"
},
{
"name": "userId",
"value": "5"
}
]
},
"options": {}
},
"id": "07670093-862f-403f-96a5-ddf7fdb0d225",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [1140, 200]
},
{
"parameters": {
"method": "POST",
"url": "https://dummyjson.com/todos/add2",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\"todo\":\"Use DummyJSON in the project\",\"completed\":false,\"userId\":15}",
"options": {}
},
"id": "db088210-2204-422c-823a-101afa464384",
"name": "HTTP Request1",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [1140, 440]
}
],
"pinData": {
"HTTP Request": [
{
"json": {
"id": 151,
"todo": "Use DummyJSON in the project",
"completed": false,
"userId": "5"
}
}
],
"HTTP Request1": [
{
"json": {
"id": 151,
"todo": "Use DummyJSON in the project",
"completed": false,
"userId": 15
}
}
]
},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
},
{
"node": "HTTP Request1",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"versionId": "c5d9075a-6d1e-49d8-b16b-7df985ebda69",
"id": "108",
"meta": {
"instanceId": "36203ea1ce3cef713fa25999bd9874ae26b9e4c2c3a90a365f2882a154d031d0"
},
"tags": []
}
@@ -0,0 +1,73 @@
{
"name": "http request test",
"nodes": [
{
"parameters": {},
"id": "12433cfb-74d9-4bf1-9afd-0ab9afc9ef19",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
820,
360
]
},
{
"parameters": {
"method": "PUT",
"url": "https://dummyjson.com/todos/10",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "userId",
"value": "42"
}
]
},
"options": {}
},
"id": "07670093-862f-403f-96a5-ddf7fdb0d225",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
1100,
360
]
}
],
"pinData": {
"HTTP Request": [
{
"json": {
"id": 10,
"todo": "Have a football scrimmage with some friends",
"completed": false,
"userId": "42"
}
}
]
},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"versionId": "209dd43e-fa03-4da7-94fb-cecf1974c5fe",
"id": "108",
"meta": {
"instanceId": "36203ea1ce3cef713fa25999bd9874ae26b9e4c2c3a90a365f2882a154d031d0"
},
"tags": []
}
@@ -0,0 +1,161 @@
{
"name": "HTTP Request Node: Continue using error output not working",
"nodes": [
{
"parameters": {},
"id": "6707decf-7ae3-46f1-8603-b0fe4844f240",
"name": "When clicking Execute workflow",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [16, 560]
},
{
"parameters": {},
"id": "09b63a84-789d-4a31-b546-849ba47ed689",
"name": "Success path",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [464, 272]
},
{
"parameters": {
"method": "POST",
"url": "https://dummyjson.com/todos/1",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\n \"q\": \"abc\",\n}",
"options": {}
},
"id": "c6841eb1-7913-4c8d-8c9d-b88a908125ed",
"name": "Invalid JSON Body",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [240, 368],
"alwaysOutputData": false,
"onError": "continueErrorOutput"
},
{
"parameters": {},
"id": "21750b7e-c18a-43a5-a068-f8aa85d1cadf",
"name": "Success path1",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [464, 656]
},
{
"parameters": {
"url": "https://dummyjson.com/html",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "ae2891f0-1968-4f57-a1a0-87d6f6dab57d",
"name": "Invalid JSON Response",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [240, 752],
"alwaysOutputData": false,
"onError": "continueErrorOutput"
},
{
"parameters": {},
"id": "baa75f00-e0dd-40b2-b718-1e8311549a05",
"name": "Request body error",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [464, 464]
},
{
"parameters": {},
"id": "4733c47f-38c8-44a8-9d77-d9e733777cbf",
"name": "Response body error",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [464, 848]
}
],
"pinData": {
"Request body error": [
{
"json": {
"error": "JSON parameter needs to be valid JSON"
}
}
],
"Response body error": [
{
"json": {
"error": "Response body is not valid JSON. Change \"Response Format\" to \"Text\""
}
}
]
},
"connections": {
"When clicking Execute workflow": {
"main": [
[
{
"node": "Invalid JSON Body",
"type": "main",
"index": 0
},
{
"node": "Invalid JSON Response",
"type": "main",
"index": 0
}
]
]
},
"Invalid JSON Body": {
"main": [
[
{
"node": "Success path",
"type": "main",
"index": 0
}
],
[
{
"node": "Request body error",
"type": "main",
"index": 0
}
]
]
},
"Invalid JSON Response": {
"main": [
[
{
"node": "Success path1",
"type": "main",
"index": 0
}
],
[
{
"node": "Response body error",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "c7026310-8c4f-4889-a45b-befebacc7dde",
"meta": {
"instanceId": "27cc9b56542ad45b38725555722c50a1c3fee1670bbb67980558314ee08517c4"
},
"id": "2Zd3If2j9PglrHri",
"tags": []
}