# uname -a
FreeBSD bsd91-test 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243825: Tue Dec 4 09:23:10 UTC 2012 root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64
Install nginx:
# cd /usr/ports/www/nginx
# make config-recursive
# make install clean
Install FastCGI Development Kit
# cd /usr/ports/www/fcgi
# make config-recursive
# make install
Install spawn-fcgi
# cd /usr/ports/www/spawn-fcgi
# make config-recursive
# make install
Check the version of the installed ports:
# pkg_info | grep -iE 'cgi|nginx'
fcgi-devkit-2.4.0 FastCGI Development Kit
nginx-1.4.1,1 Robust and small WWW server
spawn-fcgi-1.6.3 spawn-fcgi is used to spawn fastcgi applications
Edit nginx.conf
# vim /usr/local/etc/nginx/nginx.conf
server {
listen 80;
server_name testcgi.local;
location / {
# host and port to fastcgi server
root /home/srv/bsd-mon/nginx/testcgi.local;
index index.html;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params; # need this line, or query string will be empty.
#fastcgi_index index.php;
}
}View a list of fastcgi parameters:
# cat /usr/local/etc/nginx/fastcgi_params
Create the www directory:
# mkdir -p /home/srv/bsd-mon/nginx/testcgi.local
Start nginx:
# /usr/local/etc/rc.d/nginx start
Hello World Example:
# vim hello.c
#include "fcgi_stdio.h"
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] )
{
while( FCGI_Accept() >= 0 )
{
printf("Content-type: text/html; charset=UTF-8\n");
printf("Status: 200 OK\n");
printf("\n");
printf("<br>Hello world in C");
printf("<br>HTTP_HOST: %s\n", getenv("HTTP_HOST"));
printf("<br>HTTP_CONNECTION: %s\n", getenv("HTTP_CONNECTION"));
//printf("<br>HTTP_CACHE_CONTROL: %s\n", getenv("HTTP_CACHE_CONTROL"));
printf("<br>HTTP_ACCEPT: %s\n", getenv("HTTP_ACCEPT"));
printf("<br>HTTP_USER_AGENT: %s\n", getenv("HTTP_USER_AGENT"));
printf("<br>HTTP_ACCEPT_ENCODING: %s\n", getenv("HTTP_ACCEPT_ENCODING"));
printf("<br>HTTP_ACCEPT_LANGUAGE: %s\n", getenv("HTTP_ACCEPT_LANGUAGE"));
//printf("<br>PATH: %s\n", getenv("PATH"));
//printf("<br>SystemRoot: %s\n", getenv("SystemRoot"));
//printf("<br>COMSPEC: %s\n", getenv("COMSPEC"));
//printf("<br>PATHEXT: %s\n", getenv("PATHEXT"));
//printf("<br>WINDIR: %s\n", getenv("WINDIR"));
//printf("<br>SERVER_SIGNATURE: %s\n", getenv("SERVER_SIGNATURE"));
//printf("<br>SERVER_SOFTWARE: %s\n", getenv("SERVER_SOFTWARE"));
printf("<br>SERVER_NAME: %s\n", getenv("SERVER_NAME"));
printf("<br>SERVER_ADDR: %s\n", getenv("SERVER_ADDR"));
printf("<br>SERVER_PORT: %s\n", getenv("SERVER_PORT"));
printf("<br>REMOTE_ADDR: %s\n", getenv("REMOTE_ADDR"));
printf("<br>DOCUMENT_ROOT: %s\n", getenv("DOCUMENT_ROOT"));
//printf("<br>SERVER_ADMIN: %s\n", getenv("SERVER_ADMIN"));
//printf("<br>SCRIPT_FILENAME: %s\n", getenv("SCRIPT_FILENAME"));
printf("<br>REMOTE_PORT: %s\n", getenv("REMOTE_PORT"));
printf("<br>GATEWAY_INTERFACE: %s\n", getenv("GATEWAY_INTERFACE"));
printf("<br>SERVER_PROTOCOL: %s\n", getenv("SERVER_PROTOCOL"));
printf("<br>REQUEST_METHOD: %s\n", getenv("REQUEST_METHOD"));
printf("<br>QUERY_STRING: %s\n", getenv("QUERY_STRING"));
printf("<br>REQUEST_URI: %s\n", getenv("REQUEST_URI"));
printf("<br>SCRIPT_NAME: %s\n", getenv("SCRIPT_NAME"));
//printf("<br>REQUEST_TIME_FLOAT: %s\n", getenv("REQUEST_TIME_FLOAT"));
//printf("<br>REQUEST_TIME: %s\n", getenv("REQUEST_TIME"));
}
return 0;
}
Compile and link against fcgi library
# gcc -o hello hello.c -I/usr/local/include -L/usr/local/lib -lfcgi
Run the code using spawn-cgi:
# spawn-fcgi -a127.0.0.1 -p9000 -n ./hello
Or you can try to run the code using:
# cgi-fcgi -start -connect 127.0.0.1:9000 ./hello
Edit C:\Windows\System32\drivers\etc\hosts
192.168.0.128 testcgi.local
Use browser
Go to http://testcgi.local/index.html?q1=q1&q2=q2
Output:
Hello world in C
HTTP_HOST: testcgi.local
HTTP_CONNECTION: keep-alive
HTTP_ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_USER_AGENT: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36
HTTP_ACCEPT_ENCODING: gzip,deflate,sdch
HTTP_ACCEPT_LANGUAGE: en-US,en;q=0.8
SERVER_NAME: testcgi.local
SERVER_ADDR: 192.168.0.128
SERVER_PORT: 80
REMOTE_ADDR: 192.168.0.121
DOCUMENT_ROOT: /home/srv/bsd-mon/nginx/testcgi.local
REMOTE_PORT: 3791
GATEWAY_INTERFACE: CGI/1.1
SERVER_PROTOCOL: HTTP/1.1
REQUEST_METHOD: GET
QUERY_STRING: q1=q1&q2=q2
REQUEST_URI: /index.html?q1=q1&q2=q2
SCRIPT_NAME: /index.html
FastCGI libfcgi HTTP GET and POST requests example:
/*
* fastcgi_http_get_post_sample.c - FastCGI libfcgi HTTP GET and POST requests example.
* Compile with: gcc -Wall -I/usr/local/include -L/usr/local/lib -lfcgi fastcgi_http_get_post_sample.c -o fastcgi_http_get_post_sample
*
* This link contains documentation for most public functions: http://www.fastcgi.com/devkit/include/fcgiapp.h.
*
* Download the "Development Kit" which includes a C library implementation of FastCGI and C/C++ examples. The library is very easy to learn, so you should be up and running quickly. Read the fcgiapp.h file to get going. http://www.fastcgi.com/drupal/node/5.
*
* Reference: https://code.google.com/p/c-obix-tools/
* Reference: https://code.google.com/p/c-obix-tools/source/browse/trunk/diem/CoT/src/server/obix_fcgi.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcgiapp.h>
char* obix_fcgi_readRequestInput(FCGX_Request* request);
void handle_request(FCGX_Request *request);
#define printf(...) FCGX_FPrintF(request->out, __VA_ARGS__)
#define get_param(KEY) FCGX_GetParam(KEY, request->envp)
#define LISTENSOCK_FILENO 0
#define LISTENSOCK_FLAGS 0
int main(void) {
FCGX_Request request;
/* Method 1 */
// Note: If you want to use TCP rather than a unix socket, change the first argument of FCGX_OpenSocket to ":portnum" (i.e. ":2000" -- you need the colon). Then use "fastcgi_pass yourfcgiserver:2000;" in the nginx config.
//
// int sock;
// sock = FCGX_OpenSocket(":2005", 5);
// FCGX_InitRequest(&request, sock, 0);
/* Method 2 */
// Note: edit nginx.conf:
// fastcgi_pass unix:/var/run/myfcgiserver.sock;
// With this, any request to yourserver/fcgi-bin/... will be sent to your fastcgi server.
//
// int sockfd = FCGX_OpenSocket("/var/run/myfcgiserver.sock", 1024);
// FCGX_Init();
// FCGX_InitRequest(&request, sockfd, 0);
/* Method 3 */
// Note: spawn-fcgi -a127.0.0.1 -p9000 -n fastcgi_http_post_sample
//
int err = FCGX_Init(); // call before Accept in multithreaded apps
// if (err) { syslog (LOG_INFO, "FCGX_Init failed: %d", err); return 1; }
err = FCGX_InitRequest(&request, LISTENSOCK_FILENO, LISTENSOCK_FLAGS);
// if (err) { syslog(LOG_INFO, "FCGX_InitRequest failed: %d", err); return 2; }
while (FCGX_Accept_r(&request) >= 0) {
handle_request(&request);
FCGX_Finish_r(&request);
}
return EXIT_SUCCESS;
}
char* obix_fcgi_readRequestInput(FCGX_Request* request)
{
char* buffer = NULL;
int bufferSize = 1024;
int bytesRead = 0;
int error;
do
{
// we start from buffer 2KB
// and than double it's size on every iteration
bufferSize = bufferSize << 1;
buffer = (char*) realloc(buffer, bufferSize);
if (buffer == NULL)
{
//log_error("Not enough memory to read the contents of the request.");
return NULL;
}
bytesRead += FCGX_GetStr(buffer + bytesRead, bufferSize - bytesRead, request->in);
if (bytesRead == 0)
{
//empty input
free(buffer);
return NULL;
}
error = FCGX_GetError(request->in);
if (error != 0)
{
//log_error("Error occurred while reading request input (code %d).", error);
free(buffer);
return NULL;
}
// repeat until buffer is big enough to store whole input
}
while(bytesRead == bufferSize);
// finalize input string
buffer[bytesRead] = '\0';
//log_debug("Received request input (size = %d):\n%s\n", bytesRead, buffer);
return buffer;
}
void handle_request(FCGX_Request *request) {
char *value;
printf("Content-Type: text/html\r\n");
printf("\r\n");
// print the basic environment
printf("<h1>Print the basic environment:</h1>");
if ((value = get_param("REQUEST_METHOD")) != NULL) {
printf("%s ", value);
}
if ((value = get_param("REQUEST_URI")) != NULL) {
printf("%s", value);
}
if ((value = get_param("QUERY_STRING")) != NULL) {
printf("?%s", value);
}
if ((value = get_param("SERVER_PROTOCOL")) != NULL) {
printf(" %s", value);
}
// print out all the environment
printf("<h1>Print out all the environment:</h1>");
char **env = request->envp;
while (*(++env))
{
printf("%s<br>", (*env));
}
// Handle POST request
if (strcmp((value = get_param("REQUEST_METHOD")), "POST") == 0)
{
printf("<h1>Handle POST request:</h1>");
char* input = obix_fcgi_readRequestInput(request);
//obix_server_handlePOST(response, uri, input);
printf("test %s", input);
if (input != NULL)
{
free(input);
}
}
printf("\n");
}HTML form example:
<form action="http://testcgi.local/index.html?q1=q1&q2=q2" method="POST"> <input type="text" name="asdf0" value="ASDF0&ASDF0"> <input type="text" name="asdf1" value="ASDF1"> <input type="submit"> </form>
Reference:
http://www.fastcgi.com/devkit/doc/fastcgi-prog-guide/ch2c.htm#3659
No comments:
Post a Comment