n8n-nodes-nvk-browser 1.0.21 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -731,7 +731,6 @@ async function executeGetNetworkResponse(i, browserManager, returnData) {
|
|
|
731
731
|
}
|
|
732
732
|
}
|
|
733
733
|
async function executeBrowserHttpRequest(i, browserManager, returnData) {
|
|
734
|
-
const items = this.getInputData();
|
|
735
734
|
const profileId = this.getNodeParameter('profileId', i);
|
|
736
735
|
const method = this.getNodeParameter('method', i) || 'GET';
|
|
737
736
|
const url = this.getNodeParameter('url', i);
|
|
@@ -784,10 +783,11 @@ async function executeBrowserHttpRequest(i, browserManager, returnData) {
|
|
|
784
783
|
let body;
|
|
785
784
|
let contentType;
|
|
786
785
|
let useFormData = false;
|
|
786
|
+
let bodyContentType;
|
|
787
787
|
if (method === 'POST') {
|
|
788
788
|
const sendBody = this.getNodeParameter('sendBody', i);
|
|
789
789
|
if (sendBody) {
|
|
790
|
-
|
|
790
|
+
bodyContentType = this.getNodeParameter('bodyContentType', i);
|
|
791
791
|
if (bodyContentType === 'json') {
|
|
792
792
|
const jsonBody = this.getNodeParameter('jsonBody', i);
|
|
793
793
|
body = jsonBody;
|
|
@@ -799,26 +799,37 @@ async function executeBrowserHttpRequest(i, browserManager, returnData) {
|
|
|
799
799
|
contentType = 'text/plain';
|
|
800
800
|
}
|
|
801
801
|
else if (bodyContentType === 'binary') {
|
|
802
|
-
// Handle n8n Binary File
|
|
802
|
+
// Handle n8n Binary File - similar to n8n HTTP Request
|
|
803
803
|
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
|
804
|
-
const
|
|
805
|
-
|
|
806
|
-
|
|
804
|
+
const itemBinaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
|
|
805
|
+
let uploadData;
|
|
806
|
+
let contentLength;
|
|
807
|
+
if (itemBinaryData.id) {
|
|
808
|
+
// Binary data is stored as stream/file
|
|
809
|
+
const binaryStream = await this.helpers.getBinaryStream(itemBinaryData.id);
|
|
810
|
+
const chunks = [];
|
|
811
|
+
for await (const chunk of binaryStream) {
|
|
812
|
+
chunks.push(chunk);
|
|
813
|
+
}
|
|
814
|
+
uploadData = Buffer.concat(chunks);
|
|
815
|
+
contentLength = uploadData.length;
|
|
816
|
+
}
|
|
817
|
+
else {
|
|
818
|
+
// Binary data is in memory
|
|
819
|
+
uploadData = Buffer.from(itemBinaryData.data, 'base64');
|
|
820
|
+
contentLength = uploadData.length;
|
|
807
821
|
}
|
|
808
|
-
const binaryData = item.binary[binaryPropertyName];
|
|
809
|
-
const binaryBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
810
822
|
// Convert binary to base64 for transfer to browser context
|
|
811
|
-
const base64Data =
|
|
812
|
-
const mimeType =
|
|
813
|
-
|
|
814
|
-
// We'll send this to browser context to create FormData
|
|
823
|
+
const base64Data = uploadData.toString('base64');
|
|
824
|
+
const mimeType = itemBinaryData.mimeType || 'application/octet-stream';
|
|
825
|
+
// Send binary data directly (not as FormData)
|
|
815
826
|
body = JSON.stringify({
|
|
816
827
|
type: 'binary',
|
|
817
828
|
data: base64Data,
|
|
818
829
|
mimeType,
|
|
819
|
-
|
|
830
|
+
contentLength,
|
|
820
831
|
});
|
|
821
|
-
|
|
832
|
+
contentType = mimeType;
|
|
822
833
|
}
|
|
823
834
|
else if (bodyContentType === 'formData') {
|
|
824
835
|
const formDataParam = this.getNodeParameter('formData', i);
|
|
@@ -830,21 +841,31 @@ async function executeBrowserHttpRequest(i, browserManager, returnData) {
|
|
|
830
841
|
for (const param of formDataParam.parameter) {
|
|
831
842
|
if (param.name) {
|
|
832
843
|
if (param.parameterType === 'binary') {
|
|
844
|
+
// Handle binary file in form data - similar to n8n HTTP Request
|
|
833
845
|
const binaryPropertyName = param.binaryPropertyName || 'data';
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
846
|
+
const itemBinaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
|
|
847
|
+
let uploadData;
|
|
848
|
+
if (itemBinaryData.id) {
|
|
849
|
+
// Binary data is stored as stream/file
|
|
850
|
+
const binaryStream = await this.helpers.getBinaryStream(itemBinaryData.id);
|
|
851
|
+
const chunks = [];
|
|
852
|
+
for await (const chunk of binaryStream) {
|
|
853
|
+
chunks.push(chunk);
|
|
854
|
+
}
|
|
855
|
+
uploadData = Buffer.concat(chunks);
|
|
856
|
+
}
|
|
857
|
+
else {
|
|
858
|
+
// Binary data is in memory
|
|
859
|
+
uploadData = Buffer.from(itemBinaryData.data, 'base64');
|
|
837
860
|
}
|
|
838
|
-
const
|
|
839
|
-
const binaryBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
840
|
-
const base64Data = binaryBuffer.toString('base64');
|
|
861
|
+
const base64Data = uploadData.toString('base64');
|
|
841
862
|
formDataItems.push({
|
|
842
863
|
name: param.name,
|
|
843
864
|
type: 'binary',
|
|
844
865
|
binaryData: {
|
|
845
866
|
data: base64Data,
|
|
846
|
-
mimeType:
|
|
847
|
-
fileName:
|
|
867
|
+
mimeType: itemBinaryData.mimeType || 'application/octet-stream',
|
|
868
|
+
fileName: itemBinaryData.fileName || 'file',
|
|
848
869
|
},
|
|
849
870
|
});
|
|
850
871
|
}
|
|
@@ -878,8 +899,16 @@ async function executeBrowserHttpRequest(i, browserManager, returnData) {
|
|
|
878
899
|
}
|
|
879
900
|
}
|
|
880
901
|
}
|
|
881
|
-
//
|
|
882
|
-
|
|
902
|
+
// Set Content-Type header
|
|
903
|
+
// For binary body, set content-type and content-length
|
|
904
|
+
if (bodyContentType === 'binary' && typeof body === 'string') {
|
|
905
|
+
const bodyData = JSON.parse(body);
|
|
906
|
+
if (bodyData.type === 'binary') {
|
|
907
|
+
browserHeaders['Content-Type'] = bodyData.mimeType || 'application/octet-stream';
|
|
908
|
+
browserHeaders['Content-Length'] = String(bodyData.contentLength || 0);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
else if (contentType && !useFormData) {
|
|
883
912
|
browserHeaders['Content-Type'] = contentType;
|
|
884
913
|
}
|
|
885
914
|
const response = await page.evaluate(async (requestData) => {
|
|
@@ -888,55 +917,62 @@ async function executeBrowserHttpRequest(i, browserManager, returnData) {
|
|
|
888
917
|
headers: requestData.headers,
|
|
889
918
|
};
|
|
890
919
|
if (requestData.body) {
|
|
891
|
-
if (
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
920
|
+
if (typeof requestData.body === 'string') {
|
|
921
|
+
try {
|
|
922
|
+
const bodyObj = JSON.parse(requestData.body);
|
|
923
|
+
if (bodyObj.type === 'binary' && bodyObj.data) {
|
|
924
|
+
// Binary body - send directly as ArrayBuffer
|
|
925
|
+
const binaryData = bodyObj.data;
|
|
926
|
+
// Convert base64 to ArrayBuffer
|
|
927
|
+
const binaryString = atob(binaryData);
|
|
928
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
929
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
930
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
931
|
+
}
|
|
932
|
+
fetchOptions.body = bytes.buffer;
|
|
933
|
+
// Content-Type and Content-Length are already set in headers
|
|
903
934
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
935
|
+
else if (bodyObj.type === 'formData' && requestData.useFormData) {
|
|
936
|
+
// FormData with mixed text and binary
|
|
937
|
+
const formData = new FormData();
|
|
938
|
+
const items = bodyObj.items || [];
|
|
939
|
+
for (const item of items) {
|
|
940
|
+
if (item.type === 'binary' && item.binaryData && item.binaryData.data) {
|
|
941
|
+
const binaryData = item.binaryData.data;
|
|
942
|
+
const mimeType = item.binaryData.mimeType || 'application/octet-stream';
|
|
943
|
+
const fileName = item.binaryData.fileName || 'file';
|
|
944
|
+
// Convert base64 to blob
|
|
945
|
+
const binaryString = atob(binaryData);
|
|
946
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
947
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
948
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
949
|
+
}
|
|
950
|
+
const blob = new Blob([bytes], { type: mimeType });
|
|
951
|
+
const file = new File([blob], fileName, { type: mimeType });
|
|
952
|
+
formData.append(item.name, file);
|
|
953
|
+
}
|
|
954
|
+
else {
|
|
955
|
+
formData.append(item.name, item.value || '');
|
|
922
956
|
}
|
|
923
|
-
const blob = new Blob([bytes], { type: mimeType });
|
|
924
|
-
const file = new File([blob], fileName, { type: mimeType });
|
|
925
|
-
formData.append(item.name, file);
|
|
926
957
|
}
|
|
927
|
-
|
|
928
|
-
|
|
958
|
+
fetchOptions.body = formData;
|
|
959
|
+
// Remove Content-Type header when using FormData (browser will set it with boundary)
|
|
960
|
+
if (fetchOptions.headers && typeof fetchOptions.headers === 'object' && !Array.isArray(fetchOptions.headers)) {
|
|
961
|
+
delete fetchOptions.headers['Content-Type'];
|
|
929
962
|
}
|
|
930
963
|
}
|
|
931
|
-
|
|
964
|
+
else {
|
|
965
|
+
// Regular string body
|
|
966
|
+
fetchOptions.body = typeof requestData.body === 'string' ? requestData.body : String(requestData.body);
|
|
967
|
+
}
|
|
932
968
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
969
|
+
catch {
|
|
970
|
+
// Not JSON, treat as regular string
|
|
971
|
+
fetchOptions.body = typeof requestData.body === 'string' ? requestData.body : String(requestData.body);
|
|
936
972
|
}
|
|
937
973
|
}
|
|
938
974
|
else {
|
|
939
|
-
fetchOptions.body = requestData.body;
|
|
975
|
+
fetchOptions.body = typeof requestData.body === 'string' ? requestData.body : String(requestData.body);
|
|
940
976
|
}
|
|
941
977
|
}
|
|
942
978
|
const response = await fetch(requestData.url, fetchOptions);
|
package/package.json
CHANGED