Register a function to proxy requests for a method/protocol combination
typedef void *Ns_OpContext; typedef int (Ns_OpProc) (void *context, Ns_Conn *conn); typedef void (Ns_OpDeleteProc) (void *context); void Ns_RegisterProxyRequest( char *hServer, char *method, char *protocol, Ns_OpProc *proc, Ns_Callback *deleteProc, void *context );
The Ns_RegisterProxyRequest function registers function proc to handle HTTP requests. When the specified virtual server receives a proxy request, it finds the appropriate registered function.
The virtual server passes your procedure the context you specify here and the Ns_Conn structure associated with the new HTTP connection.
When a procedure is unregistered with either Ns_UnRegisterProxyRequest, the server calls the deleteProc with the same context. You can use this to do any cleanup you might require (e.g., close an index file or free something from the heap). If the value of deleteProc is NULL, the server does nothing.
/* This is a very basic http proxy module that demonstrates the use of Ns_RegisterProxyRequest. Note that this module supports only the GET method because it uses Ns_FetchURL. */ #include "ns.h" #include <stdio.h> #include <stdlib.h> #include <string.h> DllExport int Ns_ModuleVersion = 1; int http_proxy(void *context, Ns_Conn *conn); int http_proxy(void *context, Ns_Conn *conn) { Ns_DString ds, data; int counter; char *c; Ns_Set *headers; unsigned int port = conn->request->port; headers = Ns_SetCreate("headers"); if (port == 0) { port=80; } Ns_DStringInit(&ds); Ns_DStringInit(&data); if (!conn->request->query || strlen(conn->request->query)==0) /* build a URL not including a GET style query */ Ns_DStringPrintf(&data, "%s://%s:%d%s", conn->request->protocol, conn->request->host, port, conn->request->url); else /* build a URL with a GET style query */ Ns_DStringPrintf(&data, "%s://%s:%d%s?%s", conn->request- >protocol, conn->request->host, port, conn->request->url, conn->request->query); Ns_Log(Notice, "Proxying: GET %s", data); /* The the web page from wherever */ if (Ns_FetchURL(&ds, Ns_DStringValue((&data)), headers) == NS_OK) { /* Output what was returned... * Ns_FetchURL returns the status line as the new name * of the headers set it is passed, so output that first. */ Ns_ConnWrite(conn, Ns_SetName(headers), strlen(Ns_SetName(headers))); /* Now iterate through the headers structure and print out all of the * output headers */ for (counter = 0; counter < Ns_SetSize(headers); counter++) { c = Ns_SetKey(headers, counter); Ns_ConnWrite(conn, c, strlen(c)); Ns_ConnWrite(conn, ": ", 2); c = Ns_SetValue(headers, counter); /* This has a newline in it already */ Ns_ConnWrite(conn, c, strlen(c)); /* so no need to add one myself */ } Ns_ConnWrite(conn, "\r\n", 2); /* This blank means no more headers */ /* Now spit out the HTML... */ Ns_ConnWrite(conn, Ns_DStringValue((&ds)), Ns_DStringLength((&ds))); } else { Ns_ConnReturnAdminNotice(conn, 400, "Could not proxy", "An error was encountered while attempting to proxy your request."); } Ns_DStringFree(&data); Ns_DStringFree(&ds); return NS_OK; } DllExport int Ns_ModuleInit (char * hServer, char *hModule) { Ns_RegisterProxyRequest(hServer, "GET", "http", http_proxy, NULL, NULL); return NS_OK; }