Unable to use "request" library with headers - node.js

Using Chrome dev tools I can see all the requests made. I want to replicate one of them using a script. The request is replicable as replaying it from dev tools works. I'm using this code:
let request = require("request");
request.put("<hidden>", {
"headers": {
":authority": "<hidden>",
":method": "PUT",
":path": "/api/<hidden>",
":scheme": "https",
"accept": "*/*",
"accept-encoding": "gzip, deflate, br",
"accept-language": "en-US",
"authorization": "<hidden>",
"content-length": "0",
// and more
}
}, (err, response, body) => {
console.log(err);
console.log(response.statusCode);
console.log(body);
});
The console says:
TypeError [ERR_INVALID_HTTP_TOKEN]: Header name must be a valid HTTP token [":authority"]
at ClientRequest.setHeader (_http_outgoing.js:487:3)
at new ClientRequest (_http_client.js:221:14)
at Object.request (https.js:309:10)
at Object.request (C:\Users\Admin\AppData\Roaming\npm\node_modules\puppeteer-core\node_modules\agent-base\patch-core.js:25:22)
at Request.start (C:\Users\Admin\AppData\Roaming\npm\node_modules\request\request.js:751:32)
at Request.end (C:\Users\Admin\AppData\Roaming\npm\node_modules\request\request.js:1505:10)
at end (C:\Users\Admin\AppData\Roaming\npm\node_modules\request\request.js:564:14)
at Immediate._onImmediate (C:\Users\Admin\AppData\Roaming\npm\node_modules\request\request.js:578:7)
at processImmediate (internal/timers.js:439:21) {
code: 'ERR_INVALID_HTTP_TOKEN'
}
I tried not using .put(), or specifying method and body properties. Same results.

Headers that show with a leading colon are "pseudo-headers". You don't actually send them yourself with the request() library as they are an illegal http 1.1 header format.
You can read about them here: Purpose of pseudo colon-header fields.
You should be able to remove all the pseudo-headers and just make sure that the information in them is properly specified elsewhere in your request (url, method, etc...) which they would normally already be.

Related

why I can't make search request to my Elastic Enterprise Search app using axios?

so I want to make search request to my elastic enterprise search app using guide from the documentation in here , I don't want to use elastic node JS client, but I want to make http request using axios.
here is the code I use
const url = "https://XXXXXXX38ce49e5aff1aa238e6f9195.ent-search.asia-southeast1.gcp.elastic-cloud.com/api/as/v1/engines/events/search"
const headers = {"Authorization": "Bearer search-qpz4bu5o7ubb8j31r15juyrh"}
const jsonData = {
query: "hello there"
}
try {
const {data} = await axios.post(url,jsonData,headers)
response.status(200).send(data)
} catch (error) {
console.log(error)
response.status(500).send(error)
}
but I always get 401 error like this:
{
"message": "Request failed with status code 401",
"name": "Error",
"stack": "Error: Request failed with status code 401\n at createError (/Users/xxx/Documents/elastic_jxxx/firebase_emulator/functions/node_modules/axios/lib/core/createError.js:16:15)\n at settle (/Users/xxxx/Documents/elastic_jakarta_kumpul_muslim/firebase_emulator/functions/node_modules/axios/lib/core/settle.js:17:12)\n at IncomingMessage.handleStreamEnd (/Users/xxxxx/Documents/elastic_xxxxx/firebase_emulator/functions/node_modules/axios/lib/adapters/http.js:244:11)\n at IncomingMessage.emit (events.js:203:15)\n at endReadableNT (_stream_readable.js:1145:12)\n at process._tickCallback (internal/process/next_tick.js:63:19)",
"config": {
"url": "https://XXXXXXXa638ce49e5aff1aa238e6f9195.ent-search.asia-southeast1.gcp.elastic-cloud.com/api/as/v1/engines/events/search",
"method": "post",
"data": "{\"query\":\"hello there\"}",
"headers": {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json;charset=utf-8",
"User-Agent": "axios/0.20.0",
"Content-Length": 28
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"Authorization": "Bearer search-qpz4bu5o7ubb8j31r15juyrh"
}
}
I believe I have put the correct search key, I can get the sucessful response using the same baseURL and search key in postman like this
what went wrong in here ?
The headers need to be passed as a named object in the config part.
So try it like this:
const {data} = await axios.post(url, jsonData, { headers: headers })
or even more concisely:
const {data} = await axios.post(url, jsonData, { headers })
Tip: Postman is capable of pre-constructing axios requests when you click on Code. So next time you're not sure, Postman is here to help:

Node JS send empty JSON body

I have the code below which is supposed to send a POST request but with an empty JSON body:
request.post({
url: url,
headers: {
"data_digest": 'muZ7EcapQZVb77RF',
"partner_code": "ebfebc241db9b9c1a",
"msg_type": "GET_BASEDATA_TRANSPORT",
"msg_id": '1590464383047',
"Accept-Language": "zh-cn"
},
json: true,
body: {}
}, function(error, response, body) {
console.log(body);
});
However this keeps returning
'System Exception:\r\ntype org.springframework.web.HttpMediaTypeNotAcceptableException\r\nmessage:Could not find acceptable representation'
But using Postman I'm able to correctly send POST request with the exact same headers but just an empty {} in the Body parameter with Raw format.
How can I send a POST request with an empty JSON body in Node JS?
Your way of sending the body is fine. If you'd look at the actual request sent (for example using Fiddler or Wireshark) you'd see the body is sent correctly. The problem is something else - instead you'd see that the headers are not the exact same.
Using json (either with json: true and body, or as you do it, with json as object) also automatically sets the Accept header to application/json and attempts to parse the response as JSON.
It seems that this server chiguotest.ytoglobal.com has a bug, where it returns JSON but does not handle the Accept header correctly (I tested it and it seems the server "thinks" it is returning text/plain). So request is (correctly) telling the server "I expect you to return JSON", but the server says "What, JSON? No I don't know how to return JSON, only text, sorry.". Yet, it in fact does return JSON.
You can circumvent this server bug by explicitely sending an Accept: */* header:
request.post({
url: url,
headers: {
"data_digest": 'muZ7EcapQZV',
"partner_code": "ebfebc241db9b9c",
"msg_type": "GET_BASEDATA_TRANSPORT",
"msg_id": '1590464383047',
"Accept-Language": "zh-cn",
"Accept": "*/*"
},
json: true,
body: {}
}, function(error, response, body) {
console.log(body);
});
My output:
{
"data": {
"productKinds": [
{
"productCnname": "(美国)测试用-不拉G单号",
"productCode": "1",
"productEnname": "1",
"productServerhawbcodeNeed": "Y"
},
{
"productCnname": "散客可见产品",
"productCode": "111",
"productEnname": "内部产品",
"productServerhawbcodeNeed": "N"
},
... many more entries ...
]
},
"errorCode": "SUCCESS",
"errorMsg": "成功",
"status": true
}

Script from https://account-d.docusign.com/error?aspxerrorpath=/oauth/token was blocked due to mime type mismatch

I am trying to obtain the Access Token by passing authcode by calling rest api but my response was blocked saying mime type mismatch. PFB sample code
$.ajax({
async: true, // Async by default is set to “true” load the script asynchronously
dataType: 'jsonp',
crossDomain: true,
redirect_uri: 'https://hclo365.sharepoint.com/sites/wf13test',
data: 'grant_type=authorization_code&code=eyJ0eXAiOiJNVCIsImFsZyI6IlJTMjU2Iiwia2lkIjoiNjgxODVmZjEtNGU1MS00Y2U5LWFmMWMtNjg5ODEyMjAzMzE3In0%2EAQkAAAABAAYABwCAGYGDcLfWSAgAgKUHy3C31kgCAONnoYIaQgFOsTImy5_ryv0VAAEAAAAYAAEAAAAdAAAADQAkAAAAMzRkYTY1NDktMTdjMC00MTM3LWE3YWEtYWJkYWMzNjQ0YWMzNwCWbGY1cO_JQKSrZRKWhxjbMACAZ4tNZ7fWSA%2Eaz__M8ULm--8DgmUspzcA1wa7soxB0jQgnKhIwKhRT4jDsmsmIa755xPK7sD1vKmeMM4LDISN1XignVCii1IecpEWO6PWR8gq6UToJG6DnKcPurKWXEwZblsyxf2kOXR1RtDQoev5_VxkqLKTT9rHCFB01eZzTir8SVMs5BPOWdCCufMok-lVyJoq5VRL2YoPB3iOhz8MZAVlElx0srIJJWUuHiXRImmU13__3qtRf82Kxattt_6cN8IcW9rjZDYB0dfcqIKon_Q27Fp8KYU4LEpYHVunKEli60dzWliTFX34KRGJYVpYqK-Zd6OyHuqculMPE6mctVlQbcG1DD3gQ',
url: "https://account-d.docusign.com/oauth/token", // URL to fetch data from sharepoint list
method: "POST", //Specifies the operation to fetch the list item
headers: {
Authorization : "Basic MzRkYTY1NDktMTdjMC00MTM3LWE3YWEtYWJkYWMzNjQ0YWMzOjgzNmQxNmZiLWU1MDctNDM2Ny04Y2ZlLTFiODkzOGU2MTE5Yw==",
"Access-Control-Allow-Origin": '*',
"Access-Control-Allow-Headers": 'application/json',
"accept": "application/json;odata=verbose", //It defines the Data format
"content-type": "application/x-www-form-urlencoded" //It defines the content type as JSON
},
success: function(data) {
console.log('works');
},
error: function(error) {
console.log(JSON.stringify(error));
}
})
Looking for the possible solution for this to capture the access token.
I do not think you can call DS API from AJAX calls, you will be getting CORS issue. DS Dev Blog1, DS Dev Blog2 and DS Dev Blog3 explain how you can achieve Single Page Applications with DocuSign.

How do a pass commands through the OctoPrint Rest API?

What I'm trying to do is use the OctoPrint Rest API. I keep running into an error though when I'm trying to do POST requests that require a command. Here's an example of that in the docs.
POST /api/connection HTTP/1.1
Host: example.com
Content-Type: application/json
X-Api-Key: abcdef...
{
"command": "connect",
"port": "/dev/ttyACM0",
"baudrate": 115200,
"printerProfile": "my_printer_profile",
"save": true,
"autoconnect": true
}
What I'm most confused about is where I include the command or the port values. Here's what I'm currently doing.
var self = this;
request({
url: OCTOIP + "/api/connection",
method: "POST",
"content-type": "application/json",
headers: {
"X-Api-Key": KEY
},
body: JSON.stringify({"command": "connect"})
}, function(error, response, body) {
//var info = JSON.parse(body);
if (error) {
console.log(error);
self.tell("Could Not Connect");
}
else {
console.log(body);
self.tell("Connected to printer.");
}
});
What happens is I keep getting this error message.
Expected content-type JSON
I've tried changing content-type to just json, I've tried getting rid of the JSON.stringify and just putting it as {"command": "connect"}. Or even dropping the curly brackets altogether. Another thing I tried was using form and instead of the body. None of those have worked. What am I doing wrong here?
Fixed the issue. It turns out it wasn't working because I didn't put the content-type in the header.

Sending large xml as body in request module in nodejs

I have a very large xml which gets generated using wsjs node module. it looks like
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:diag="http://diagnostic.ws.fcrewards.test.com/" xmlns:ws="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><soapenv:Header><ws:Action>http://diagnostic.ws.fcrewards.test.com/doEcho</ws:Action><ws:To>https://ws.mastercard.com/mtf/MRS/DiagnosticService</ws:To><ws:MessageID>35b479f1-5a54-e9a4-5551-0f15507f54b8</ws:MessageID><ws:ReplyTo><ws:Address>http://www.w3.org/2005/08/addressing/role/anonymous</ws:Address></ws:ReplyTo><o:Security><u:Timestamp wsu:Id="_0" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><u:Created>2017-02-24T17:13:13Z</u:Created><u:Expires>2017-02-24T17:18:13Z</u:Expires></u:Timestamp><o:BinarySecurityToken ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" u:Id="sec_0">MIID1zCCAr+gAwIBAgIRAIVAIPeDa+CgeYorExNgwDQYJKoZIhvcNAQELBQAwgYUxCzAJBgNVBAYTAkJFMRwwGgYDVQQKExNNYXN0ZUNhcmQgV29ybGR3aWRlMSQwIgYDVQQLExtHbG9iYWwgSW5mb3JtYXRpb24gU2VjdXJpdHkxMjAwBgNVBAjdjdjjdjdjjdjjdQgUFJEIE1lc3NhZ2VzIFNpssssssssssssssssssssssssIxNjIxMzcwN1owZjEbMBkGA1UEAxMSbXRmLkNIUy5wYXlGb3J3jdjjdjdjdjjdjjndkwlklwlwlwww25pbmcgU1cxDjAMBgNVBAsTBUNIUyAxMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM675qti1N/aMP+YsPe9UIaJasISYzIpEoysKhClmWfBTqJTrcw0UWnraSOGqdPvEpgcLdW2BwnZ+T2gmcLa/BY69hW+CYm0pR0px9MPNuP77YcJCS5d6ffuHvTlkVpBq2hWVhOck0X0uhu+m2I6G8Dshi8yiBJohs+jpuf63OxVtBTemFNM5pVDdB5z7sYhkrdcNzlSoPTKNcTFfZgnj0G6iwkb4XK1mSlXbQL8jYEPPZWDdxPFl1SrSnwUoyl3r84SZrV13JstZ4YrolAm8mmKB7pU+bJ46+zpeYDRDo/YH4cxSpkyPUuwB27PtLk1J/9FgBNLfY0XQnlk/b3Mm3MCAwEAAaNgMF4wHwYDVR0jBBgwFoAU66ASd4JT9FhYrwHp4f9kBT5H2aowDAYDVR0TBAUwAwIBADAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFJ1obzmA1M2PIL8GumtHSIdwUrZMMA0GCSqGSIb3DQEBCwUAA4IBAQASqfFjdTt74OHwmEJVlO3pYnnHcxvDU0v7+2xTTMpWSAKmfDGf5j71UDsa6E/ymclcz/mdbsHSvyYii8TsrYK8Nyq6o2nTAQ0mhRhSpip7kjv5eQ0PtJZhl0Je7W9b3GIS1M5IbNN7xusKNHaJSg7ZIf/gUwWuBOq1CxABE0xRGY5b5e6giglP2iJwgeOHukmeGiLck3HGqZjei+T/Fnvsyy7hQ6qzGTDZg6B6yd1ojMZddmjDV8QsQfUQWM0//rvORZup98VP7I9LmrDBQuu7cPPy0Vg8VRWZC9wrM82e6IHl1uMovU12PCth1vAcSyTjuorNn5NoQg8FIoLCdgLk</o:BinarySecurityToken><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><Reference URI="#_0"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><DigestValue>qNgtbxFDtGr1QCRG4ZnGSzfWqQ+GZJkuQAHgTxcI4B8=</DigestValue></Reference></SignedInfo><SignatureValue>ZqHJTwD91tcddddddddd3uZkuChVE0BHEx55YF3kGNw1D55VbunmbNZkmxxkuBvyAMjns/DJ8/duThXhlAmyPLYhRgj4djz8smJbksago1Tb+DFT8RQ4tOVPD2TPSaC5wrwA9g9zCCpPDHHv5FmZ4TIxwkPjG37MBqOIgUF8cUkL9kXU0sIJrUQddddddddddddddddddddddddddddddddddddddddddddddddddddddwsRtcjKDksvWpMBj0oSysWi+8/ce2HnO4nOuhrvX66BDOAyPL+avL2+JNTlA==</SignatureValue><KeyInfo><o:SecurityTokenReference><o:Reference URI="#sec_0" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/></o:SecurityTokenReference></KeyInfo></Signature></o:Security></soapenv:Header><soapenv:Body><diag:doEcho>Cieran</diag:doEcho></soapenv:Body></soapenv:Envelope>
when I send this request using request module of node.js
request.post({
url: ctx.url,
body: ctx.request,
headers: {
"SOAPAction": ctx.action,
"Content-Type": ctx.contentType,
"ContentLength": Buffer.byteLength(ctx.request),
"MIME-Version": "1.0",
"Connection": "Keep-Alive",
"AcceptEncoding": "gzip"
},
encoding: null,
rejectUnauthorized: true,
agentOptions: ctx.agentOptions
},
function(error, response, body) {
ctx.response = body
if (response) {
ctx.resp_headers = response.headers
ctx.resp_contentType = response.headers["content-type"]
}
if (error) ctx.error = error
else ctx.statusCode = response.statusCode
callback(ctx)
})
ctx.request has the whole xml in it as 1 big string
I always get Authorization failed error because endpoint is out rightly rejecting my request.
But if I take the xml and put it in SOAPUI and do format xml then I get the right result.
So I concluded that since i'm sending the body as 1 big xml the endpoint doesn't like my request.
What's the workaround for this?
Is there any other node module available which can format the xml or break it up in small strings?

Resources