Hi, Justin.
I’ve reproduced the relevant code below. It’s almost exactly the simplepost.c
example Christian supplies in his tutorial.
https://www.gnu.org/software/libmicrohttpd/tutorial.html#simplepost_002ec The
biggest changes are that 1) I put in debugging writes, 2) I tried to override
the Content Type header from application/json to
application/x-www-form-urlencoded.
I’ve highlighted the relevant parts in yellow. In my main routine,
MHD_start_daemon is passed answer_to_connection as the callback routine. In
answer_to_connection MHD_create_post_processor is called. It returned a null
because application/json is not supported.
I’m getting the impression from other posts that I should not use
MHD_create_post_processor, but create my own processor of post requests. There
should be a hook that is called when pieces of the request body arrive, but I
haven’t found that hook.
Does your JSON-handling code use MHD_create_post_processor?
Regards, Rick
static int
answer_to_connection (void *cls, struct MHD_Connection *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls)
{
const char* incoming_encoding; // Interesting. Apparently, we point to a
// string that they have allocated and keep ahold of.
LogMessage("In answer_to_connection. Method = \"%s\"", method);
if (NULL == *con_cls) {
LogMessage("con_cls points to a NULL.");
struct connection_info_struct *con_info;
con_info = malloc (sizeof (struct connection_info_struct));
if (NULL == con_info) return MHD_NO;
con_info->answerstring = NULL;
if (0 == strcmp (method, "POST")) {
LogMessage("Method is POST.");
incoming_encoding = MHD_lookup_connection_value(connection,
MHD_HEADER_KIND,
MHD_HTTP_HEADER_CONTENT_TYPE);
LogMessage("Content Type before I changed it was \"%s\"",
incoming_encoding);
MHD_set_connection_value(connection,
MHD_HEADER_KIND,
MHD_HTTP_HEADER_CONTENT_TYPE,
MHD_HTTP_POST_ENCODING_FORM_URLENCODED);
incoming_encoding = NULL;
incoming_encoding = MHD_lookup_connection_value(connection,
MHD_HEADER_KIND,
MHD_HTTP_HEADER_CONTENT_TYPE);
LogMessage("And after I supposedly changed the content type, the c t it
had was \"%s\"", incoming_encoding);
con_info->postprocessor =
MHD_create_post_processor (connection, POSTBUFFERSIZE,
iterate_post, (void *) con_info);
if (NULL == con_info->postprocessor) {
LogMessage("con_info->postprocessor is null");
free (con_info);
return MHD_NO;
}
con_info->connectiontype = POST;
} else {
LogMessage("Method is GET.");
con_info->connectiontype = GET;
}
*con_cls = (void *) con_info;
return MHD_YES;
}
if (0 == strcmp (method, "GET")) {
LogMessage("Method is GET.");
LogMessage("About to send askpage page.");
return send_page (connection, askpage);
}
if (0 == strcmp (method, "POST")) {
LogMessage("Method is POST.");
struct connection_info_struct *con_info = *con_cls;
if (*upload_data_size != 0) {
MHD_post_process (con_info->postprocessor, upload_data,
*upload_data_size);
*upload_data_size = 0;
return MHD_YES;
} else if (NULL != con_info->answerstring) {
LogMessage("About to send con_info->answerstring page.");
return send_page (connection, con_info->answerstring);
}
}
LogMessage("About to send errorpage page.");
return send_page (connection, errorpage);
}
int main(int argc, char** argv) {
int portNum;
char portStr[10];
char outputDir[80];
char logFile[80];
char logPath[200];
struct MHD_Daemon* d;
GetCmdLineStr(argc, argv, "-o", "???", outputDir, sizeof(outputDir) );
GetCmdLineStr(argc, argv, "-l", "???", logFile, sizeof(logFile ) );
if (!strcmp(outputDir, "???") || !strcmp(logFile, "???") ) {
printf("Must supply -o outputDir and -l logFile on the command
line.\n");
return 1;
}
GetCmdLineStr(argc, argv, "-p", "???", portStr, sizeof(portStr) );
if (!strcmp(portStr, "???") ) {
printf("Must supply -p portStr on the command line.\n");
return 1;
}
strcpy(logPath, outputDir);
strcat(logPath, "/");
strcat(logPath, logFile);
portNum = atoi(portStr);
SetAppName("webcxn");
SetLogFileName(logPath);
SetLoggingOn(TRUE);
LogMessage("Webcxn starting");
LogMessage("Webcxn will listen on port number %d", portNum);
d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, portNum, NULL, NULL,
&answer_to_connection, NULL,
MHD_OPTION_NOTIFY_COMPLETED, request_completed,
NULL, MHD_OPTION_END);
if (d == NULL) {
LogMessage("Failed to start the daemon.");
return 1;
}
LogMessage("About to \"pause\" waiting while our daemon does things.");
pause();
LogMessage("Came out of the pause. Signal received?");
MHD_stop_daemon(d);
return 0;
}
From: libmicrohttpd <[email protected]> On
Behalf Of Justin Graves
Sent: Friday, February 22, 2019 10:12 AM
To: [email protected]; libmicrohttpd development and user mailinglist
<[email protected]>
Subject: [EXTERNAL] Re: [libmicrohttpd] Can handle Content-Type =
application/json ?
We are running libmicrohttpd in an API which uses JSON in both request and
response bodies almost exclusively with no issue. We do also use form data. If
the client sends a body with "application/json" as the "Content-Type" header,
we will see whatever they sent via MHD_get_connection_values.
I have just verified this, using libmicrohttp v0.9.62, by sending a request
with a "Content-Type" header of "application/json", then using
MHD_get_connection_values with MHD_HEADER_KIND, and it gives me a key of
"Content-Type" exactly once with a value of "application/json".
Perhaps providing example code related to your header parsing would help?
-
Justin Graves
On Feb 22, 2019, 3:02 AM -0600, Hedin, Richard (InfoSys)
<[email protected]<mailto:[email protected]>>, wrote:
Gentlepeople:
I am using libmicrohttpd to make, naturally, a web server. The client wants to
send me a post request with a content type of “application/json”.
Libmicrohttpd doesn’t seem to support application/json. Only
"application/x-www-form-urlencoded" and "multipart/form-data". I tried using
MHD_set_connection_value as the source code suggested, but it doesn’t work. I
suspect it doesn’t replace the existing Content-Type key, but adds a header to
the end.
Does libmicrohttpd just not work for this case? I don’t feel I can tell my
client not to send me application/json. It’s such an obvious and commonly
accepted format.
Ideas?
Regards, Rick
[AAA]
Get the AAA Mobile app!
[http://www.aaa.com/AAA/images/applebadge.png]<http://www.aaa.com/configuration/SEM/AAAEmailMobileAppDownload.html?app=IOS>[http://www.aaa.com/AAA/images/googlebadge.png]<http://www.aaa.com/configuration/SEM/AAAEmailMobileAppDownload.html?app=ANDROID>
AAA Disclaimer Communication
This communication (including all attachments) is intended solely for the use
of the person(s) to whom it is addressed and should be treated as a
confidential AAA communication. If you are not the intended recipient, any use,
distribution, printing, or copying of this email is strictly prohibited. If you
received this email in error, please immediately delete it from your system and
notify the originator. Your cooperation is appreciated.
________________________________
EXTERNAL - This email originated from an external source
________________________________
[AAA]
Get the AAA Mobile app!
[http://www.aaa.com/AAA/images/applebadge.png]<http://www.aaa.com/configuration/SEM/AAAEmailMobileAppDownload.html?app=IOS>[http://www.aaa.com/AAA/images/googlebadge.png]<http://www.aaa.com/configuration/SEM/AAAEmailMobileAppDownload.html?app=ANDROID>
AAA Disclaimer Communication
This communication (including all attachments) is intended solely for the use
of the person(s) to whom it is addressed and should be treated as a
confidential AAA communication. If you are not the intended recipient, any use,
distribution, printing, or copying of this email is strictly prohibited. If you
received this email in error, please immediately delete it from your system and
notify the originator. Your cooperation is appreciated.