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:
- Transfer-Encoding
- Server
- Content-Length
- ETag
- Location
- Set-Cookie
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_Ok | 200 |
e_ReplyStatus_MovedPerm | 301 |
e_ReplyStatus_NotModified | 304 |
e_ReplyStatus_TmpRedirect | 307 |
e_ReplyStatus_PermRedirect | 308 |
e_ReplyStatus_BadRequest | 400 |
e_ReplyStatus_Forbidden | 403 |
e_ReplyStatus_NotFound | 404 |
e_ReplyStatus_MethodNotAllowed | 405 |
e_ReplyStatus_URITooLong | 414 |
e_ReplyStatus_RequestHeaderFieldsTooLarge | 431 |
e_ReplyStatus_InternalServerError | 500 |
e_ReplyStatus_NotImplemented | 501 |
e_ReplyStatus_HTTPVersionNotSupported | 505 |
e_ReplyStatus_InsufficientStorage | 507 |
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.