
mongoose - issue #407
I cannot get mongoose to process a GET from the client when requesting a JSON file.
I have the following javascript that does a GET on a CGI called "GeneralInfoParams" that returns JSON formatted data:
var jqxhr = $.getJSON( "/usr/www/cgi-bin/GeneralInfoParams", function() {
console.log( "success getting parameters from server" );
})
I am using the example code from server.c to run mongoose. I am attaching my config file.
I expected the call to be successful. I have validated my JSON output from the script file on another server. The call fails.
What version of the product are you using? On what operating system? I am running the current version v.5.4 server on QNX 6.5.0
Do I need to
- mongoose_config.txt 6.04KB
Comment #1
Posted on Apr 22, 2014 by Helpful GiraffeSorry. Do I need to add an event handler to handle GET requests? I see in the code where SSI #exec's are handled and that works fine, calling a popen to spawn the executive. I do not see a place in the code to spawn the cgi I am requesting in the GET.
Comment #2
Posted on Apr 22, 2014 by Helpful GiraffeI am having great difficulty getting either a XMLhttpRequest or a jquery $.getJSON to work with Mongoose. I was able to get this code to work on slinger, with a slight url change to match that servers requirements. I know that my JSON data returns correct from the CGI GeneralInfoParams.
I have some javascript to make a get request to the server:
$.ajaxSetup({ cache: false });
var jqxhr = $.getJSON( "/GeneralInfoParams", function() {
console.log( "success getting parameters from server" );
})
.done(function(data)
{
document.getElementById('RRName').innerHTML = data.rrname;
document.getElementById('LocoNum').innerHTML = data.loconum;
document.getElementById('ModelNum').innerHTML = data.modelnum;
document.getElementById('SerialNum').innerHTML = data.serialnum;
document.getElementById('CHMSerialNum').innerHTML = data.chmserialnum;
document.getElementById('SSDSerialNum').innerHTML = data.ssdserialnum;
document.getElementById('SWVerDate').innerHTML = data.swverdate;
document.getElementById('ConfigVerDate').innerHTML = data.configverdate;
})
.fail(function() {
console.log( "error getting parameter data from server" );
})
$.ajaxSetup({ cache: true });
Notice I set the URL to "/GeneralInfoParams". I did this because when I try to pass in the full path of “/usr/www/cgi-bin/ GeneralInfoParams”, the ev_handler I set up below will not have the full path in the conn->uri for some reason. The only thing that makes the event handler work is when I pass in a single path like "/GeneralInfoParams". This seems to be the case also in your form.c example where your javascript passes a URL of "/get_value" which is caught in your handler example.
So in the event handler below, I call a function called do_cgi_exec to return the json. I found out that if in my CGI I printed the “Content-Type: application/json”, that the code would never work. I stripped this out and just had my CGI print the JSON data. This got the $.getJSON to work on Mongoose, however, the time it took for $.getJSON to do a callback to the .done function was like 45 seconds. Way too slow. So I did a test where I just printed some simple json directly from the event handler: mg_printf_data(conn, "{\"value\": 43}"); This made the response time fast.
//Event handler for CGI calls from client Javascript for JSON data static int ev_handler(struct mg_connection *conn, enum mg_event ev) { if (ev == MG_REQUEST) { if (strcmp(conn->uri, "/GeneralInfoParams") == 0) { do_cgi_exec(conn, (char *)conn->uri); //mg_printf_data(conn, "{\"value\": 43}"); } else if (strcmp(conn->uri, "/set_value") == 0) { return MG_FALSE; } else { // Better way is to set "document_root" option, put "index.html" file // into document_root and return MG_FALSE here. We're printing HTML // page by hands just to keep everything in one C file. //print_params(conn); return MG_FALSE; } return MG_TRUE; } else if (ev == MG_AUTH) { return MG_TRUE; } return MG_FALSE; }
Calling do_cgi_exec() which does a popen to execute the CGI, seems to execute quickly when I single step through the code. But the time it takes for the a getJSON to return a callback is really long.
Notice I added the full path "/usr/www/cgi-bin “ back onto the url in this function. This is not ideal at all. I only did this to get around the problem I had with the full path.
static void do_cgi_exec(struct mg_connection *conn, char *tag) { char cmd[IOBUF_SIZE]; FILE *fp;
char lCommand[100]; sprintf (lCommand, "/usr/www/cgi-bin%s", tag); if ((fp = popen(lCommand, "r")) == NULL) { mg_printf(conn, "Cannot exec cgi: [%s]: %s", tag, strerror(errno)); } else { int n;
while ((n = fread(cmd, 1, sizeof(cmd), fp)) > 0) {
mg_write(conn, cmd, n);
}
pclose(fp);
} }
What I really want is the mongoose.c code to natively be able to handle what I am trying to do, or an example code that does this. I want to be able to do a getJSON call from Javascript with a URL to an executable that returns dynamic JSON data to be used for populating my web page html.
Can you please help me out with this?
Comment #3
Posted on Jul 27, 2014 by Massive HorseDon't use mg_write or mg_printf. Use mg_send_data() or mg_printf_data.
Status: Done
Labels:
Type-Defect
Priority-Medium