Lsapi api

jrmarino

Well-Known Member
#1
I seem to recall that the original intent for LSAPI is that it would be an alternative to the fastcgi protocol.

How is this effort going? Will LSAPI be documented and available for use for our own executable programs? It seem this has stalled and that's a shame, I'm sure people are interested in this.
 

jrmarino

Well-Known Member
#3
you misunderstood the question.

You publish PHP-LSAPI and Ruby-LSAPI. We all know that.

However, you guys said that you would publish the API for LSAPI so that we could use it for our own applications. E.g. for things other than PHP and Ruby. This was mentioned long ago as a goal. I see no movement in this goal.

Do you now understand what I am asking about?
 
Last edited:

mistwang

LiteSpeed Staff
#4
You can use our PHP-LSAPI and Ruby-LSAPI code as an example. All client side code is open, the API is pretty much like FCGI, we can provide a simple sample code like the "echo" FCGI example.

We do not spend much time to push it as an third party integration API as there is not much interest in it even though the code is completely open, pretty much all are internal development.
 

jrmarino

Well-Known Member
#5
yeah, I knew I could dig around the php-lsapi code.

I think there "is not much interest" because it has never been published and documented. If somebody spent the time to properly document the API, then people would consider using it.

Given the benchmarks that nitewave just linked to, why would people not be interested in using it over fastcgi? Certainly if they are already litespeed clients, but perhaps promoting LSAPI for any application might result in new ones. It's a distinguishing feature that sets litespeed apart.

I personally think it would be worth litespeedstech's time to document it properly. I wouldn't think it would change much, so it should be a minimal effort to maintain once it was written. If it turns out nobody cares, it didn't cost much (a few hours time?), and it could potentially be very interesting to prospective clients.
 

mistwang

LiteSpeed Staff
#8
LSAPI is pretty much like FCGI API, below is a simple example, which is like FCGI echo example, it shows you how to access request header, request body, create its own listener socket, etc. Just link it with lsapilib.c .

All the API functions are in lsapilib.h, it is easy to figure out what a function does from the function name. And code is open, it should be easy to figure out any thing.


Code:
#include <lsapilib.h>

#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

typedef struct
{
    char * pBuf;
    char * pBufEnd;
    char * pCur;
}Buff;

int PrintEnv( const char * pKey, int keyLen, const char * pValue, int valLen,
                void * arg )
{
    int len;
    Buff * buf = (Buff *)arg;
    buf->pCur += snprintf( buf->pCur,
                buf->pBufEnd - buf->pCur, "%s=%s\n", pKey, pValue );
    len = buf->pCur - buf->pBuf;
    if ( len > 4096 )
    {
        if ( LSAPI_Write( buf->pBuf, len ) < len )
            return -1;
        buf->pCur = buf->pBuf;
    }
    return 1;             
}

int processReq( int *count )
{
    int i = 0, l;
    int len;
    int n;
    char achBuf[8192];
    char * p = achBuf;
    char * pEnd = &achBuf[8192];
    Buff buf;
    char achHeader[] = "Content-type: text/html";
    char achHeader2[] = "X-Powered-by: LSAPI";

    len = LSAPI_GetReqBodyLen();

    /* response header should be added one by one */
    LSAPI_AppendRespHeader( achHeader, sizeof( achHeader ) - 1 );
    LSAPI_AppendRespHeader( achHeader2, sizeof( achHeader2 ) - 1 );

    p += snprintf( p, pEnd - p, 
            "<title>LSAPI echo</title>"
            "<h1>LSAPI echo</h1>\n"
            "Request number %d,  Process ID: %d<p>\n"
            "Request environment:<br>\n<pre>", ++(*count), getpid());
            
    buf.pBuf = achBuf;
    buf.pBufEnd = pEnd;
    buf.pCur = p;

    /*Write a error message to STDERR stream */
    char *pErr = "this is a error message send to STDERR.";
    LSAPI_Write_Stderr( pErr, strlen( pErr ) );
        
    if ( LSAPI_ForeachHeader( PrintEnv, &buf ) == -1 )
    {
        return -1;
    }

    if ( LSAPI_ForeachEnv( PrintEnv, &buf ) == -1 )
    {
        return -1;
    }
            
    p = buf.pCur;
    if (len <= 0)
    {
        p += snprintf( p, pEnd - p, "No data from standard input.<p>\n" );
    }
    else
    {
        p += snprintf(p, pEnd - p, "Standard input:<br>\n<pre>\n");
        if ( LSAPI_Write( achBuf, p - achBuf ) < p - achBuf )
            return -1;
            
        p = achBuf;
        while( i < len )
        {
            n = len - i;
            if ( n > sizeof( achBuf ) )
                n = sizeof( achBuf );
            l = LSAPI_ReadReqBody( achBuf, n );
            if ( l == 0 )
            {
                p += snprintf(p, pEnd-p,
                    "\nERROR: Error occured before enough bytes received on standard input<p>\n");
                break;
            }
            if ( l < 0 )
            {
                p += snprintf(p, pEnd-p,
                        "\nERROR: Read failed before enough bytes of request body received<p>\n");
                break;
            }
            i += l;
            if ( LSAPI_Write( achBuf, l ) < l )
                return -1;
        }
        p += snprintf(p, pEnd - p, "\n</pre><p>\n");
    }
    
    if ( p > achBuf )
    {
        if ( LSAPI_Write( achBuf, p - achBuf ) < p - achBuf )
            return -1;
    }
    
    LSAPI_Finish();

    return 0;
}

int processHello( )
{
    int len;
    char achHeader[] = "Content-type: text/html";

    len = LSAPI_GetReqBodyLen();

    /* response header should be added one by one */
    LSAPI_AppendRespHeader( achHeader, sizeof( achHeader ) - 1 );
    char achMessage[] = "Hello, World";
    if ( LSAPI_Write( achMessage, sizeof( achMessage ) - 1 )
                < sizeof( achMessage ) - 1 )
        return -1;


    LSAPI_Finish();

    return 0;
}

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

int main(int argc, char *argv[])
{
    LSAPI_Request req;
    int count = 0;
    int fd;

    if ( argc > 1 )
    {
        fd = LSAPI_CreateListenSock( argv[1], 10 );
    }
    
    LSAPI_Init();
    LSAPI_InitRequest( &req, fd );

    LSAPI_Init_Prefork_Server( 10, select, 0 );
    
    while( LSAPI_Prefork_Accept_r( &req ) >= 0 )
    {
        if ( processReq( &count ) == -1 )
            return 1;
        if ( count >= 10000 )
            break;
    }

/* Hello world example */
/* 
    LSAPI_Init();
    while( LSAPI_Accept() >= 0 )
    {
        if ( processHello() == -1 )
            return 1;
    }
*/    
    return EXIT_SUCCESS;
}
Python integration has not been done yet. It is on our to-do list.
 

jrmarino

Well-Known Member
#9
Okay, thanks.

I may use LSAPI with Ada. If I am able to do so cleanly, I'll publish the code and maybe some documentation. No promises, and it's not immediately on my list of things to do.
 
Top