# 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