HTTPDynamicPage

 

What was missing in HTTPServer is a way to make dynamic pages... until now. Here's an example program that uses new HTTPDynamicPage class and shows how to create fully dynamic pages in the code.

Dynamic pages are useful for interactive websites. One can build web application on MBED with help of dynamic pages.

 

pub_iva2k_HTTPDynamicPage

 

once compiled and copied to MBED, open

http://mbeddeviceip/dynamic.htm?anyurlparamsyoulike&more

You will see the example page echo back to you the query string "?anyurlparamsyoulike&more". You can further modify the code to parse the query and perform some dynamic response generation. Simplest example could be to ask for a temperature in F or in C.

 

The complete code of HTTPDynamicPage.h (This code is only for quick overview. To reliably get the code without corruption use the published program):

 

#ifndef HTTPDYNAMICPAGE_H
#define HTTPDYNAMICPAGE_H

#include "HTTPServer.h"

/**
 * A datastorage helper for the HTTPDynamicPage class.
 * Stores dynamically created page data and the size left to upload.
 */
class HTTPDynamicPageData : public HTTPData {
  public:
    HTTPDynamicPageData()
     : page_free(NULL), page(NULL), size(0), _left(0) {}
    virtual ~HTTPDynamicPageData() {
      if (page_free && page) {
          page_free(page);
      }
    }

    /** Pointer to garbage collection function (for freeing page data)
     * Should be set by callback function to a suitable free() if page is dynamically allocated
     */
    void (*page_free)(void *page);
    
    /** Pointer to the page data */
    char *page;
    
    /** Page data size
     * As long as the page is NULL terminated you don't have to tell the data length.
     * But if you want to send binary data you should tell us the size.
     */
    int size;

    /** Page data size left for the upload */
    int _left;
};

/**
 * This class Provide a Handler to send Dynamic HTTP Pages from the bin file.
 */
class HTTPDynamicPage : public HTTPHandler {
  public:
    /**
     * Constructor takes the page path and the page callback function.
     */
    HTTPDynamicPage(const char *path, HTTPStatus page_fnc(HTTPConnection *con, HTTPDynamicPageData *pd))
     : HTTPHandler(path), _page_fnc(page_fnc) {
    }

    HTTPDynamicPage(HTTPServer *server, const char *path, HTTPStatus page_fnc(HTTPConnection *con, HTTPDynamicPageData *pd))
     : HTTPHandler(path), _page_fnc(page_fnc) {
      server->addHandler(this);
    }

  private:
    /**
     * This Dynamic Page is requested!
     * Prepare a datastorage helper "HTTPDynamicPageData", create the page and store in helper, then initialize remaining data size.
     * And return HTTP_OK if all ok.
     */
    virtual HTTPStatus init(HTTPConnection *con) const {
      HTTPDynamicPageData *data = new HTTPDynamicPageData();
      con->data = data;
      HTTPStatus status = _page_fnc(con, data);    // assigns data->page, data->size and optionally data->page_free
      if (!data->size && data->page)
          data->size = strlen(data->page);
      data->_left = data->size;
      con->setLength(data->size);
      return status;
    }

    /**
     * Send the maximum data out to the client. 
     * If the file is complete transmitted close connection by returning HTTP_SuccessEnded
     */
    virtual HTTPHandle send(HTTPConnection *con, int maximum) const {
      HTTPDynamicPageData *data = static_cast<HTTPDynamicPageData *>(con->data);
      int len = min(maximum, data->_left);
      err_t err;

      do {
        err = con->write((void*)&data->page[data->size - data->_left], len, 1);
        if (err == ERR_MEM) {
          len >>= 1;
        }
      } while(err == ERR_MEM && len > 1);
      if (err == ERR_OK) {
        data->_left -= len;
      }
      return (data->_left) ? HTTP_Success : HTTP_SuccessEnded;
    }

    HTTPStatus (*_page_fnc)(HTTPConnection *con, HTTPDynamicPageData *pd);
};

#endif


5 comments

15 Jan 2010

Ilya,

When compiling the code above, I received errors on Line 77. 

HTTPDynamicPageData *data = static_cast(con->data);

So I looked up my older code (with the SNTP client) and found this on Line 77.  It compliles without error.

HTTPDynamicPageData *data = static_cast<HTTPDynamicPageData *>(con->data);

Is there anything else that changed what allows for the new Line 77 in the above code to compile w/o error?  Or have things totally changed?

...kevin

16 Jan 2010 . Edited: 16 Jan 2010

Kevin,

The online forum editor is notorious for chewing up the code. I'm tired fighting with it. It obviously cleaned out <HTTPDynamicPageData *> as it looks like HTML tag. Please use the published program instead of the code. I learned my lesson and not pasting whole files into posts anymore. Only code to illustrate ideas. I still will try to fix the above, but no guarantees.

04 Jul 2010

Nice work IIya! Can you help a little more?

How can I turn on/off a LED1 by a click on the page?

How can I show an A/D reading on the page?

How can I show the state of a digital input on the page?

I’m newbie to mbed, sorry if my questions seams so obvious to you.

Harald

07 Jul 2010

I have a few moments and I'll give a couple of pointers...

 

> How can I turn on/off a LED1 by a click on the page?

Use javascript and RPC. Search this site for examples. Simon published some examples a while back.

 

>How can I show an A/D reading on the page?

I assume you want it to be dynamic. If you are good with static data (one that won't change after the page is drawn) - use dynamic page that will print something from A/D output. If you want to dynamically update the data - use javascript and RPC, similar to the above. You will need to set up a timer in javascript that will periodically query A/D over the RPC and print result into the HTML document.

 

> How can I show the state of a digital input on the page?

Same as above.

19 Jul 2010

Hallo ..,

Has any one a sample code with an dynamix page and "fix" pages, whiche are stored as file on mbed-board?

best regards robert

You need to log in to post a comment