5

I am trying to make a POST request to a knowledgebase. I can get the correct response from the request maybe 5-10% of the time. All the other times I get the error in the title back from the server:

No argument passed{“Error”:{“Code”:“BadArgument”,“Message”:“Request body Is Null or Empty.”}}  

I have a feeling this is caused by Node.js being async and my variable is still undefined when the request goes through. Although, how can it when req.write() includes the variable? Maybe I can insert a delay to insure the variable is defined before the request is sent?

var https = require('https');

var resData = "";

var options = {
    host: "westus.api.cognitive.microsoft.com",
    port: 443,
    path: "/qnamaker/v2.0/knowledgebases/<kb-key>/generateAnswer",
    method : 'POST',
    headers: {
        'Content-Type': 'application/json',
        "Ocp-Apim-Subscription-Key":"<sub-key>",
    },
};

bot.dialog('qnaReq', function (session, args) {
    //call QnA Bot and ask that bot the question
var req = https.request(options, function(res) {

    res.on('data', function (chunk) {
        resData += chunk;
    });

    res.on('error', function(e) {
    console.log('problem with request: ' + e.message);
    });

    res.on('end', function() {
        if (resData.length != 75) { //75 is the length of the error I get almost every time. This line prevents the application from crashing since I am trying to access values that won't be there.
        var accessibleData = JSON.parse(resData);
        session.send(accessibleData["answers"][0]["answer"]);
        } else {
            session.send("No argument passed" + resData);
        }
        resData = "";
    });
});

    var postData = {question: session.message.text};
    console.log(postData); //postData is defined

    req.write(JSON.stringify(postData));
    req.end();

}).triggerAction({
    matches: 'IT Help'
});

console results

enter image description here

Brennan Casey
  • 887
  • 2
  • 7
  • 17
  • Are you sure that your session is not null? Can you console.log your `postData`to check it. Your code seem pretty straightforward, can't find what could go wrong. – Sigma Jul 13 '17 at 13:39
  • Yeah, console.log(postData) works perfectly. I'm not exactly sure why I can query my results fine then try it again and it doesnt work the next 15 times I try it – Brennan Casey Jul 13 '17 at 13:54
  • Is it possible that the API limits the requests rate? Can your reproduce this behaviour with postman or another client? – Sigma Jul 13 '17 at 14:06
  • Have you tried with the `top` field in your postData. It seems to be optional, but who knows... { "question": "is qna maker free?", "top": 3 } https://westus.dev.cognitive.microsoft.com/docs/services/58994a073d9e04097c7ba6fe/operations/58994a073d9e041ad42d9ba9 – Sigma Jul 13 '17 at 14:09
  • Using hurl.it always gives me a correct response. I haven't used postman before but I can look into it. – Brennan Casey Jul 13 '17 at 14:10
  • The api does have a limit to the request rate but I have reached it resulting in a different error. The top field is defaulted to 1 but i tried it anyway with the same results – Brennan Casey Jul 13 '17 at 14:13
  • Try to declare your `options` object after the line `bot.dialog('qnaReq',function (session, args) {` Maybe the content length screwed your function. It seems to work when you the API twice in a row with the same body. – Sigma Jul 13 '17 at 14:19
  • I can called the api sometimes 20 times in a row with the same body and it works 1 time so it has nothing to do with 2 in a row. When I set the body ahead of time: var postData = {question: "what is the cloud"}; same error- No argument passed – Brennan Casey Jul 13 '17 at 14:29
  • Not sure it can works just ahead of `var postData`. But maybe it will between `bot.dialog('qnaReq', function (session, args) {` and `var req = https.request(options, function(res) {` Where your code is running? – Sigma Jul 13 '17 at 14:39
  • It still has the inconsistency but I have a slight feeling it works more often this way. Is there a way to create a delay between req.write() and when https.request(..) executes? I think that could solve the problem. – Brennan Casey Jul 13 '17 at 14:52
  • What happens if instead of the 'https' module you use the 'request' module in the following way => https://github.com/Microsoft/BotBuilder-CognitiveServices/blob/master/Node/lib/QnAMakerRecognizer.js#L39 – Ezequiel Jadib Jul 18 '17 at 19:48
  • I think you're already on the right track, but in general, in situations like these, I recommend running a packet sniffer like Wireshark and viewing the exact messages that you're sending out so that you know for certain that the problem is/isn't in what you're sending or receiving. – Kdawg Jul 21 '17 at 03:16
  • Can you move var resData = ""; inside bot.dialog('qnaReq', function (session, args) { .... }? – Jannes Botis Jul 21 '17 at 11:48

2 Answers2

0

It seems to be the issue as mentioned here.

Try to use Content-Length Header as mentioned here

sandeep
  • 190
  • 1
  • 2
  • 12
0

Your code looks correct. You issue a request using http.request() and do a req.write() and a req.end() (note you can skip the write part and just do req.end(data)).

I think the key here is what happens to the data when you do req.write():

var postData = {question: session.message.text};

Are you sure that session.message.text is not undefined? Because if it is, then postData would be { question: undefined }, which stringified becomes '{}'.

rtn
  • 127,556
  • 20
  • 111
  • 121