Showing posts with label httpd. Show all posts
Showing posts with label httpd. Show all posts

2013-11-22

Writing a C/C++ App run from apache

A few weeks back I started wondering on ways to improve the performance of certain areas of my site (as I do periodically) and while I came across examples of PHP compilers in their many forms, I started wondering if I should just go whole hog and write some parts of the application right in C/C++. Sure, everyone is jumping on nodejs, but I've worked in both C and C++ languages before and while it has been sometime, I thought it might be an interesting exercise to try writing some of the back end processes in either one. After all, I'm running mysql as my db, and there are mysql c headers and api, so it should be fairly straight forward. I found quickly that some of this documentation was lacking. Sure I can create a C/C++ executable that'll give me info from my DB on demand, but getting it back to the requester was being a pain. Digging around and experimenting led me to finding a few things that I'd like to share here.
int MIMEHeader() { 
     cout << "Content-type: text/html" << endl << endl << endl; 
     cout << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"<<endl; 
     cout <<"<HTML xlmns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>" <<endl;
}

int main() {
     MIMEHeader();
     cout<<">head<>/head><body>"<<endl;        
     cout<<"Hello World!"<<endl;    
     cout<<"</body>"<<endl;
     return TRUE;
}
First off, yes, you really do need three "endl"'s on the first line. One finishes the current line and the next to tell apache you really mean that this is html and it should serve it. The next two sets up the doctype and get things ready for you to output your info. Calling this function from our main function causes things to be ready for output. In the example here, we tack on the proverbial "Hello World" example.
The next step here is to get apache to proxy the output of our program to the end user's web browser. You'll need this block in your sections affected.
<Directory "/path/your/website/x">
     AllowOverride None
     Options ExecCGI
     Order allow,deny
     Allow from all
</Directory>
ScriptAlias /x /path/to/your/website/x
In the example, I used /x as my subdir of compiled code. So, resolving it would be "http://example.com/x/programName".

At this point you're good to go, and boy is it FAST. In my non-exhaustive testing, a simple App involving a MySQL query takes less than 1ms more than the actual MySQL query. Obviously, your results may vary. Here's the example C++ I wrote for a start before I started adding more fancy api type features to it. I compiled it on CentOS 5.4 with stock CentOS distributed MySQL 5.1:

// Compile this using:
// g++ -o mysqltest mysqltest.cpp -L/usr/lib64/mysql -lmysqlclient -I/usr/include/mysql && ./mysqltest
//

#include <iostream>
#include <mysql/mysql.h>
using namespace std;
MYSQL *connection, mysql;
MYSQL_RES *result;
MYSQL_ROW row;
int query_state;
int MIMEHeader() {
cout << "Content-type: text/html"<<endl<<endl<<endl<<"<HTML><BODY><PRE>";
}
int Footer() { 
cout << "</PRE></BODY></HTML>";
}
int main() {
char * env;
MIMEHeader();
mysql_init(&mysql);
connection = mysql_real_connect(&mysql,"localhost","myUs3r","myPa55word","myBookmarks",0,0,0);
if (connection == NULL) { 
cout << mysql_error(&mysql) << endl;
return 1;
query_state=mysql_query(connection,"select * from links where id like '%blogger.com';");
if (query_state!=0) {
cout << mysql_error(&mysql) << endl;
                return 1;
}
result = mysql_store_result(connection);
cout << "<table>"<<endl;
while  (( row = mysql_fetch_row(result)) != NULL ) {
cout << "<tr><td>" << row[0] <<"</td><td>"<< row[1] <<"</td><td>"<< row[2] <<"</td></tr>"<<endl;
}
cout << "</table>"<<endl;
Footer();
mysql_free_result(result);
mysql_close(connection);
return 0;
}

2011-11-08

SSLCertificateFile errors in Apache httpd-2.2.21

Apache 2.2.21 is out, so, being the 'on the ball' sys-admin I am, I pulled it down and rolled myself an rpm using rpm build (which I should probably make a post on later). After a few minutes of compiling, I had my spiffy rpm and I was ready to deploy it.
I first pushed it to all of our beta sites as they most closely matched our live servers and got them running in no time with a little 'rpm -Uvh httpd-2.2.21.rpm' command. After a week of that running well, I pushed it to our dev server this morning and ran into a problem... Where I previously had:
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /etc/httpd/conf/ssl.crt/secure_mysite_com.crt
SSLCertificateKeyFile /etc/httpd/conf/ssl.key/secure_mysite_com.key

in our vhost config, it no longer allowed me to start httpd. Looked in the error log and I found:
[Tue Nov 08 09:38:46 2011] [error] Server should be SSL-aware but has no certificate configured [Hint: SSLCertificateFile] ((null):0)

Of course my first response was "But I DO!". I dug around and found many places where it was defined, always correct. After paring down our long list of vhosts a bit, I was able to get one to work. Apparently it had the following lines:
SSLEngine on
SSLCipherSuite HIGH:!SSLv2:!ADH:!aNULL:!eNULL:!NULL
SSLProtocol -ALL +SSLv3 +TLSv1
SSLCertificateFile /etc/httpd/conf/ssl.crt/secure_mysite_com.crt
SSLCACertificateFile /etc/httpd/conf/ssl.crt/intermediate_bundle.crt
SSLCertificateKeyFile /etc/httpd/conf/ssl.key/secure_mysite_com.key

I don't know why I had to explicitly define my CACert on top of the others, but this made it happy and I was able to go along my way!

I found out after rolling this to a few other servers that it's also hypersensitive to Vhosts that are on port 443 but don't have ssl configs. Make sure you have the above lines or an include file with them in every vhost you have configured to run on port 443!