EmbeddedRelated.com
Forums

Help needed with uploading data to HTTP Server

Started by racqueldesign May 8, 2013
Hi,

I need help with uploading(maybe posting is the proper word) data to my HTTP server. I have read the document on uploading files but this is a simple data upload and the skeleton example isn't working me. Can someone please tell me what I am doing wrong.

The HTTP Server doesn't have a webpage to accept FORM. It simple respond to upload data. Example of the data in the body of the HTTP request i am require to upload is :
{
"sensor 2": 1,
"name": "contact sensor",
"username": "sandy",
"password": "access",
"msg": [{"update"}]
}
--------------------skeleton example in the document-------------
int my_CGI(HttpState * s)
{
switch(http_getAction(s)) {
case CGI_START:
break;
case CGI_DATA:
break;
case CGI_END:
break;
case CGI_EOF:
break;
case CGI_ABORT:
break;
}
return 0;
}
It depends how did you set your initialization. To enable cgi funtions (in the new style, as your example) your have to:

1) #define USE_HTTP_UPLOAD
2) register the MIME type in your static table
3) register the function in the HTTP web server (with authentication, if you want)

This is a example:

#define USE_HTTP_UPLOAD

int http_myCGI(HttpState *state);

SSPEC_MIMETABLE_START
SSPEC_MIME(".cgi", "")
SSPEC_MIMETABLE_END

SSPEC_RESOURCETABLE_START
SSPEC_RESOURCE_P_FUNCTION("/my.cgi", http_cabinetsCGI, "my1", ADMIN_GROUP, ADMIN_GROUP, SERVER_HTTP, SERVER_AUTH_BASIC)
SSPEC_RESOURCETABLE_END

_debug int http_myCGI(HttpState *state) {
int rc;

rc = 0;
switch (http_getAction(state)) {
case CGI_START:
// see manual reference for see what you can do here
break;
case CGI_DATA:
// here you get a chunk of data, you can process or save in local buffer or FAT file
case CGI_END:
// end of POST data, see manual reference
break;
..
..
case CGI_EOF:
// when you finish, remember to send to client at least a
// header HTTP response (HTTP 1.0 200 OK). You can do this
// with this function, see HTTP.LIB
http_genHeader(state, http_getData(state), HTTP_MAXBUFFER, 200, NULL, 0, NULL);
// then tell to HTTP server that you have finished to process the request and do not call this function anymore.
rc = CGI_SEND_DONE;
break;
}

return rc;
}

If you want you can also send to client an entire page or existing FAT file by switching/redirecting to. You can also produce the entire response in another cgi.

In your example you should return 0 only if you haven't finished to process the request so the HTTP server will call your function again with another chunk of data, or another state. But at the end return something else (1, CGI_DONE, CGI_SEND_DONE...). Or else you client will wait until a socket time-out will occurs.

I hope this can help you.
Thanks Mark,

But how under which http_getAction(state) action is data parse? Is it CGI_DATA? Also do I respond to client under this same action? Example of http post data is:
{
"sensor 2": 1,
"name": "contact sensor",
"username": "sandy",
"password": "access",
"msg": [{"update"}]
}
It depends how data is encoded in the http form post. If the form mime type is "application/x-www-form-urlencoded" the body of the request is one giant query string (name/value pairs separated by the ampersand '&', and names separated from values by equal '='). For example:
var1=value1&var2=value2&var3=value3

Values are encoded to be compatible with some special characters so you need to decode. This is a HTTP specification so I suggest to search on the web for more informations about this. Dynamic C libraries has http_urldecode().

Else if the mime type is multipart/form-data each field of the form is enclosed between boundaries. In this case you can post binary data of an arbitrary length.

In the CGI_DATA you can obtain the name of the field by the http_getField(), value and its length in bytes by http_getData() and http_getDataLenth(). Take a look in the Dynamic C TCP/IP Reference Manual Vol.2.

Response must be sent ONLY when you have received all data submitted from the client because you have to write it on the same socket buffer (and if you write on that buffer while client is still sending its data, it will lost your response). So you should do this in CGI_EOF.

Read the Dynamic C TCP/IP Reference Manual Vol.2, more specifically the chapter about HTTP server. You will find all that you need. The chapter introduces the old style cgi, then talk about the new style for posting bynary data and save to file (file uploading), but essentially it is the same: you have a HTTP form with some fields with values (string, int, ecc, all treates as binary data). Encoding is set by the client (mime parameter) but the Dynamic C HTTP library process all this for you and call your function only when data are processed and ready to you. It is your task how to interprete/save these values.
It sounds like you (original poster) might be going through a lot of unnecessary work. Take a look at the RabbitWeb samples if you're dealing with forms, and some of the HTTP Upload samples for file uploads.

There's a lot of code already in Dynamic C to make it easy to do forms and uploads. Trying to reinvent that through the CGI interface will be difficult and time consuming.

-Tom
Yes, RabbitWeb can made some thing more easy. It enables a sort of server-side scripting system like PHP in your Rabbit module. But it is memory and CPU-time consuming. And web pages with forms must be resident inside the firmware (with the #ximport directive) because they need to be processed by the server before served to client who requests it. In this case "client" must be a web browser application that display the page and then post back data to server.

In the other way, the cgi function acts like a sort of web service and client should be a browser again but also a Java/Delphi/C# standalone client for remote administration, for example.

At the end you should decide the way based on how you intend to send data and how you process them then.