getting http post data

16 Jan 2011

Hi all am currently experimenting with embed and i am very impressed with it I have a question. I can get the mbed to act as webserver but i would like to control the leds via webpage control where can i get the post data that is sent when the submit button is pressed any help appreciated as i cant see where to get the page data or do you have to go via a handler. i did look at rpc but my braincell gave up many thanks for your time Chris

22 May 2011

So is there not a a code snippet that shows how to do this ? I'm thinking it must be a pretty useful example to have for us newbies to mBed , something that recovers just a few post values that could be used to update variables in the code. I have found the more involved RPC and AJAX things but a basic example would be easier for now. I have Donatiens httpserver running Ok.

K

22 May 2011

//*****************************************************
ON MAIN
//*****************************************************

#include "PostHandler.h"
//get your IP ready code goes here

HTTPServer svr;		//initialize server object
svr.bind(80);		//let server to listen to standard HTTP port

svr.addHandler<PostHandler>("/android");	//add a handler named PostHandler (executed when received "http://your_ip/android")

while(1)
{
	Net::poll();			//start listening
}


//*****************************************************
ON PostHandler.h
//*****************************************************

#ifndef POST_HANDLER_H
#define POST_HANDLER_H
#include "../HTTPRequestHandler.h"
#include "../HTTPRequestDispatcher.h"

//handles POST request
class PostHandler : public HTTPRequestHandler
{
    public:
        PostHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket);
        virtual ~PostHandler();
    
        static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTCPSocket){return new PostHandler(rootPath, path, pTCPSocket);}
        
        virtual void doGet();
        virtual void doPost();
        virtual void doHead();
        
        virtual void onReadable();
        virtual void onWriteable();
        virtual void onClose();
};

#endif

//*****************************************************
ON PostHandler.cpp
//*****************************************************

#include "PostHandler.h"
#include "string.h"


PostHandler::PostHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket):HTTPRequestHandler(rootPath, path, pTCPSocket){
}


PostHandler::~PostHandler(){
}

void PostHandler::doGet(){
}

void PostHandler::doPost()
{
    
    //get post variables
    string _path = path();
    string _rootpath = rootPath();
    int _datalen = dataLen();
    
    //grab header variables
    string _content_length = reqHeaders()["Content-Length"];
    string _content_type = reqHeaders()["Content-Type"];
    string _user_agent = reqHeaders()["User-Agent"];
    string _expect = reqHeaders()["Expect"];
}

void PostHandler::doHead(){
}

void PostHandler::onReadable(){
    
    Serial pcx(USBTX, USBRX);
    
    int _datalen = dataLen();   	//read POST data length
    
    //allocate size of readable data
    char* _read_data = (char *) malloc(sizeof(char) * _datalen);
    
    //read POST data
    readData(_read_data, _datalen);
    
    pcx.printf("\r\n\r\nPOST Data\t:\t%s\r\n", _read_data);

	//create a response

	char *http_response = "This is my reply";
    
    setContentLen(strlen(http_response));
    respHeaders()["Content-Type"] = "text/plain; charset=utf-8";
    respHeaders()["Connection"] = "close";
    
    writeData(http_response, strlen(http_response));
}

void PostHandler::onWriteable(){    
close();
}

void PostHandler::onClose(){
return;
}

_read_data contains the post data, examine it and decide what you're going to do with it. You're probably going to seperate the POST components, process it, light some LED etc

Good luck

22 May 2011

Herson,

Thank you so much for that , I'll let you know how I get on but that looks like exactly what I needed.

cheers Kevin

23 May 2011

If you get problems running it, let me know

23 May 2011

This is where I'm at so far...

When I post the form I get the doPost and after a few seconds the doClose handler running but not doHead or onReadable.

Here is the html I'm using, which I suspect is my issue.

<!DOCTYPE HTML PUBLIC "-W3CDTD HTML 4.01EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=ISO-8859-1"> <title>Post Test</title> </head>

<body>

<h1>Kevin's POST test</h1>

<h2>Post form</h2>

<form method="post" action="http://192.168.1.169/android">

text:<input type="text" size =40 name="name">

<input type=submit value="Submit Post">

</form>

</body>

</html>

and I am recovering some but not all values in the doPost handler

Setup OK Listening...

doPost

Path

Root /android

Length 10

Content Length 10

Content Type application/x-www-form-urlencoded

user agent Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1

Expect

doClose

I'll keep working on it but any help much appreciated ...

K

23 May 2011

did it get to print anything inside the onReadable()?

also on the malloc part

<<code>>char* _read_data = (char *) malloc(sizeof(char) * (_datalen+1));<</code>>

to accomodate terminating character

23 May 2011

It never executed the onReadable() at all... .I put a printf as the first line

K

23 May 2011

try taking out the DOCTYPE and meta tags from your html file and see what happens

everything else is working as you get the length of the actual POST data

23 May 2011

I put them in actually because it wasn't working but just took them out again and it's made no difference. It doesn't call the doHead() or onReadable() handler - just the doPost() - which does as you say recover the length and the onClose()

23 May 2011

Try take out the close() part on the onWriteable par

23 May 2011

It doesn't execute onWriteable() but I did try it without the close() too....

I'm going to have to call it a night here (4AM) but I'll check back in the morning...

Thanks for persevering :-) K

BTW It doesn't recover a value for _path or _expect in doPost().. Is that an issue ?

23 May 2011

Hello Herson Bagay,

On PostHandler.cpp, there are some function haven't complete one, am i rite? like example: PostHandler() doGet() doHead() onWriteable()

Can you provide us a sample code how we going to make use of this PostHandler.h library function on Main.cpp?

Thank you, Wen

23 May 2011

The expect and path, dont be concerned for now, i dont even use the values in my code

The doGet is executed when you send a GET request

As for the onWriteable, it is executed whenever you send an http reply

23 May 2011

Hello Herson,

Thanks for your reply.

May i know when is the GET request? I still no idea how to add the function in main.cpp. I simply assign PostHandler x; in global main.cpp and in the main while loop i just put x.doGet(); or x.onWriteable(); then i compile i get this message "No default constructor exists for class "PostHandler" (E291)".

May i know how can i solve the errors?

Thank you, Wen

23 May 2011

Herson,

Good morning - as ever a nights sleep has helped :-) I think I have to add at the end of httpserver.h

  #include "impl/PostHandler.h" 

Now just to work out how to redirect back to a web page served from the file system after the POST but that should be fairly easy ...

Thanks for all your help last night, much appreciated it's got me over the hurdle.

Kevin

23 May 2011

Mine works like a charm.

Did you include the necessary

#ifndef POST_HANDLER_H
#define POST_HANDLER_H
#include "../HTTPRequestHandler.h"
#include "../HTTPRequestDispatcher.h"

on PostHandler.h

23 May 2011

What on earth are you doing awake at this time of (your) morning ?

I edited my previous post at the coincident time you posted... all sorted now I think.

K

23 May 2011

Im much more of a nocturnal coder and Im used to 5 hour sleeps

26 Mar 2013

Can anyone lend some assistance as the brain is going to mush over this issue, and the lack of error log is making it difficult to resolve

so from the following above..

*********** ON MAIN ***********

  1. include "PostHandler.h" get your IP ready code goes here

HTTPServer svr; initialize server object svr.bind(80); let server to listen to standard HTTP port

svr.addHandler<PostHandler>("/android"); add a handler named PostHandler (executed when received "http://your_ip/android")

while(1) { Net::poll(); start listening }

yes got that - listen for stuff thats posted to '/android'.

see comments yes understand #includes no probs there

  1. ifndef POST_HANDLER_H
  2. define POST_HANDLER_H
  3. include "../HTTPRequestHandler.h"
  4. include "../HTTPRequestDispatcher.h"

handles POST request

class PostHandler : public HTTPRequestHandler { public: PostHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket); virtual PostHandler();

static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTCPSocket){return new PostHandler(rootPath, path, pTCPSocket);}

virtual void doGet(); virtual void doPost(); virtual void doHead();

virtual void onReadable(); virtual void onWriteable(); virtual void onClose();

0 what aree these things doing? };

  1. endif

does the cpp file live in the same folder as the compiled or where shoud it reside.

*********** ON PostHandler.cpp ***********

  1. include "PostHandler.h"
  2. include "string.h"

PostHandler::PostHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket):HTTPRequestHandler(rootPath, path, pTCPSocket){ }

PostHandler::PostHandler(){ }

void PostHandler::doGet(){ }

getting the post data and headers how do we echo the data to the terminal window for error checking?

void PostHandler::doPost() {

get post variables string _path = path(); string _rootpath = rootPath(); int _datalen = dataLen();

grab header variables string _content_length = reqHeaders()["Content-Length"]; string _content_type = reqHeaders()["Content-Type"]; string _user_agent = reqHeaders()["User-Agent"]; string _expect = reqHeaders()["Expect"]; }

void PostHandler::doHead(){ } empty function.

void PostHandler::onReadable(){

Serial pcx(USBTX, USBRX);

int _datalen = dataLen(); read POST data length

allocate size of readable data char* _read_data = (char *) malloc(sizeof(char) * _datalen);

read POST data readData(_read_data, _datalen);

pcx.printf("\r\n\r\nPOST Data\t:\t%s\r\n", _read_data);

create a response

char *http_response = "This is my reply";

setContentLen(strlen(http_response)); respHeaders()["Content-Type"] = "text/plain; charset=utf-8"; respHeaders()["Connection"] = "close";

writeData(http_response, strlen(http_response)); }

void PostHandler::onWriteable(){ close(); }

void PostHandler::onClose(){ return; }

any help would be gratefully appreciated

Mark