This is a discussion on Apache module in C within the Apache Web Server forums, part of the Web Server and Related Forums category; Hello I'm just getting along with the apache2 modules features and limitations but it seems i can't find ...
|
|||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
|
|||
|
Hello
I'm just getting along with the apache2 modules features and limitations but it seems i can't find a documentation to clear some questions of mine. First of all, I'm trying to make a module that keeps some data persistent in memory between requests, information that can be retrieved lately for a specific request.[something like a connection to something, or just a simple integer var that increments for each request {device, db, doesn't matter} ]. And i wanted to know if it's possible to call a cgi from a module, let's say i have computed the data in the module and i want to send it to a cgi ? If you can point to me some documentation would be great. Thanks in advance |
|
|||
|
sphere wrote:
> First of all, I'm trying to make a module that keeps some data > persistent in memory between requests, information that can be > retrieved lately for a specific request.[something like a connection to > something, or just a simple integer var that increments for each > request {device, db, doesn't matter} ]. You might want to look at either FastCGI or SCGI. FastCGI was an early attempt to overcome the limitations of CGI, but didn't receive much attention after PHP became popular. SCGI is the 'Simple' implementation of the idea. In both cases, mod_scgi or mod_fcgi is added to the Apache configuration. Your server listens on a specified port, and Apache connects to it for specific requests. Each request is processed separately, but the server is persistent and can retain state information. Ruby on Rails has renewed interest in both approaches, both to reduce the costs of starting a new cgi process for every request, and to retain information between requests. I've been using SCGI, which is available at https://www.mems-exchange.org/software/scgi/ . The server in this case is implemented in Python, but you can build and install mod_scgi by itself. Then add a stanza to httpd.conf or elsewhere like: LoadModule scgi_module /usr/lib64/apache2/mod_scgi.so <Location "/scgi-bin"> SCGIServer 127.0.0.1:4000 SCGIHandler On SetHandler scgi-handler </Location> A quick and dirty implementation of the C server: ================================================== =============== #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <errno.h> #include <string.h> #include <arpa/inet.h> #include <unistd.h> #include <ctype.h> typedef struct env { char* label; char* value; struct env* next; } ENV; static size_t read_size(int fd); static int read_data(int fd, char* buf, size_t size); static void free_environment(ENV* env); static ENV* read_environment(char* buf, size_t size); static void print_environ(int fd, ENV* environ); static char* find_value(ENV* environ, char* label); int main(int argc, char** argv) { ENV* environ = NULL; char* buf; int sock_fd; int listen_fd; int port = 4000; size_t size; struct sockaddr_in addr; socklen_t addrlen; char msgbuf[8000]; int on = 1; int iteration = 1; char* value; sock_fd = socket(PF_INET, SOCK_STREAM, 0); if (sock_fd == -1) { fprintf(stderr, "socket failed: %s\n", strerror(errno)); exit(-1); } setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); memset(&addr, 0, sizeof(struct sockaddr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (bind(sock_fd, (struct sockaddr*) &addr, sizeof(struct sockaddr)) == -1) { fprintf(stderr, "bind failed: %s\n", strerror(errno)); exit(-1); } if (listen(sock_fd, 5) == -1) { fprintf(stderr, "listen failed: %s\n", strerror(errno)); exit(-1); } addrlen = sizeof(struct sockaddr); while (1) { fprintf(stderr, "listening on port %d\n", port); listen_fd = accept(sock_fd, (struct sockaddr*) &addr, &addrlen); if (listen_fd == -1) { fprintf(stderr, "accept failed: %s\n", strerror(errno)); exit(-1); } size = read_size(listen_fd); fprintf(stderr, "size: %d\n", (int) size); if (size == -1) { goto exit; } buf = calloc(1, size+32); if (buf == NULL) { fprintf(stderr, "calloc failed: %s\n", strerror(errno)); goto exit; } if (read_data(listen_fd, buf, size) == -1) { goto exit; } fprintf(stderr, "read the data size = %d\n", (int)size); fprintf(stderr, "calling read_environment\n"); environ = read_environment(buf, size); sprintf(msgbuf, "%s", "Content-Type: text/html\r\n\r\n"); write(listen_fd, msgbuf, strlen(msgbuf)); sprintf(buf, "<html><body>\r\n"); write(listen_fd, buf, strlen(buf)); value = find_value(environ, "QUERY_STRING"); sprintf(msgbuf, "iteration %d<br/>value: %s<br/>", iteration++, value); write(listen_fd, msgbuf, strlen(msgbuf)); if (environ) { print_environ(listen_fd, environ); free_environment(environ); } else { fprintf(stderr, "no environ\n"); sprintf(msgbuf, "Hello World from Buddha"); write(listen_fd, msgbuf, strlen(msgbuf)); } sprintf(buf, "</body></html>\r\n"); write(listen_fd, buf, strlen(buf)); close(listen_fd); } exit: close(listen_fd); close(sock_fd); return 0; } static size_t read_size(int fd) { int i = 0; char buf[32]; char c; ssize_t bytes_read; memset(buf, 0, sizeof buf); while (i < sizeof(buf)-1) { bytes_read = read(fd, &c, 1); if (bytes_read == -1) { fprintf(stderr, "read failed: %s\n", strerror(errno)); if (errno == EINTR || errno == EAGAIN) { continue; } return -1; } if (c == ':') { break; } if (!isdigit(c)) { i = 0; memset(buf, 0, sizeof buf); } else { buf[i++] = c; } } return (size_t) atoi(buf); } static int read_data(int fd, char* buf, size_t size) { ssize_t bytes_read = 0; size_t bytes_left = (size_t) size; int index = 0; read(fd, buf, size+31); return 0; while (index < size) { bytes_read = read(fd, &buf[index], bytes_left); if (bytes_read == -1) { fprintf(stderr, "read failed: %s\n", strerror(errno)); if (errno == EINTR || errno == EAGAIN) { continue; } return -1; } index += bytes_read; bytes_left = size - bytes_read; } return 0; } static ENV* read_environment(char* buf, size_t size) { ENV* node; ENV* head = NULL; ENV* tail = NULL; char* label; char* value; char* ptr = buf; char* end = buf + size; while (ptr < end) { label = strdup(ptr); ptr += (strlen(ptr) + 1); value = strdup(ptr); ptr += (strlen(ptr) + 1); node = calloc(1, sizeof(ENV)); if (node == NULL) { fprintf(stderr, "calloc failed: %s\n", strerror(errno)); return NULL; } node->label = label; node->value = value; if (head == NULL) { head = node; tail = node; } else { tail->next = node; tail = node; } } return head; } static void free_environment(ENV* env) { ENV* next; ENV* node = env; while (node) { next = node->next; free(node); node = next; } } static void print_environ(int fd, ENV* environ) { char buf[1024]; ENV* node; for (node=environ; node; node=node->next) { sprintf(buf, "%s: %s<br>", node->label, node->value); write(fd, buf, strlen(buf)); } } static char* find_value(ENV* environ, char* label) { ENV* node; for (node=environ; node; node=node->next) { if (strcasecmp(node->label, label) == 0) { return node->value; } } return ""; } ----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==---- http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups ----= East and West-Coast Server Farms - Total Privacy via Encryption =---- |