Bitty HTTP

Development » Headers

1Custom Headers

This example will show how to add your own custom headers to the http reply.

Bitty HTTP only provides a minimal set of headers.

The following headers are the ones that Bitty HTTP will output:

This example will also show changing the returned status code and redirecting to another page.

AJAX

This example uses some javascript ajax to display the headers. What the script will do is re-request the same page and then add the headers returned to a div on the screen.

Files

FileServer.c

The file server is changed to provide 4 new pages.

/Redirect1.html

Redirect1.html is a simple page that just redirects to Redirect2.html.

/Redirect2.html

Redirect2.html is another simple page that just shows that it was redirected from Redirect1.html by printing it's name

/StatusCode.html

StatusCode.html changes the status code returned and displays it.

/GenericHeader.html

GenericHeader.html adds a custom header to the reply. The page will display the headers that where sent with the page.

void File_Root(struct WebServer *Web); void File_Redirect1(struct WebServer *Web); void File_Redirect2(struct WebServer *Web); void File_StatusCode(struct WebServer *Web); void File_GenericHeader(struct WebServer *Web); void File_Display(struct WebServer *Web); void File_SomeStyle(struct WebServer *Web); void File_Quit(struct WebServer *Web); struct FileInfo m_Files[]= { /* Filename, Dynamic, Cookies, Gets, Posts, Callback */ {"/",true,NULL,NULL,NULL,File_Root}, {"/Redirect1.html",true,NULL,NULL,NULL,File_Redirect1}, {"/Redirect2.html",true,NULL,NULL,NULL,File_Redirect2}, {"/StatusCode.html",true,NULL,NULL,NULL,File_StatusCode}, {"/GenericHeader.html",true,NULL,NULL,NULL,File_GenericHeader}, {"/SomeStyle.css",false,NULL,NULL,NULL,File_SomeStyle}, {"/quit.html",true,NULL,NULL,NULL,File_Quit}, };

The new pages Redirect1.html, Redirect2.html. StatusCode.html, and GenericHeader.html have been added.

const char RootHTML[]= "<!DOCTYPE html>" "<html>" "<head>" "<title>Bitty HTTP - Root</title>" "<link rel='stylesheet' href='/SomeStyle.css'>" "</head>" "<body>" "<div id='top'>Bitty HTTP Example - Root</div>" "<div id='quitbttn'><a href='/quit.html'>QUIT</a></div>" "<div id='content'>" "Headers example<br/>" "<br/>" "This is the main page.<br/>" "<a href='/Redirect1.html'>Redirect Test</a><br/>" "<a href='/StatusCode.html'>Status Code Test</a><br/>" "<a href='/GenericHeader.html'>Generic Header Test</a><br/>" "</div>" "<div id='bottom'></div>" "</body>" "</html>";

The root page has been changed to a number of links to the new pages.

const char Redirect1HTML[]= "<!DOCTYPE html>" "<html>" "<head>" "<title>Bitty HTTP - Root</title>" "<link rel='stylesheet' href='/SomeStyle.css'>" "</head>" "<body>" "<div id='top'>Bitty HTTP Example - Root</div>" "<div id='quitbttn'><a href='/quit.html'>QUIT</a></div>" "<div id='content'>" "Headers example.<br/>" "<br/>" "<h1>Redirect 1</h1>" "</div>" "<div id='bottom'></div>" "</body>" "</html>"; void File_Redirect1(struct WebServer *Web) { WS_Location(Web,"/Redirect2.html"); WS_WriteWhole(Web,Redirect1HTML,sizeof(Redirect1HTML)-1); }

This is the first page of the redirect example. In the code for this page we first call WS_Location() with the URL we want to redirect to. The WS_Location() function adds a Location: header to the output. You must add any headers before outputing any of the body of the page, so in this case we call WS_Location() before using WS_WriteWhole() to output our page.

The WS_Location() function will also change the status code to 301 Moved Permanently

When we load this page the Location: header will redirect us to the /Redirect2.html page

If you want to redirect using a different status code than 301 then you need to output a custom header using WS_Header() and WS_SetHTTPStatusCode() as follows:

WS_Header(Web,"Location: /Redirect2.html"); WS_SetHTTPStatusCode(Web,e_ReplyStatus_TmpRedirect);

Continuing with FileServer.c:

const char Redirect2HTML[]= "<!DOCTYPE html>" "<html>" "<head>" "<title>Bitty HTTP - Root</title>" "<link rel='stylesheet' href='/SomeStyle.css'>" "</head>" "<body>" "<div id='top'>Bitty HTTP Example - Root</div>" "<div id='quitbttn'><a href='/quit.html'>QUIT</a></div>" "<div id='content'>" "Headers example.<br/>" "<br/>" "<h1>Redirect 2</h1>" "</div>" "<div id='bottom'></div>" "</body>" "</html>"; void File_Redirect2(struct WebServer *Web) { WS_WriteWhole(Web,Redirect2HTML,sizeof(Redirect2HTML)-1); }

The next page is a simple page to display that we have been redirected.

const char StatusCodeHTML[]= "<!DOCTYPE html>" "<html>" "<head>" "<title>Bitty HTTP - Status Code</title>" "<link rel='stylesheet' href='/SomeStyle.css'>" "</head>" "<body>" "<div id='top'>Bitty HTTP Example - Status Code</div>" "<div id='quitbttn'><a href='/quit.html'>QUIT</a></div>" "<div id='content'>" "<h1>Status Code</h1>" "Re-requesting page to get the headers (by ajax):<br/>" "<div id='Headers' style='white-space: pre;border:1px solid black;margin:5px;padding:5px;font-family: monospace'></div>" "</div>" "<div id='bottom'></div>" "<script>\n" " var req = new XMLHttpRequest();\n" " req.open('GET', document.location, false);\n" " req.send(null);\n" " var headers = req.getAllResponseHeaders();\n" " var outdiv=document.getElementById('Headers');\n" " outdiv.innerHTML='Status:'+req.status+' '+req.statusText+'\\n\\n'+headers;\n" "</script>\n" "</body>" "</html>"; void File_StatusCode(struct WebServer *Web) { WS_SetHTTPStatusCode(Web,e_ReplyStatus_Forbidden); WS_WriteWhole(Web,StatusCodeHTML,sizeof(StatusCodeHTML)-1); }

This is the set status code example. It uses the WS_SetHTTPStatusCode() function to set the status code to one of the defined return codes. This needs to be called before any of the body is sent.

The system supports the following status codes:

e_ReplyStatus_Ok200
e_ReplyStatus_MovedPerm301
e_ReplyStatus_NotModified304
e_ReplyStatus_TmpRedirect307
e_ReplyStatus_PermRedirect308
e_ReplyStatus_BadRequest400
e_ReplyStatus_Forbidden403
e_ReplyStatus_NotFound404
e_ReplyStatus_MethodNotAllowed405
e_ReplyStatus_URITooLong414
e_ReplyStatus_RequestHeaderFieldsTooLarge431
e_ReplyStatus_InternalServerError500
e_ReplyStatus_NotImplemented501
e_ReplyStatus_HTTPVersionNotSupported505
e_ReplyStatus_InsufficientStorage507

It should be noted that the page works by including some javascript that makes a second request to the server for the same page (using AJAX). It does this because there is no way to the status code or headers from javascript without using AJAX

const char GenericHeaderHTML[]= "<!DOCTYPE html>" "<html>" "<head>" "<title>Bitty HTTP - Generic Header</title>" "<link rel='stylesheet' href='/SomeStyle.css'>" "</head>" "<body>" "<div id='top'>Bitty HTTP Example - Generic Header</div>" "<div id='quitbttn'><a href='/quit.html'>QUIT</a></div>" "<div id='content'>" "<h1>Generic Header</h1>" "Re-requesting page to get the headers (by ajax):<br/>" "<div id='Headers' style='white-space: pre;border:1px solid black;margin:5px;padding:5px;font-family: monospace'></div>" "</div>" "<div id='bottom'></div>" "<script>\n" " var req = new XMLHttpRequest();\n" " req.open('GET', document.location, false);\n" " req.send(null);\n" " var headers = req.getAllResponseHeaders();\n" " var outdiv=document.getElementById('Headers');\n" " outdiv.innerHTML='Status:'+req.status+' '+req.statusText+'\\n\\n'+headers;\n" "</script>\n" "</body>" "</html>"; void File_GenericHeader(struct WebServer *Web) { WS_Header(Web,"X-Powered-By: Imagination"); WS_WriteWhole(Web,GenericHeaderHTML,sizeof(GenericHeaderHTML)-1); }

This example shows adding a generic header string. The WS_Header() function takes the string to output this string it output in the HTTP headers with a newline appended to the end of the string. This must be called before any body is output.