I would like to use mechanisms available in AOLserver (nsd/urlspace.c,
nsd/op.c) to define different handlers for different parts of URL
tree. I am particulary interested in:
- directory aliases (see: http://aolserver.com/docs/cdev/c-app2.htm#14874)
- TCL registered procs
- registered ADP (see my TCL command ns_adp_registeradp in AOLserver 4.0)

I would like to use these mechanisms to allow independent TCL modules
to handle parts of URL tree. During request handling I would like to
identify which TCL module handles which url (exactly which instance of
given module). The problem is well described in documentation for ACS
Request Processor, but there they speak about packages and package
instances (http://developer.arsdigita.com/doc/request-processor).

My solution is to add another field to Ns_Conn structure which will be
initialized during request handling to url pattern used to register
the handler. That url pattern (combined with [ns_conn server] and
[ns_conn method]) identifies the handler so I would make it accessible
from TCL by [ns_conn handler]. I suspect that this extention could be
usefull for other purposes as well.

I would like to get advise for the following:
1) Could my problem be solved without patching AOLserver?
2) Does proposed extention seem usefull for anyone?
3) Is there better proposal for implementing that functionality in C?
4) Would my patch be included in AOLserver core ?

Below is my understanding of how AOLserver handles incoming request
and what should be changed.

--- Details ---

AOlserver uses special data structure defined in nsd/urlspace.c to
keep information how to handle incoming request. You can access this
structure using functions like:

void
Ns_UrlSpecificSet(char *server, char *method, char *url, int id, void *data,
                  int flags, void (*deletefunc) (void *))
void *
Ns_UrlSpecificGet(char *server, char *method, char *url, int id)

which allow you to set and retrive data given:
- server: eg. server1
- method: eg. GET/HEAD/POST
- url pattern: eg. *.adp, /myproc, /mytree/*

Their primary usage is to define how aolserver should handle incoming
HTTP requests. This is done by reqistering request handlers:
- FastGet for static files,
- AdpRun for ADP pages
- TclDoOp for TCL registered procs (and ADP pages in AOL 4.0).

// nsd/fastpath.c
Ns_RegisterRequest(server, "GET", "/", FastGet, NULL, NULL, 0);
Ns_RegisterRequest(server, "HEAD", "/", FastGet, NULL, NULL, 0);
Ns_RegisterRequest(server, "POST", "/", FastGet, NULL, NULL, 0);

// nsd/adp.c
Ns_RegisterRequest(server, "GET", map, AdpProc, NULL, NULL, 0);
Ns_RegisterRequest(server, "HEAD", map, AdpProc, NULL,NULL, 0);
Ns_RegisterRequest(server, "POST", map, AdpProc, NULL,NULL, 0);

You can register, get and unregister request handler using the
following procs defined in nsd/op.c:

void
Ns_RegisterRequest(char *server, char *method, char *url, Ns_OpProc *procPtr,
    Ns_Callback *deleteProcPtr, void *arg, int flags)

void
Ns_UnRegisterRequest(char *server, char *method, char *url, int inherit)

void
Ns_GetRequest(char *server, char *method, char *url, Ns_OpProc **procPtrPtr,
    Ns_Callback **deleteProcPtrPtr, void **argPtr, int *flagsPtr)

Notice that Ns_GetRequest is never used in AOLserver core! Its interface
have to be changed in my proposal. Probably the best soultion is to add
Ns_GetRequest2.

$ grep Ns_GetRequest aolserver-3.4/nsd/*

aolserver-3.4/nsd/op.c: * Ns_GetRequest --
aolserver-3.4/nsd/op.c:Ns_GetRequest(char *server, char *method, char *url, Ns_OpProc 
**procPtrPtr,

Incoming request is handled by function Ns_ConnRunRequest (defined in
nsd/op.c) which runs one of registered request handlers.

int
Ns_ConnRunRequest(Ns_Conn *conn)
{
    Req *reqPtr;
    int  status;
    char *server = Ns_ConnServer(conn);

    reqPtr = (Req *) Ns_UrlSpecificGet(server, conn->request->method,
                                       conn->request->url, reqId);
    if (reqPtr == NULL) {
      status = Ns_ConnReturnNotFound(conn);
    } else {
      status = (*reqPtr->procPtr) (reqPtr->arg, conn);
    }
    return status;
}

I propose to add to Req and Ns_Conn definition filed:

char* handler;

Req.handler should be initialized in Ns_RegisterRequest to parameter
url so it could be used in Ns_ConnRunRequest to initialize
Ns_Conn.handler in the following way:

if (reqPtr == NULL) {
   status = Ns_ConnReturnNotFound(conn);
} else {
   // I assume that Req structure won't be freed during request handling
   conn->handler = reqPtr->handler;
   status = (*reqPtr->procPtr) (reqPtr->arg, conn);
}

Maybe it's better to ns_strdup(reqPtr->handler) and to free it later in
NsConnThread in nsd/serv.c. What do you think?

--tkosiak

Reply via email to