LSIAPI web app?

gnois

New Member
#1
First of all, thanks for developing OpenLiteSpeed. It is the best high performance + full featured C++ web server I find.

Suppose I would like to use Openlitespeed LSIAPI to create something similar to
https://github.com/julienschmidt/httprouter
with C/C++ and then build web apps on that.

Is it a feasible idea?
I had read the codes on addon/example and src/modules.
If it is feasible, which example should I develop based on? Any advice is much appreciated.
I notice the addon/example are reregistering their handlers every time HTTP request is received. Why do they not register it once upon module load and be done with it?

Also, is there any relationship between such LSIAPI web app and vhost app? If such LSIAPI module is registered, we no longer need to configure any vhost on Openlitespeed, right?

Many thanks again!
 
Last edited:

lsmichael

Active Member
#2
Hi,

Thanks for your interest in OpenLiteSpeed. I was talking with the developers about this thread during lunch. It's probably best not to build any modules for LSIAPI yet, since it's still in flux.

Also, we're not quite sure what you're trying to do. It seems like the module you're interested in creating would just serve HTTP requests. This is what OpenLiteSpeed does already. What are we missing?

Michael
 
#3
I am actually toying the idea of using C++ to build web applications.

If we look at the server side languages, most choices with vibrant ecosystem are interpreted and dynamically typed, eg: PHP, ruby, nodejs, python.
There are only few compiled and statically typed language for server side which is competitive enough, like ASP.NET, Java (both has huge VM) or Go, D.
And here we have C++ with Openlitespeed which already gave us Evented I/O, TLS, SPDY etc. This is a really compelling platform and there is nothing like it today!

The module that I was referring to is a custom URL router. Openlitespeed already does it, but only expose the programmability to fCGI or LSAPI interpreted languages I guess?
 

lsmichael

Active Member
#4
Right. So you want to expose it to more SAPIs? That's cool, but I can't help but ask why? What would you be hoping to connect it to?

Still, if you want to do it, I'd like to see if someone can help you. Let me see what people say.

m
 
#5
Hi there,

First, let me preface this by saying that our module API is still undergoing changes, so anything that I post here may be changed in the future.

From what I understand, you are asking about implementing your own request handler based on the URL given.
So for example, example.com/index.bar would be handled by a ".bar" handler?

Before I go into an example, you asked about reregistering the handlers each request.
The module I used as an example does this, and basically this allows you to do more involved checks for if you want your module to handle the request(i.e. check the query string, cookies, request body, etc.).
If you want the module to be statically assigned to a specific suffix, after creating and registering the module, on the Web Admin, go to Script Handler and create a new one.
Here, you can specify the suffix to handle and how you want it to be handled (in this case, module handler and your module name).​

If that is the case, I suggest taking a look at addon/example/testparam.c

Important things to note:
  • MNAME must be the same as the file name.
  • The lsi_serverhook_t array contains all the functions that you wish to "hook" onto a request, at a given hook point.
    • IMPORTANT: This should always end with lsi_serverhook_t_END
  • The lsi_handler_t object should contain the handler's main, on read, on write, and on clean up functions. The last three are optional, but the main function is what starts your handler.
    • NOTE: There can only be one handler per module.
  • The (optional) lsi_config_t object is for if you have any configurations you wish to set up for the module on server start up.
    • This should contain the parsing function, the freeing function, and any parameters you wish to pass to the parser.
  • Finally, the lsi_module_t object is what pulls everything together.
    • This should always have LSI_MODULE_SIGNATURE, followed by:
      • an Initializer function - if you need to do any initialization on server start up, this is the place to do it.
      • The handler object - This is optional if you don't have a handler
      • The configuration parser object - This is also optional if you don't have any configurations.
      • Version string.
      • The server hooks object - The functions that you want to hook onto a request.
With that, I will get into more detail about the functions in this particular module:

reg_handler - This hooks into the URI_MAP hook point. Essentially, what we do in this function is check the uri that was passed in, and if it contains what we want to handle, register the request handler.
If you wish to statically handle a specific suffix, this function is not necessary.​

testparam_handlerBeginProcess - This is your handler's "main" function. It will only be called if you registered it in the previous function.
You can set the response headers and append to the response body here (it can be incrementally or all at once), then once you are done, you end the response.

Final notes:
- You are required to include <ls.h>, else nothing will work.
- We have runtime libraries in include/lsr/ that you may find useful.


We tried to document the functions available as much as we could, but if something is unclear, please let us know!

If you have any more questions, let us know and we'll see what we can do to help.
Kevin
 
#6
@Kevin,
`... implementing your own request handler based on the URL given.`
Yes

`So for example, example.com/index.bar would be handled by a ".bar" handler?`

Nope. The url handler does not depend on suffix.
Suppose urls are RESTful like, the handler would bind to the root / path, and does its own dispatching to internal functions in C/C++ based on the path and request method. Eg:

GET / --> home(..)
GET /user --> listUsers(..)
GET /user/@id --> showUser(id) where @id can be a number, such as /user/1, /user/23
POST /user --> createUser(..)
...

That means Openlitespeed's only sees one handler that handles ALL url requests. That is why I asked if vhost is still need to be configured in the first post.
The handler is expected to take over all url dispatching and supports parameters in url, such as @id above.

Your explanation regarding testparam.c is exactly what I did not understand previously. :)

So correct me if I am wrong:

1. If we want to register such a handler, both lsi_handler_t and serverhook must be present in lsi_module_t.
2. In the serverhook, the reg_handler is invoked upon a HTTP request, based on its hook point.
3. In reg_handler, if the url matches its specific pattern, lsi_module_t is brought to life by register_req_handler().
4. Repeat (2) and (3) for *every* HTTP request?
 
Last edited:
#7
@Michael,
As you can see I am not planning to expose to more SAPIs, but rather to handle all HTTP requests from LSIAPI module.
The module *.so file will be the complete web application. It generates HTTP response, and may talk to database. No PHP or Ruby or Python.
 

lsmichael

Active Member
#8
@Michael,
As you can see I am not planning to expose to more SAPIs, but rather to handle all HTTP requests from LSIAPI module.
The module *.so file will be the complete web application. It generates HTTP response, and may talk to database. No PHP or Ruby or Python.
Really? That seems like a monumental project... No?
 
#9
Suppose urls are RESTful like, the handler would bind to the root / path, and does its own dispatching to internal functions in C/C++ based on the path and request method. Eg:

GET / --> home(..)
GET /user --> listUsers(..)
GET /user/@id --> showUser(id) where @id can be a number, such as /user/1, /user/23
POST /user --> createUser(..)
If I am understanding you correctly, then yes, you have to configure it in the VHost.

On the web admin, you can check out Virtual Hosts -> select a virtual host -> context -> create a new one and make it handled by the module.

1. If we want to register such a handler, both lsi_handler_t and serverhook must be present in lsi_module_t.
2. In the serverhook, the reg_handler is invoked upon a HTTP request, based on its hook point.
3. In reg_handler, if the url matches its specific pattern, lsi_module_t is brought to life by register_req_handler().
4. Repeat (2) and (3) for *every* HTTP request?
1. Yes. I am asking another developer who is more involved in this part of the code regarding whether or not lsi_serverhook_t is required, but the current answer is that the structure is required even if there's nothing inside it except the end.
2. Correct.
3. You got it.
4. If it needs to be registered dynamically, yes, though it sounds like you were looking to do it the context way, so if you are to assign the module to be a certain context's handler, 3 is not necessary.

Kevin
 
#10
Really? That seems like a monumental project... No?
Yeah, but that depends on how complex the web app is. Or maybe I am too naive. :unsure:

If I am understanding you correctly, then yes, you have to configure it in the VHost.

On the web admin, you can check out Virtual Hosts -> select a virtual host -> context -> create a new one and make it handled by the module.

....
4. If it needs to be registered dynamically, yes, though it sounds like you were looking to do it the context way, so if you are to assign the module to be a certain context's handler, 3 is not necessary.

Kevin
Ah I wasn't aware of the context way. That's a very valuable pointer! (y)(y)
Now only I understood testparam.c and can make hellohandler.c to work.
Looks like you guys already had my use case figured out and covered. Impressive!
Can't wait to start coding now...

Thanks. I think Openlitespeed deserves far wider publicity, seriously.
 
#11
Thanks for the kind words!

Yes, we are trying our best to cover as many uses as possible, so anything new is good.

If you have any more questions let us know!

Kevin
 
Top