aws elasticsearch getting signature error on post request - node.js

Got a 403 signature error , when using the below fetch function:
function elasticsearchFetch(AWS, elasticsearchDomain, endpointPath, options = {}, region = process.env.AWS_REGION) {
return new Promise((resolve, reject) => {
const { body, method = 'GET' } = options;
const endpoint = new AWS.Endpoint(elasticsearchDomain);
const request = new AWS.HttpRequest(endpoint, region);
request.method = method;
request.path += endpointPath;
request.headers.host = elasticsearchDomain;
if (body) {
request.body = body;
request.headers['Content-Type'] = 'application/json';
request.headers['Content-Length'] = request.body.length;
}
const credentials = new AWS.EnvironmentCredentials('AWS');
const signer = new AWS.Signers.V4(request, 'es');
signer.addAuthorization(credentials, new Date());
const client = new AWS.HttpClient();
client.handleRequest(request, null, (res) => {
let chunks = '';
res.on('data', (chunk) => {
chunks += chunk;
});
res.on('end', () => {
if (res.statusCode !== 201) console.log('Got these options STATUSCODE', JSON.stringify(options, false, 2));
return resolve({ statusCode: res.statusCode, body: chunks });
});
}, (error) => {
console.log('Got these options ERROR', JSON.stringify(options, false, 2));
return reject(error);
});
});
}
This is the options used for the request in above function :
{
"method": "POST",
"body": "{\"prefix\":\"image_233/ArtService/articles-0/GB/ART-60297885/\",\"id\":\"ART-60297885\",\"retailUnit\":\"GB\",\"commercial\":{\"name\":{\"en-GB\":\"FÖRBÄTTRA\"}},\"schemaType\":\"product\",\"productType\":\"ART\"}"
}
and got this error :
{
"statusCode": 403,
"body": "{\"message\":\"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\"}"
}
This is the endpoint : 233/_doc/

I believe your Content-Length header is incorrect, causing the signature mismatch.
Your payload includes the string FÖRBÄTTRA, which has two double-byte characters.
You're setting the Content-Length to request.body.length, which comes to 186.
While this is the number of characters in the body, it is not the number of bytes in the body (188).
To calculate the Content-Length, use Buffer.byteLength(request.body). For a POST request like this, you can even remove that line of code altogether, and the request will succeed.
// Content-Length is only needed for DELETE requests that include a request
// body, but including it for all requests doesn't seem to hurt anything.
request.headers['Content-Length'] = Buffer.byteLength(request.body);
Source: https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-request-signing.html#es-request-signing-node

By the way, why not use elasticsearch client for nodejs to communicate with elasticsearch rather than writing your own logic. You can consider using http-aws-es which does the request signing part for you. The code will look like
const { Client } = require("elasticsearch");
const esConnectionClass = require("http-aws-es");
const elasticsearchConfig = {
host: "somePath",
connectionClass: esConnectionClass
};
const nativeClient = new Client(elasticsearchConfig);
const result = await nativeClient.search({});

Related

AWS Using Lambda to Get S3 Object

I have put together an AWS API Gateway (HTTP) that triggers a lambda function. The lambda function gets an object from an S3 bucket. I've followed the docs from AWS, and I'm getting the objects body contents successfully but the PDF is coming through corrupted.
I have also reviewed this post on AWS, but for some reason when I add isBase64Encoded: true the response returns as 500 and no detail gets logged to CloudWatch.
const getSupportingDocs = async (doc_id) => {
try {
const streamToString = (stream) =>
new Promise((resolve, reject) => {
const chunks = [];
stream.on("data", (chunk) => chunks.push(chunk));
stream.on("error", reject);
stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
});
const command = new GetObjectCommand({
Bucket: "deq-waterlink-at",
Key: doc_id,
});
const { Body } = await s3Client.send(command);
//const { Body } = await s3Client.send(command).promise(); -> tried & nothing happened
const bodyContents = await streamToString(Body);
//console.log(bodyContents);
return bodyContents;
}
catch (err) {
console.log("ERROR DOWNLOADING: ", err);
}
};
exports.handler = async (event) => {
console.log("EVENT: ", event);
let response;
try {
if (event.queryStringParameters) {
let key = event.queryStringParameters['doc-id'];
let doc = await getSupportingDocs(`interactiveMap/${key}`);
response ={
"statusCode":200,
"body": JSON.stringify(doc),
/*"isBase64Encoded": true, --> Results in an Internal Server Error*/
"headers": {"content-type": "application/pdf"}
};
}
else {
response = {
statusCode: 200,
body: JSON.stringify('No Document ID included'),
};
}
return response;
}
catch (err) {
console.log("ERROR: ", err);
}
};
UPDATE:
After following the suggestion by Daniel Seichter below I was able to get the download triggered but I get an error message when trying to open the PDF that the file is damaged and cannot be repaired. If I removed the JSON.stringify around doc that file downloads but is blank.
I can directly download the file from S3 and it is not corrupted so something is happening in the download process.
I can log the response that the function generates and get the response below, but the browser returns a 500 response.
2022-08-03T21:56:12.163Z 9bd65c5c-6742-45a3-a6ef-6f314e4efa89 INFO RESPONSE: {
statusCode: 200,
headers: { 'content-type': 'application/pdf' },
isBase64Encoded: true,
body: '"%PDF-1.7\\n\\n4 0 obj\\n(Identity)\\nendobj\\n5 0 obj\\n(Adobe)\\nendobj\\n8 0 obj\\n<<\\n/Filter /FlateDecode\\n/Length 35942\\n/Length1 67496\\n/Type /Stream\\n>>\\nstream\\nx��\\u0007X\\u0014��?~�ݙ��.\\u001d�]\\u0016\\u0010\\\\p\\u0017V���bÂ�\\u00114(\\b(��J�+D�5�\\u0016M��ILL̛\\u00045�E\\r��Ę^Mb��f�2�;wv�\\u0012�����<�����a>s��{��{Ν\\u0001�\\u0000�\\u0019�\\u0003O^Ѱ!m�[;\\u0000\\u0016F\\u0001D?6$/\x7F0��\\u000b\\u00006���z\\f)\\u001c]t��u\\u0014�\x7F\\u0004(=2�h\\\\΢w�g\\u0003�܎�l\\u001f]�Lm�d�\\t\\u0000�\\"�/�&odI�O��\\u0000BN\\u0001�\'*�*�\\u0003NNa\\u0001�^�2\'+�4Yg�x�\\u0006�\\u0017�g�S���~�=U�Ma}�ߦU4z!\\flH\\u000f�\\u0001ô�󧖏��\\u0018#�G\\u0000}~��������X�\\b�O��\\u0004c��[��a<���i^����\\u0000�\\u0004��ٙ��\\u0015k�.l\x7F\\n��:UW1�+�Q���\\u000f`yk]uSE��\\\\\\u000bDY���Y\\u0015uպ��4\\u0001��\\u0007к���M�yp\\u001c`�)Z��P��\\u001b��\\u0001���y��K�xၭ������B�\\u0000�xxf�\\u001f�����s�w��> �Dz\\"0�?�9A-�\\u0005�eb�l�\\u0003rM\\u0017\\u001d�i��7C\\u001f`�\\u0004\\u0006\\f��\\tȵY���\\u0014�[�\\u001c\\u0002\\u001e\\u0004�vލU����68��\\u00020j�cy�c�m��y�:�r�>8��j\\u0005<�q�\\u001eR)�,��#V w��V��hO�\\u0015\\u0002$a\\u001b�%��\\u001dp��+���o�W���wa\\u0016�\\u000f\\u001e�t�\\f<��a�b;\\u001c����\\u0007�(\\u0016�4��I�P.���p8�܈y��\\u0011����wE\\u000e�=\\nu|\\u0013$*Z�A�&*!��\\r~\\u0015��\\u000f�\\u0004��7�N�q(��\\u0004�\\u0010J�\\np��=�\\u0013y���,�w\\nsa\'M���w�t�/|�I��އ�큻i��\\u001dH�\'#\\u0004�\\u0006=��\\u0018�\x7F|p/�f�Z��������\\u001e8��q��z\\\\=�\\u001eW������q��z\\\\=����vp\\b�����۾\\u0004�\\u000b�|$l���z�\\u0001����\\f���\\u0000���a;�;,��5c�tخX�y{��?\\u0001^^��r�L��\\txŢϻ��)�\\u0003r��`�\\u0013A�~3\\\\=�\\u001eW��\\u001d�\\u001e^��<�<��˺z�� #�\\u0001\\u001a�C��\\u0000�O\\u0002\\u0011T�*\\u0019ՠFԀ\\u0006Q\\u000bZ_\'�#��\\u0007=�AF#\\u0018\\u0011� �w\\u001eL`B4C0b��!\\u0010�\\u0018\\n��s\\u0010\\u0006a��\\u0010�\\u0018\\u0001���2FA��/��h�\\u001e�\\u0003�\\u0002VD��6����\\u0018�A��\\u001d1\\u0016�\\u0010� \\u001e1\\u001e�\\u000f�\\t=\\u0011\\u0013 \\u00011\\u0011\\u0012\\u0011{�\\u0003с�;$A\\u0012b2$#��ވNp!� ��\\u001b�Ș\\n��np#��>�i���\\u0015�è\\f�L�D̂,ľ��w\\u0016�A\x7F��0\\u0000q��\\u0003a b6d�~\\u0001\\u000f\\fB\\u001c$c\\u000e� �B.b\\u001e��~�|\\u0018�8\\u0018� \\u000e�q(\\fE\\u001c\\u0006�|?�p\\u0018�X\\u0000#\\u0010G�Hđ2��Q�\\u001fa4�F,�1�c`,�X�\\u001f�\\b�\\u0010��\\u0018q\\u001c�C�\\u0006�#��\\u0012�\\u0019\\\\a(�B)�\\u0004��8\\u0011�E�\\u0016�|��L�I0\\tq2LF,�r�\\n���\\u001e��X\\t��UP�X\\rՈSa��;�\\u00065�52�B-�t��8\\u0003f����P�X\'�,��X\\u000f��^�����Ѐ� c#4\\"6A\\u0013b34���90\\u0007q.�C�\'�|���\\u0000\\u0016�����\\u0010q\\u0011,F\\\\,�\\u0012X��\\u0002-�/�\\u0015Z\\u0011����Ka\\u0019�2\\u0019۠�w\\u0012���\\u0011��r�\\u0015�\\u0012q���`��\\u000bX\\r�\\u0011��\\u001a�\\u001b�F�\\u001b�&ě\\u0010?���f�[�\\u0016ĵ�\\u0016q\\u001d�G\\\\��\\u0019��\\u001b\\u00107�F�[�V�M�\\u0019q3��;\\u0001��x;lA�\\"�\\u001dp\\u0007�V���)�)�]�\\rq��w�݈����O�^؎�]���~��e�\\u0001;|\\u001f�\\u0003� �2\\u0010\\u001f��?�?|\\u001f���\\b�#�(�Ў�.�.���\\u0010v�n�=�\\u0018�c�8��\\u0017q/�\\u0007�\\u000f�!�\\u0003�\\u0007� �Ax\\u0002�\\t���\\u0010\\u001cB<\\f�\\u0011����OB\\u0007b\\u0007<�{\\u000f���ix\\u001a�\\u0019x\\u0016�Yx\\u000e�9�w�yx\\u001e�\\u0005x\\u0001�Ex\\u0011�%x\\u0019�ex��\\u000e�\\u0002�\\"�*�k�\\u001a�Qx\\u001d�ux��6�!�18��&��x\\u001c�#�\\u0005o���\\u001dx\\u0017�]\\u0019߃�\\u0010߇\\u000f|��\\u0003�\\u0010�C�\\b�#\\u0019?��\\u0011?�O|o§p\\u0002񄌟�爟��\\u0005|�;\\u0006\'�K�/�+į�kįe�\\u0006��\\u0001�·�������x\\nN!��Ӿ��\\f�A�\\u0001~D�\\u0011~B�\\t~F�\\u0019�(�\\u0002� ������o���#�\\u0006\x7F�\\u001f�\x7F\x9F�\x7F�9�sp��*��N�N�\\u0010%\\u0019}���wML�5�\\u0019X\\u001a\\"\\u0011x)��u\\u001aa\\u0018�~�vaM�¼\\u001cTk���b�\\u001d�\\u0010�3!�\\u0017j��NW\\n�ʹ�Lԉ�\\u0004�#/\x7F�Æ\\u0017�\\u0000\\u0018]8fl\\u0011��f|\\tL�xm\\u0019�7��w^\\u0012e�P�Ɏ\x7F[\\u000b��\\u0005H�\\u0015C\\u001a�\\u0018\\\\/�QS\\u000fA�;\\n��8Ԙ\\u0013P�yQ\\u000b-�y�\\u0013g��s��\\u0007 �N�K�b�\\u0002,=V.]�z�\\u00015UWi\\u001c\\u0002�\\u0017������I���p�Kځ=Fg\\u0018�&{ܓS:��h��\\u0011Æff���q�������\\u001c�\\u0012\\u0013z����clVK��Ȉ�А`�)�h��\\u001a�J\\u0014�\\n�c\\u0019\\u0002I�=,�dW��\\u0011i��J�\\u0003�K��l��g[;\\u0004]R(򲇢.�G_\\u0016��\\u001d\\u001f�\\u000e�����<Z�.\\u0018�U;�ډ�\\u001dh+�4\\u0012[\\n<�_5ݞ_�\\u001e�[U^�O��\\r���?:\\u0003��u�R�r��ժ�$إRcP�!,��E\\u0006\\u000f$r�\\u0019��w\\u0017\\u0003�69�=������kz�gM9\\u0006�yX\\u0013�.���u�pq\\u0016�c]!�?D�\\u0015��J�]km���\\u001d�Xw%u��a�\\u0001��;4U���k�s\\u0015H�.`��k�)\\u001f��U^cm�r\\u0019\\"1Ś_c]m��ȯ)G���SWL��ܒ\\u0015���� ��\\u001b\\u001d�C�Đ\\u0005\'#���a�V\\u001a]�z��}ۘ��sm\\u0014KKKÐ���v�\\u0010+˟��]\\ts&\'��\\u0014`#U�t���\\nJg�t��5�2�7�4�E�kp`*�]�ի���U\\u0015U9��s�=��\\r�\'��\\u001dD��\\u0006�\\u0002\\u00050��s��Jm~f\\u0017�-ɥ��+�\\"��ޝR\\u001eH����L+�`\\u0018V�n�����\\u0012;\\u0016ͤP�\\t�+3e᱕\\u0012|���S�|��n]�+��r��S��T\\u0004R\\u0014q�_�\\u0006\\u0007�\\u0007��^=�n\\u001d��|u�~_�\\u0014��`_���`�7�\\u001c[-,����\\u000e��l\\u001f|Ci�����E�S\\t\\u0018<�$;�f,�\\u0016vE\\u0001E\\n\\u0005K-w\\u0007��?�\\u00027�2\\u0014�جȨq%��ȧ\\u0012\\u001a.ư�N\\u0005\\t\\u00057\\u0013�8�6ʣ��n��\\u0006�6\\u001b��5�=0\\u0005#��cJ�q+L��\\r\\u001e�\\u0003ǣ��tt�\\u0004��9�]9ݏ�۱��d\\u0005\\u0016�.�w��\\r!�����$�_dW���M�%l$S�\\u000f1�,\\r�\\u001c8����:0��X�������h�K:\\"��Z\\rF�\\u0000t��\\u0005c&�X�WwK�?%�S*\\u0007(����Ձ�D���2�`+(�0�8M�:���?>�Kqa����ǻ�\\u0005A\\u0001)(F)G=���NV���!+�&�\\u001c�5Ժ��d7C����]��Wr�\\n��S\\u0019�J\\u0013i�J#���\\u0018\\u0011��\\u0007<\\u0000�r.\'\'����\\u0004�4�+�#�~Ɵf�7\\u0014/7��E�r?���t��0M��i�\\u000bhw=*�#xD���2��\\bMڍ)\\u0007q\\u0018E\\u0002{4DK\\"w�Sc����u����h�\\u0012\\u001e?�+�]hz܄�=\\u001a��dĆr��\'�\\u0006YYb��[��=�%�JkV��R\\u001d��2��P�Xb�\\u001bڭ\\u0011/E�6|Y�\\f��X<DVA/\\u0012\\u0005�H���|�A�$\\u000eRI,�cѫU��\\u000e6�\\u001e��\\u0003\\u000b�\\u0010H/\\r�W�\\n��,d<\\f%�`�\\u001a\x7F:��\\"+\x7F K0�\\u0018�80e\\u0011Y�+��,ĸ\\u0011�\\u000b\\u0002���<�D-d\\u001eƣ�>7p�C&�m6�\\u0006�ހ��x�\\u001dh�\\u001b��\\u0007�3\\u0003�3\\u0002��{m�^\\u0013�W��\\u0019-�Ie��)�bw�ų���1���}�Ɛ>HG�\\u0003tL\\u000e�\'��\\u000eR�GkH�\'1�~?\\u0019�}4a�G�6�,����z��\\u0010\\u0019��-��D\x7Fj\\u0002M�O�w��M���7�n��Bi�!\\"\\u0006x*�3��̈�!438Ј�_��߈\\u0002S9L�w\\u0013��y��|�u��믌\\u0016Tb��w�/��ɻ댖��z\\u0015�W�z\\u0019���z\\n�\\u0007��Z����-V�m[\\u0012,[�EZ~�\\u001clٱ9ܲis/˭��,\\u001b1��L6cq��dúp��u\\u000e��u6\\u000b�#��kש\\r��C�C�C��\\t\\u0002\\u0007\\f\\u0007\\u0018=ήlj���?\\u0018����=��-�\\u0012�Y�Y�z��\\f�<�}j�)����mf��\\u0004��=F�sO���vo��-�˓��/�r��\\r�y\\u001a;B\\u001b�=��7[z[���F���z��ҁדx�|�w��\\u001f&��dףF��Qbx��\\u0000�f�˲z�Ӳ��mY�\\u0016fY���a��ی�em}-mXM��m;�w�����M\\f�Z��\\\\���5.m\\t�\\\\�2�Ҋ�%��b�\\n[�[�-�Ao��\\u0004��(\\u00156KxX/\\u000b��,��^��d}/�.!Q\\u001f�S\\u0017\\u001b����6}\\u000f�.2*Z\\u001b\\u0016\\u001e�\\r\\u000e\\t�\\u0006��Z����hu\\u001aQ��(����x\\r�\\u0013\\u001a��U�x\\u0014�\\n�ö��\\u001e�a4��\\u001e�\\u0018�D�c�I��| D�\\u0013,�����\\u0012,�)X\\nݤ=�\\u0000P���P�\\n�r�ݎ\\u0002TQc�S\\u001d\\u0005�b�Ē]��T����J\\u001c��vn%�b��&L,�O�i���Q�!TJ��xcdw���\\u0011�^UPT��.mO��[�K��GcScc��\\u001f�]!����9����T��-ZS��\x7FG����H�ы�� V�\\u001d��\\\\t��YNo�[s�DǤ\x7F$��܅#l�\\u0003\\u0014fP\\u0001���҅��\\u0010�`�w�g2~�\\u0015��|����!\\u0004��/\\u00079�$�\x7F� 7�夕\\u0014�&�#ͨ?=�,K\\u0011�a�\\u001e\\u001e�\\u000b�\\u0007�\\u0012+\\t\':B��\\u0018Qs�#q$��P!�0N�g=+��*�Y�\\u0017~adn�\\u001a�����$z�\\u0012��\\u0011<��\\u0013�;l�\\u0007�I��P8��Ga��a\\u0017\\u001c�2/�3\\u001f�W�#\\u0011�\\u0004\\\\\\u001fV�\\r��\\u000ea&`�0�KV1#�s\\\\,(�\\\\&�Lc\\u000f��DA�q5;\\b��\\u0007l;��mp�Mf��<\\u0018\\u0001�I\\u001f�a�c{�\\u0016�\\u0018sߕ�!�A�,\\u0001;�c�����r��Jr ����|��\\u001b�;i\'��H˥��_:.ȁ�[�)\\u0014�I��R�S�\\u0007+`��e���C�I��z�\\"q\\u0004�$\\nǀ��8\\u0006��q�u�<ZF\\"�\\u0004��\\u0011y�D�!�#g�`y\x7F�W�>P�G8\\u0001_�3\\u001a��#�����\\u001b`�\\u0011�\\u0004\\u0005�6P�y���^��>~M�\\u0014��h3�!\\u0010,�W+\\u000f��\\u001dZ�v\\b\\u0003;�\\u00178��,?��+�,ð\\u0004^׳嬗Ń{\\u001d�\\u0006e��E�)��Gdʜe��xA��\\u0019����\\"�]>9M�����Ka��Ì�\\u0017�\\u0003xJ�b�`\\u000b��ߓ4�\\u00140\\u0005����d����3�\\n���0-�\\u0016�N\\t$R�S�Z��=\\u001eb8K�qCv6�QFl��\\u0010�a\\u000bV(�\\n&�\\u001c\\u0014\\u001a\\u0012\\u0012��Vt\\u001c8�A�Y�ݿ`����\\n����G$\\u0012Ϗ>�\\u001ev`�\\\\��\\u000fI�-���\\u0010J��H��.z�P�{Ly�B��TΔ��r���^�׬\\u000b\\u0002.\\u0012/�q�\\u000e�\\u001bj��\\u0012z\\f�Җ����\\u001e�և�\\u0019\\u001f�3�\\u0016\\u0012�n>�!�(��oం���ǐ�\\u001d\\u0007��җR�g�C:�.\\"!\\u000fm\'1s\\u0017\\u001d\\u0018\\u0016���6\\u001d�ʄp\'�\\u001a#��̞*�\\u001a\\u0019A\\u0010�aB�1QH4�fF��\\u0004�ڣ\\u001bf��L�K�1�1�\\u0012�4�:�\\\\]���7�bf1߬�/6�\\u001bu\\u000b\\f+\\r6�P\\u0000��\\u0018N\x7FBET�J\\u0003`4|�Uӽ\\u0011�Bۮ\\u0011���h(i�eg��\\f�C�\\fx�\\u0001���?�\\u0014W\\u0019vQ\\u0019g����qq\\u0019<�f�By�d�ԡ~[���#�ҝ3I��-�\\f��ng���#�J&�y���;�&\\u0013�����\\u0006�o\\u0016�`k�x��(����\\u0018����1N~4������4�\\u0013哭��s��X�D\\u0018��\\u001e8[�8�\\u001f�U0��\\u0012\\u0018r\\u001d&�*�[��\\fE��#����(V�)�(�(f+U��\\u0003�ދ�\\u0006�H8��_� \\n�\'\\f��.�D^\\u0005<��~ߧ� �!��!�^���ECxg��]�t8ʂB���Mo(�YY�\x7F\\u0010G�H~1,湲RR������!�Ёُe�#E\\u0006��Ge�$65��!5N�|o����\'\\u0007\\u001d���d�8\x7F�|\\u001d\\u0013��\\u001d��i�/�Y�\\u0019p��\\u0003��\\u0019�\\u0011��\x7F7��=�\\u0019\'j2�\\u0003\\u0011��h;\\u001b�%\\nN�\\u0019m��2��xUi�5���\\u0002Q�4e��M-&�d�X��ɮ��do2��\\u001c�\\u0016L���i�6:mr\\u001ak]���\\u0007gV��TȦ\\u0002-\\u0003���A\\u001c\\u000e>&�g<��\'(#=֝\\u001aB��ю�\\u001d\\u001fo��i�\\b6�4w*�}z��H����|��uuu���\\nb�9i�\'�.1)j\\\\zF�1�\\u0006�\\u001b6���[�\\r^�7�82!sj���)\\u0015\\u0015$��.b�V93�hr��Ma9Vk��_֡�7\\u001cJ�p����\\t��\\bO2\\u0004��4��T\\f#i�A4��^�A�\\"����9�|�\\"d����S�\\u0017�`\\u0001\\u0016�o�X<�B\\u000b\\u001bڢ|�\\u0007��2�YTV��٧�P�\\u0019������r�!A|\\u001f�kv��G�\\u0001G��I�ww��D�%\x84�wI�3��-\\\\TQ��u#�\\u0014��7�}%9}�c\\u00032\'IO���X����׆���DG\\u0013��~A*�0�\\u0013!�u)<�r�\\u0017��v\\u0005\\u001e�_˰��D�F��\\u0010�!p��h\\u0015b\\u000by\\\\c��3Ո���tȤ\\u0006Q�C�Muw��~9�\\n��9���s!��?&��|x����ز\\b9\\u001e3�օ\\u000eq9��\\\\I�\\n��e��i\\u0014�\\u0019\\u0000j�z��ax䎊����t��(�]��\\u000bM~�Y�,�^Z�9�]��҉�6l���g�\\u0017(��p�\\u0001���U��w�\\u0013��j�\\u001dJG�=�$�8j*_���/V.\\b�\\u001d��Y���\\u0019;%&K4d��\\"��fk�-ZN�5�\\u0013�����i\\u001f����jmK\\u0000�=�$b1�\\bV�)Xž8�oe�)�(�FJ1J�,�4���� �� [Q�\\u0001\\u001d��$\\u0018��3h��/���ۥ6i,�M��\\u0013ս����}���z\x7FN�04T $-Dz�yt\\\\ϑd+��\\u0013Ƀi��{�GFZ{�\\u001f����ߥ�\\u0018�Ēp��B\\\\���G?�\\u0013#r�\\u0015��]O\\u0004�ݪ\\u0016�g�\\u0006���VcѺ�\\u001e�W�����M5t�M\\u0005ggjvg�<�n�\\u001diC�d�8���Y���Y\\"�O\\u0011A��|v`�\\u0015I�\\u001d��b4�p2�\\u0011D\\rEcpW\\u0018\'\\u0002�;���/�I\\u0013F2�B\\u001dS-,d�tq�\\u000eI\\u0014�V\\u0006U�J��.ͨV�*�W\\u0011��<Z\\"ˌ\\u0001�\\t��\\u0016��\\u0016^\\u0016��,*2e�\\u0018Qh��\\\\a#\\r�wr\\u001d\\u0004��Ё*�j�rN\\u001d�N\\u0014��tu�8��\\u0013�s�*�13�l\\u0015.�ML�Z��*�f�D娉 Z��n�F��R\\u0000���Ũ�jƃ��Q��.�4~�\\u0004�6\\u0012�E2mee~�P\\u001e�\\bt �Tm;(����I��l6��ŝນ$%J�\\u0013�V�ʘ��΃Lq�\\u0014�\\u001f����9�k�������1#�֢�R\\u000e^��F��LV��1�W�����x�(V��?v��\\u000eŻX�\\u0006�=\\u0000*�\\u001b83\\rd\\u0014����Ҿ���<tf�#�\\u000e5\\u000b�F�W\\u001b�('... 702140 more characters
}
try to set in your response the correct mimetype: application/pdf
instead of using
response ={
statusCode:200,
body: doc
}
use this one:
response ={
statusCode:200,
headers: {"content-type": "application/pdf"},
body: doc
}
This should give your browser the information, of the correct content type.
Edit:
if this won't work, you probably need to follow this instructions: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings.html

Authenticating FTX API SHA256 HMAC with Node

I am lost with using HMAC SHA256 for api authentication. This is my first time using it and I'm not sure what I am missing although I suspect it has to do with the timestamp. Can someone please help me identify what it is I am missing?
Everytime I try and make an API call I get a response stating
data: { success: false, error: 'Not logged in: Invalid signature' }
Here are the requirements for making the API call including the HMAC SHA256.
Here is the code I am using currently:
const axios = require('axios');
var forge = require('node-forge');
require('dotenv').config()
// get timestamp
var time = new Date().getTime();
// generate and return hash
function generateHash(plainText,secretKey)
{
var hmac = forge.hmac.create();
hmac.start('sha256', secretKey);
hmac.update(plainText);
var hashText = hmac.digest().toHex();
return hashText
}
// set axios config
var config = {
url:"https://ftx.us/api/wallet/all_balances",
method:"GET",
headers :{
"FTXUS-KEY":process.env.FTX_API_KEY,
"FTXUS-TS":time,
"FTXUS-SIGN":generateHash(`${new Date()}${"GET"}${"/wallet/all_balances"}`,process.env.FTX_API_SECRET)
}
}
axios(config)
.then(response => {
console.log(response.data)
}).catch(function (error) {
console.log(error);
})
I had to go through the same issue, so here goes my code.
import * as crypto from "crypto";
import fetch from "node-fetch";
// a function to call FTX (US)
async function callFtxAPIAsync(secrets, method, requestPath, body) {
const timestamp = Date.now();
const signaturePayload = timestamp + method.toUpperCase() + "/api" + requestPath + (method.toUpperCase() == "POST" ? JSON.stringify(body) : "");
const signature = crypto.createHmac('sha256', secrets.secret)
.update(signaturePayload)
.digest('hex');
const response = await fetch("https://ftx.us/api" + requestPath, {
method: method,
body: body != null ? JSON.stringify(body) : "",
headers: {
'FTXUS-KEY': secrets.key,
'FTXUS-TS': timestamp.toString(),
'FTXUS-SIGN': signature,
"Content-Type": "application/json",
"Accepts": "application/json"
}
});
return await response.json();
}
then call a post endpoint as for example:
let resultQuote = await callFtxAPIAsync(secrets, "post", "/otc/quotes",
{
"fromCoin": "USD",
"toCoin": "ETH",
"size": usd
});
or a get one:
let resultQuote = await callFtxAPIAsync(secrets, "get", "/otc/quotes/1234");
I hope it helps 😄
You need to add the full URL path, except the domain, in your case /api is missing. Try this:
"FTXUS-SIGN":generateHash(`${new Date()}${"GET"}${"/api/wallet/all_balances"}`,process.env.FTX_API_SECRET)

Nodejs, express http request - response not unzipping

I am trying to write a function that creates an HTTPS request.
This is all part of an expressjs project with Typescript.
I can get the HTTPS request working and getting a response - but the response is encoded with GZIP. I am trying my best to follow the documentation. But no luck, the response stays zipped.
This is my code
private getData = (host, pathname): Promise<string> => {
return new Promise((resolve, reject) => {
const options = {
hostname: host,
path: pathname,
gzip: true,
method: 'GET',
headers: {'x-apikey': 'XXXX'}
}
const req = https.request(options, (res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
console.log('error!')
return reject(new Error('statusCode=' + res.statusCode));
}
let body = '';
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
try {
console.log('res.headers', res.headers)
console.log('res.headers', body)
body = JSON.parse.toString();
resolve(body);
} catch (e) {
reject(e);
}
resolve(body);
});
req.on('error', (e) => {
reject(e.message);
});
// send the request
});
req.end();
});
}
The console log statement shows this
So obviously the JSONparsing is failing. What am I missing?
Thanks heaps for the help
https.request() does not natively support gzip compression. So, you will have to either add support for it yourself as shown here or use an https request library such as got() that already supports gzip (and also already supports promises too).
import got from 'got';
private getData = (host, pathname): Promise<string> => {
const options = {
method: 'GET',
headers: {'x-apikey': 'XXXX'}
}
return got(`https://${host}${pathname}`, options).json();
}
FYI, it's not clear in your question what type of response you are expecting. You attempt to use:
body = JSON.parse.toString();
which doesn't make any sense because JSON.parse.toString() is trying to get string version of the JSON.parse function without actually even calling that function - very odd. Perhaps you meant JSON.parse(body)? But, your typescript makes it look like you're expecting a promise that resolves to a string so that wouldn't usually be the result of JSON parsing.
If you are expecting a gzipped JSON response, then you would use the:
return got(`https://${host}${pathname}`, options).json();
I show above. If you are expecting just a string, not JSON, then you would change that line to:
return got(`https://${host}${pathname}`, options).text();

Make a HTTP Post call within Azure Functions using Nodejs

I am trying to make a HTTP Post call from within Azure Functions using nodejs. The payload which needs to be passed is in JSON with two properties title and description. For some reason, the below code doesn't work and I don't get any errors in the log too. The POST operation works in a Postman rest client. Can someone point me in the right direction? Thanks
var http = require('https');
module.exports = function (context, req) {
var body = {
"title": "Sunday",
"description": "Last day of the week"
}
const options = {
hostname: 'capservice-xxxxxxxx.ondemand.com',
port: 443,
path: '/incident/SafetyIncidents',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': body.length
}
}
var response = '';
const request = http.request(options, (res) => {
context.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
response += d;
})
res.on('end', (d) => {
context.res = {
body: response
}
context.done();
})
})
request.on('error', (error) => {
context.log.error(error)
context.done();
})
request.write(body);
request.end();
};
Had a bit more chance to investigate the issue. I've actually tested it on Azure Functions now - and got it to work.
Your body variable is incorrectly typed:
// This assumes that the body type is JSON.
var body = {
"title": "Sunday",
"description": "Last day of the week"
}
See the reference here: https://nodejs.dev/learn/make-an-http-post-request-using-nodejs
const https = require('https')
// See the JSON.stringify
const data = JSON.stringify({
todo: 'Buy the milk'
})
When I try to execute your function above as it is (with changing the URL) - I'm receiving a parameter error as below
FailureException: TypeError [ERR_INVALID_ARG_TYPE]: The first argument
must be of type string or an instance of Buffer. Received an instance
of ObjectStack
Adding the JSON.stringify to the body object solved the problem for me.

Using Q promises in HTTP requests with NodeJs

I'm trying to make a chain of promises functions which use HTTP requests in NodeJS with Kraken framework.
My code could work in 90% of cases, but if the distant requested server takes time to respond, the code will return an error with undefined values. So I think Q is a good solution to prevent that.
Here's the situation :
We access to a URL with a "code" parameter -> the route controller takes this param to use it in a HTTP POST request -> the response (a token) is stored in a variable and used in an other HTTP GET request -> the response (multiple JSON objects) is stored in variable too -> all variables are stored in a MongoDB.
If functions are not used in this order, of course it fails.
var Q = require('q');
module.exports = function (router) {
router.get('/', function (req, res) {
var codein = req.param('code');
if(codein){
console.log('Provided code: ' + codein+'\n');
getAccessToken(codein).then(function(token){
console.log('Provided AccessToken: ' + token + '\n');
getUsername(token).then(function(userdata){
console.log('Provided Username: ' + JSON.parse(userdata).username + '\n');
storeData(userdata).then(function(msg){
console.log(msg);
res.redirect('/dashboard/' + JSON.parse(userdata).username);
});
});
});
}
else{
console.log('Access Denied, redirecting...');
res.redirect('/');
}
});
};
This method works, but actually didn't resolve the problem, because sometimes variable are undefined again. I think it's my request functions which aren't well made...
Here's an example of the first function with POST request :
var getAccessToken = function(cod){
var def = Q.defer();
var data = querystring.stringify({
client_id:"1234567890",
client_secret:"******",
grant_type:"authorization_code",
redirect_uri:"http://localhost:8000/r/callback",
code:cod
});
var options = {
host: 'domain.server.com',
port: 443,
path: '/api/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(data)
}
};
var response = "";
var req = https.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
response += chunk;
});
res.on('end', function(){
var json = JSON.parse(response);
var acto = json.access_token;
def.resolve(acto);
});
});
req.write(data);
req.end();
return def.promise;
};
In this case the acto variable can be undefined... So am I using Q in a wrong way ?
EDIT
To understand my problem, let me show you what can I have in my output console (really rare but happens) :
Provided code: 12345678910
Provided Username: user543210
Instead of :
Provided code: 12345678910
Provided AccessToken: 9876543210
Provided Username: user
I think you need to account for 2 scenarios
Where the Twitch API takes time to respond.
The Twitch response cannot be parsed
The code
res.on('end', function(){
var json = JSON.parse(response);
var acto = json.access_token;
def.resolve(acto);
});
Should be modified as:
try {
var json = JSON.parse(response);
var acto = json.access_token;
//check if acto is undefined
if (acto === undefined) {
def.reject('Some error message');
} else {
def.resolve(acto);
}
} catch (error) {
//since the JSON could not be parse
def.reject(error);
}

Resources