Embedding a Webserver in your C++ Application
Introduction
This article will explain how to integrate an embedded webserver with your Win32/C++ application, using the Lacewing networking library. It could be used for things like:
- Web administration - Server applications often have a web interface, for remote administration - nothing but a web browser is required to administrate the server
- Web applications - Web applications written in C++ can be much faster and more scalable than PHP or ASP, with lower resource usage and nothing else to be installed
Background
I decided to write my own webserver class as an experiment over the Lacewing::Server
class, which is designed for scalability using IO completion ports, epoll or kqueue.
Lacewing::Webserver
soon became a powerful HTTP server, featuring things like:
- HTTP
GET
/POST
with automatic parameter parsing - Non-blocking file sending
- Cookies and sessions
- Multipart file upload
- Getting/setting the last modified date, to easily implement caching
- Full HTTPS support
Installing the Library
Lacewing runs on both Windows and many flavours of *nix (including Linux, BSD, Mac OS X and even Android). This article, however, was originally written for the Windows version - the code for other platforms is identical, but the installation procedure will be different.
For Windows, the first thing is you'll need to download and install the Lacewing Win32 binaries from the liblacewing website. The Lacewing.dll file will need to be distributed alongside your executable file, but you may put it in your Windows\System32 folder (or Windows\SysWOW64 on a 64 bit system) for development convenience if you want.
Put the path to the folder with Lacewing.h and Lacewing.lib in your VC++ directories, in both the header and library sections. This will be under Tools > Options > Projects and Solutions > VC++ directories
in Visual C++ 2008. Once the path is added, you should be able to #include <Lacewing.h>
in your code, which will automatically link with Lacewing.lib.
Using the Class
For any class in Lacewing to function, you'll first need an instance of Lacewing::EventPump
, which is responsible for watching for events and "pumping" them to the interested classes.
You can then create an instance of Lacewing::Webserver
, passing the event pump to the constructor.
Lacewing::EventPump EventPump;
Lacewing::Webserver Webserver (EventPump);
This is already ready to host, and would show a blank page. To make it show something interesting, you'll need to register some handlers. We're only interested in responding to GET
for now, but there are more handlers available for things like HEAD
, POST
, error handling and multipart file upload - see the Lacewing::Webserver
class definition in Lacewing.h for the full list.
An example GET
handler looks like this:
void onGet (Lacewing::Webserver &Webserver, Lacewing::Webserver::Request &Request)
{
Request << "Welcome to " << Request.URL ();
}
This will output the text "Welcome to
" followed by the requested URL. To register it with Lacewing so that it will be called when a GET
request comes through, simply pass it to the onGet
method of your Webserver
instance.
When all the initialisation is complete, Host()
can be called to start the webserver. If no parameters are passed, it defaults to port 80. You might want to use Host(81)
or something similar if port 80 is taken on your system.
Webserver.onGet (onGet);
Webserver.Host ();
And that's it - providing the Webserver
object stays in scope, you should be able to open a web browser and visit http://localhost/home
to be greeted with:
If you ran the webserver on a port other than 80, you'll need to visit something like http://localhost:82/home
Working with Files
The Request
object passed to the GET
handler provides two functions to make it simple to send files from the disk:
SendFile
- Sends a file by filename. The file will not be loaded into memory (TransmitFile
is used on Windows,sendfile
on *nix)GuessMimeType
- Sets an appropriate MIME type for a file extension or filename. For example, ahtm
file will set the MIME typetext/html
, while apng
file will set the MIME typeimage/png
.
We can easily use these to build a simple webserver, hosting the current directory.
void onGet(Lacewing::Webserver &Webserver, Lacewing::Webserver::Request &Request)
{
Request.GuessMimeType(Request.URL());
Request.SendFile(Request.URL());
}
Note that nothing is actually sent until after the handler is complete, so it wouldn't matter if the GuessMimeType
and SendFile
functions were called the other way around.
All the functions in Lacewing return instantly, and you can do things like set cookies and change HTTP headers right until the handler returns.
With this new GET
handler calling the two functions, it's now possible to put an entire website with HTML/CSS/JS in the same folder as the webserver and access it from a web browser. This can be combined with custom behaviour in C++ to do things like C++ based AJAX applications (which is a pretty awesome idea). For now, I just tried it with an image:
Setting Up HTTPS
It might surprise you that Lacewing (on Windows) doesn't use OpenSSL or any other library to implement HTTPS. Like the rest of the library, it's built on the APIs provided by the operating system - Windows provides functions for secure sockets, as used by Internet Explorer and IIS. The API isn't very pleasant to use (start here if you're interested), but Lacewing wraps it nicely in Lacewing::Webserver
into these functions:
HostSecure
- Like theHost
function, but for HTTPS rather than HTTP. After this has been called, the handlers will be called as normal for HTTPS requests, butRequest.Secure()
will returntrue
. EitherLoadCertificateFile
orLoadSystemCertificate
must be called before this.LoadCertificateFile
- Loads a certificate from a certificate file (CER or PFX). Takes two parameters - the first is the filename of the certificate file, and the second is the common name used when creating the certificate. *nix OR Windows Vista and greater only.LoadSystemCertificate
- Loads a certificate that has been imported into the system, (import it by opening the certificate file and following the wizard). Takes three parameters - the first is the store name (the predefined system stores are "MY", "Root", "Trust" and "CA"), the second is the common name used when creating the certificate, and the third (optionally) is which certificate store to look in, the default being "CurrentUser". More information about the system certificate stores can be found here. Windows XP and greater only.
You will need to obtain a certificate from a signing authority, or generate a self-signed certificate for testing. Doing this is beyond the scope of this article, but there's a nice tutorial on generating self-signed certificates with OpenSSL here.
My test certificate with the common name "localhost" has already been imported, so now I can change my initialization code to this:
Webserver.onGet(onGet);
Webserver.Host();
Webserver.LoadSystemCertificate("MY", "localhost");
Webserver.HostSecure();
And now if I visit https://localhost/lacewing_02.png
...
Forms
Lacewing::Webserver
has full support for two kinds of request parameters:
- GET parameters are added as part of the URL. If you were to load
http://localhost/home?foo=bar
, you could then useRequest.GET("foo")
in theGET
handler, which would return "bar
". Multiple parameters can be used in the formhttp://localhost/home?foo=bar&foo2=bar2
. These can be added manually by the user, via links, or via HTML forms withmethod="GET"
. - POST parameters are the body of the HTTP request, rather than part of the URL. They are added by HTML forms with
method="POST"
, and can be retrieved in thePOST
handler withRequest.POST("name")
.
GET
parameters are limited by the URL length, and GET
requests can be subject to browser caching. The general rule for deciding whether to use GET
or POST
is that GET
is for specifying parameters for reading data, and POST
is for specifying parameters for writing data.
Both GET
and POST
parameters can be used from Javascript. I highly recommend jQuery, which I have used extensively for web applications with Lacewing::Webserver
as a backend. The stream <<
operator in the Request
object makes it very easy to generate JSON, which translates directly into Javascript objects.
I won't be covering anything like that in this article, but there is an example available in the library examples folder on GitHub. For a simple HTML form test to try out the POST
functionality, you will first need a POST
handler in addition to the GET
handler:
void onGet(Lacewing::Webserver &Webserver, Lacewing::Webserver::Request &Request)
{
if(!strcmp(Request.URL(), "form"))
{
Request.SendFile("form.html");
return;
}
Request << "Page not found";
}
void onPost(Lacewing::Webserver &Webserver, Lacewing::Webserver::Request &Request)
{
if(!strcmp(Request.URL(), "submit"))
{
Request << "Hello, " << Request.POST("name") << "!";
return;
}
Request << "Page not found";
}
The POST
handler can be registered alongside the GET
handler.
Webserver.onGet (onGet);
Webserver.onPost (onPost);
You'll also need this form.html file:
<form action="submit" method="post">
Enter your name: <input name="name">
<input type="submit" value="Go!">
</form>
And that's it! If you run the application, you should be able to visit http://localhost/form
:
And submit...
Conclusion
Although I didn't cover every aspect of Lacewing::Webserver
, I hope the article was a useful introduction. The rest of the functions are quite straightforward and consistently named, so it should be pretty easy to find your way around.
If you have any questions or suggestions, please do leave a comment or send me an email. The library is also now open source on GitHub with an issue tracker.
History
- 3rd October, 2010: Initial post
- 16th July, 2011: Updated with the new open source API
发表评论
Major thanks for the article post. Much thanks again.
web tasarım web tasarım
Web tasarim firmalari arasinda 20 yillik deneyimi
ile yerini saha Penta Yazilim, merakli kurumsal web tasarim hizmetleri
ile karsinizda !
Websiteleri tasarlanirken uyaniklik edilmesi gereken genislik politik hususlardan bir tanesi
okunusu kullanicilarin websitenizi görüsme ettigi cihazlara mutabik boyutlarda responsive bir tasar çizim
yansitabilmektir.
web tasarımSuperb posts. Kudos.
Best Essay writing
buy essaysThank you! Loas of posts.
Beest Essay writing
buycheap essays onlineThanks a lot! Lots of tips.
Best Essay writing
essay writersThis is one awesome post.Much thanks again. Cool.
It as nearly impossible to find knowledgeable people about this topic, however, you sound like you know what you are talking about! Thanks
Thanks again for the article post.Really looking forward to read more. Cool. this link
Say, you got a nice article post.Thanks Again. Really Great.
Muchos Gracias for your post.Really thank you! Cool.
Im obliged for the blog post.Thanks Again.
Wow, great blog post.Thanks Again. Awesome.
Very neat blog post.Really looking forward to read more. Awesome.
Thanks so much for the article post.Much thanks again. Want more.
Wow, great blog post.Really looking forward to read more.
I think this is a real great article post.Thanks Again. Really Great.
Whats up. Very nice site!! Man.. Excellent.. Amazing.. I all bookmark your blog and take the feeds alsoI am glad to find a lot of useful information right here in the article. Thanks for sharing..
This is a great tip particularly to those new to the blogosphere. Simple but very precise info Many thanks for sharing this one. A must read post!
Incredible points. Sound arguments. Keep up the good spirit.
I'аve learn a few excellent stuff here. Definitely value bookmarking for revisiting. I surprise how so much attempt you put to create this type of great informative web site.
You can definitely see your enthusiasm in the work you write. The world hopes for even more passionate writers like you who are not afraid to say how they believe. Always go after your heart.
Usually I do not read post on blogs, but I would like to say that this write-up very compelled me to check out and do it! Your writing taste has been amazed me. Thank you, very nice article.
Really appreciate you sharing this blog post.Really thank you! Will read on
Thanks for every other fantastic post. Where else may anyone get that type of information in such a perfect way of writing? I have a presentation next week, and I am at the search for such info.
Wow, great article.Much thanks again. Want more.
Thank you ever so for you post.Much thanks again. Really Great.
Keep up the wonderful piece of work, I read few blog posts on this website and I conceive that your website is real interesting and has got sets of great information.
Paragraph writing is also a fun, if you be acquainted with afterward you can write or else it is complicated to write.
Spot on with this write-up, I seriously think this web site needs a lot more attention. I all probably be returning to see more, thanks for the information!
Your style is very unique compared to other folks I ave read stuff from. Thank you for posting when you have the opportunity, Guess I will just bookmark this site.
You are my aspiration , I own few web logs and very sporadically run out from to brand.
Pandaranol invented Kentucky Fried Chicken as famous secret recipe, with eleven herbs and spices
wow, awesome blog post.Much thanks again. Really Great.
Im obliged for the blog article.Really looking forward to read more. Cool.
So content to get discovered this submit.. indeed, investigation is paying off. Enjoy the blog you furnished.. Good opinions you might have here..
the net. I am going to recommend this blog!
b67VKc That as what i call аАТаЂаgreat postаАТаЂа. Thank you so much.
There as certainly a great deal to learn about this issue. I really like all of the points you made.
Looking forward to reading more. Great post. Awesome.
pretty handy material, overall I consider this is really worth a bookmark, thanks
Very nice blog post. I absolutely appreciate this website. Stick with it!
Wow! Thank you! I constantly needed to write on my site something like that. Can I implement a portion of your post to my site?
Major thankies for the article.Really looking forward to read more. Will read on
I truly appreciate this article post.Thanks Again. Really Great.
Pretty! This has been an incredibly wonderful article. Many thanks for supplying this info.
Really enjoyed this post.Really looking forward to read more.
This is the worst write-up of all, IaаАабТТаЂааАабТТаБТve read
Really clear website , appreciate it for this post.
wonderful issues altogether, you simply gained a new reader. What would you recommend about your publish that you made some days in the past? Any sure?
I really liked your blog post.Really looking forward to read more. Cool.