# Web Server
[Libraries]

A simple Web Server. More...

## Data Structures
struct | HtmlFormElement
| A structure that represents a key-value pair in an HTML form. More...
struct | HtmlForm
| A structure that represents a collection of HtmlFormElement structures. More...
## Functions
int | WebServer_SetActive (int active)
| Start the WebServer up, listening on port 80.
int | WebServer_GetActive (void)
| Read the active state of the WebServer subsystem.
int | WebServer_SetListenPort (int port)
| Set the port that the webserver should listen on for new connections.
int | WebServer_GetListenPort (void)
| Get the port that the webserver is currently listening on.
int | WebServer_Route (char *address, int(*handler)(char *requestType, char *address, char *requestBuffer, int requestMaxSize, void *socket, char *buffer, int len))
| Adds a route handler to the WebServer.
int | WebServer_WriteResponseOkHTML (void *socket)
| Writes the HTTP OK message and sets the content type to HTML.
int | WebServer_WriteResponseOkPlain (void *socket)
| Writes the HTTP OK message and sets the content type to plain text.
int | WebServer_WriteHeader (int includeCSS, void *socket, char *buffer, int len)
| Writes the HTML header.
int | WebServer_WriteBodyStart (char *reloadAddress, void *socket, char *buffer, int len)
| Writes the start of the BODY tag.
int | WebServer_WriteBodyEnd (void *socket)
| Writes the end of the Body tag - and the final end of HTML tag.
bool | WebServer_GetPostData (void *socket, char *requestBuffer, int maxSize)
| Set the data of an incoming HTTP POST request to the given buffer.
int | WebServer_ParseFormElements (char *request, HtmlForm *form)
| Extract the elements of an HTML form into key/value pairs.

## Detailed Description

A simple Web Server.

This Web Server implementation is based on the ServerSocket and Socket functions defined in Sockets. When started, a ServerSocket is opened and set to listen on port 80.

When the server receives a request, it checks the incoming address against a list of handlers. If the request address matches, the handler is invoked and checking stops. Users can add their own handlers to return custom information - see WebServer_Route(). Most of the rest of the WebServer system provides helpful functions for generating and parsing HTML.

There is a single default/test handler that will handle any requests that are not otherwise handled. This is about the simplest demo possible of how to write a handler - it simply prints out some text and a count of how pages it has served. There are more handler examples further down this page, and in the mcbuilder examples. Take a look at TestHandler() in webserver.c to see its source.

To access the web server type the IP address of your board into a web browser, optionally followed by the address of any handlers you've registered, ie 192.168.1.200/myhandler.

## Function Documentation

int WebServer_GetActive | ( | void |  | ) |

Read the active state of the WebServer subsystem.

Returns:
  State - 1/non-zero (on) or 0 (off).

Definition at line 170 of file webserver.c.

int WebServer_GetListenPort | ( | void |  | ) |

Get the port that the webserver is currently listening on.

Returns:
  The port number.

Example

      int currentPort = WebServer_GetListenPort( );

Definition at line 204 of file webserver.c.

bool WebServer_GetPostData | ( | void * | socket,
|  | char * | requestBuffer,
|  | int | maxSize |
| ) |  |  |

Set the data of an incoming HTTP POST request to the given buffer.

This is designed to be used from within a custom handler. An incoming HTTP request will have some number of lines of header information, and this function will read through them until getting to the body of the message. It will then store the contents of the body in the given buffer, null-terminating the end of the data.

It's usually convenient to set the POST data in the requestBuffer since it's already allocated.

Example

    int MyRequestHandler( char* requestType, char* address, char* requestBuffer,
                          int requestMaxSize, void* socket, char* buffer, int len )
    {
      // ... other setup here ...

      if ( strncmp( requestType, "POST", 4 ) == 0 ) // if the request is indeed a POST
      {
        if( WebServer_GetPostData( socket, requestBuffer, requestMaxSize ) ) // set the POST data in the requestBuffer
        {
          // process the data in any way you like.
          // here, we're expecting a form and we want to grab the info out of it
          formElements = WebServer_ParseFormElements( requestBuffer, &form );
        }
      }

      // ... write out the response here ...
    }

Parameters:

  | socket | The socket from the incoming request
  | requestBuffer | A pointer to the buffer to store the data in.
  | maxSize | The maximum amount of data to be placed in the buffer.

Returns:
  true on success, false on failure

Definition at line 496 of file webserver.c.

int WebServer_ParseFormElements | ( | char * | request,
|  | HtmlForm * | form |
| ) |  |  |

Extract the elements of an HTML form into key/value pairs.

This is designed to be used from within a custom handler. HTML forms can be sent via either the HTTP GET or POST methods. The request parameter must be set to the start of the form data, which is located in a different place for each method. In the GET case, we need to check if there are any form elements, as indicated by a ? after the URL address. In the POST case, we can use WebServer_GetPostData() to find the beginning of the POST data for us.

Note that the HtmlForm structure will simply point to the elements in the request buffer, so as soon as the buffer is deleted or out of scope, the form data is no longer valid.

Example

    int MyRequestHandler( char* requestType, char* address, char* requestBuffer,
                          int requestMaxSize, void* socket, char* buffer, int len )
    {
      // ... other setup here ...

      int formElements = 0;
      HtmlForm form;
      form.count = 0;

      // determine the kind of request - GET or POST
      if ( strncmp( requestType, "GET", 3 ) == 0 )
      {
        char *p = strchr( requestBuffer, '?' ); // if GET, see if there's a ?
        if( p != NULL ) // if we didn't find a ?, there were no form elements
          formElements = WebServer_ParseFormElements( p+1, &form );
        // we have to send "p + 1" since the form data starts right after the ?
      }
      else if ( strncmp( requestType, "POST", 4 ) == 0 )
      {
        // make sure we're pointing at the POST data and if it looks good, process it
        if( WebServer_GetPostData( socket, requestBuffer, requestMaxSize ) )
          formElements = WebServer_ParseFormElements( requestBuffer, &form );
      }

      // ... write out the response here ...
    }

Parameters:

  | request | A pointer to the form data
  | form | The HtmlForm structure to populate with elements

Returns:
  The number of form elements found

Definition at line 582 of file webserver.c.

int WebServer_Route | ( | char * | address,
|  | int(*)(char *requestType, char *address, char *requestBuffer, int requestMaxSize, void *socket, char *buffer, int len) | handler |
| ) |  |  |

Adds a route handler to the WebServer.

This function binds an address fragment (e.g. "/", "/adcs", etc.) to a handler that will be called when the address matches. Matching ignores characters in the incoming address that are beyond the end of the address specified to this function. The first function to match the address will receive all the traffic and no more handlers will be checked. Thus if a handler is set up to match "/images" it will match "/images" and "/images/logo.png" and so on. Also if there is a subseqent handler set to match "/images/diagram" it will never be called since the prior handler will match the entire "/images" space. You can register your handlers prior to firing up the webserver system.

The handler will be called with the request type specified (usually "GET" or "POST"), the incoming address ( "/device/0", "/images/logo.png", etc.) A buffer (and max length) is passed in that can be used to receive the rest of the message if necessary. Then there will be the socket which will take the response and a helpful large buffer or specified length which can be used to build strings.

At the time the handler is called, only the first line of the request has been read. It is used to determine the request type and the address requested. If you need to process the request further its contents may be read into a buffer (the request buffer passed in is good once the request type address have been used since they're in there initially). The SocketReadLine( ) function is convenient to read a line of the request at a time.

The handler itself must first write the response using one of WebServer_WriteResponseOkHTML() for sending HTML or WebServer_WriteResponseOkPlain() for returning plain text. These send the appropriate HTTP header (for example "HTTP/1.0 200 OK\r\nContent-type:text/html\r\n\r\n"). All responses may be simply written to the Socket, but several helpers are provided to assist in the construction of simple web pages (for example WebServer_WriteHeader(), WebServer_WriteBodyStart(), etc.).

The handler should return non-zero if it handled the response appropriately or 0 if not, in which case the webserver will check for matches with other handlers that can handle it.

Parameters:

  | address | An string specify the addresses to match.
  | handler | pointer to a handler function that will be called when the address is matched.

Returns:
  CONTROLLER_OK (=0) on success or the appropriate error if not

Here is an example of how to register a handler:

    // now requests at MyBoardsIPAddress/my/handler will be handled by MyHandler
    WebServer_Route( "/my/handler", MyHandler );

And here is an example handler, printing out some simple info in response to any request.

    int MyHandler( char* requestType, char* address, char* requestBuffer, int requestMaxSize,
                     void* socket, char* buffer, int len )
    {
      (void)requestType;
      (void)address;
      WebServer_WriteResponseOkHTML( socket );
      WebServer_WriteHeader( true, socket, buffer, len );
      WebServer_WriteBodyStart( address, socket, buffer, len );
      snprintf( buffer, len, "<H1>TEST</H1>%d hits", WebServer->hits );
      SocketWrite( socket, buffer, strlen( buffer ) );
      WebServer_WriteBodyEnd( socket );
      return true;
    }

Definition at line 269 of file webserver.c.

int WebServer_SetActive | ( | int | active | ) |

Start the WebServer up, listening on port 80.

See WebServer_Route() for info on how to register handlers for certain requests.

Parameters:

  | active | An integer specifying the active state - 1 (on) or 0 (off).

Returns:
  CONTROLLER_OK (0) on success or the appropriate error if not

Example

      // fire up the webserver
      WebServer_SetActive(true);

Definition at line 122 of file webserver.c.

int WebServer_SetListenPort | ( | int | port | ) |

Set the port that the webserver should listen on for new connections.

Note that this does not immediately take effect - because the webserver (if it's open) is already listening on a port, it will only take effect after it serves one last request on that port.

Parameters:

  | port | The new port to listen on.

Returns:
  0 on success.

Example

      // listen on a non-standard port for HTTP
      WebServer_SetListenPort(8080);

Definition at line 189 of file webserver.c.

int WebServer_WriteBodyEnd | ( | void * | socket | ) |

Writes the end of the Body tag - and the final end of HTML tag.

Should be preceded by writes to the socket with the content of the page - this is often the last thing done in a handler. See WebServer_Route() for a more complete example.

Parameters:

  | socket | The socket to write to

Returns:
  non-zero on success, zero on failure.

Example

      int MyRequestHandler( char* requestType, char* address, char* requestBuffer,
                          int requestMaxSize, void* socket, char* buffer, int len )
      {
        // ... other code actually doing interesting things ...
        WebServer_WriteBodyEnd(socket); // now we're all done
        return 1;
      }

Definition at line 456 of file webserver.c.

int WebServer_WriteBodyStart | ( | char * | reloadAddress,
|  | void * | socket,
|  | char * | buffer,
|  | int | len |
| ) |  |  |

Writes the start of the BODY tag.

Should be preceded by a call to WebServer_WriteHeader(). Also writes a light grey background. You can optionally specify that you'd like the page to automatically refresh itself once a second by passing in the address to reload to reloadAddress. See WebServer_Route() for a more complete example.

Parameters:

  | reloadAddress | A string signaling the address of a 1 second reload request. If it is NULL, no reload is requested.
  | socket | The socket to write to.
  | buffer | Helper buffer which the function can use. Should be at least 300 bytes. This is usually the buffer passed into your handler as buffer.
  | len | Helper buffer length. Also usually passed into your handler as len.

Todo:
  more parameterization of the tag

Example

      int MyRequestHandler( char* requestType, char* address, char* requestBuffer,
                          int requestMaxSize, void* socket, char* buffer, int len )
      {
        // ... usually write out the OK response and the header first ...
        WebServer_WriteBodyStart(0, socket, buffer, len); // write the body start, with no reload
        // ... continue processing ...
      }

Definition at line 418 of file webserver.c.

int WebServer_WriteHeader | ( | int | includeCSS,
|  | void * | socket,
|  | char * | buffer,
|  | int | len |
| ) |  |  |

Writes the HTML header.

Should be preceded by a call to WebServer_WriteResponseOkHTML(). See WebServer_Route() for a more complete example.

Parameters:

  | includeCSS | A flag signalling the inclusion of a very simple CSS header refining h1 and body text slightly.
  | socket | The socket to write to
  | buffer | Helper buffer which the function can use. Should be at least 300 bytes.
  | len | Helper buffer length

Returns:
  non-zero on success, zero on failure.

Todo:
  more parameterization

Example

      int MyRequestHandler( char* requestType, char* address, char* requestBuffer,
                          int requestMaxSize, void* socket, char* buffer, int len )
      {
        // ... usually write out the OK response first ...
        WebServer_WriteHeader(true, socket, buffer, len); // write the header, including simple CSS
        // ... continue processing ...
      }

Definition at line 377 of file webserver.c.

int WebServer_WriteResponseOkHTML | ( | void * | socket | ) |

Writes the HTTP OK message and sets the content type to HTML.

This will typically be the first thing you write out in your handler. Also see WebServer_WriteResponseOkPlain() to set your response type to plain text.

Parameters:

  | socket | The socket to write to

Returns:
  non-zero on success, zero on failure.

Example

      int MyRequestHandler( char* requestType, char* address, char* requestBuffer,
                          int requestMaxSize, void* socket, char* buffer, int len )
      {
        WebServer_WriteResponseOkHTML(socket); // write the response out first
        // ... continue processing ...
      }

Definition at line 312 of file webserver.c.

int WebServer_WriteResponseOkPlain | ( | void * | socket | ) |

Writes the HTTP OK message and sets the content type to plain text.

This will typically be the first thing you write out in your handler. Also see WebServer_WriteResponseOkHTML() to set your response type to HTML.

Parameters:

  | socket | The socket to write to.

Returns:
  non-zero on success, zero on failure.

Example

      int MyRequestHandler( char* requestType, char* address, char* requestBuffer,
                          int requestMaxSize, void* socket, char* buffer, int len )
      {
        WebServer_WriteResponseOkPlain(socket); // write the response out first
        // ... continue processing ...
      }

Definition at line 349 of file webserver.c.