[HN Gopher] Lapis: A Web Framework for Lua
       ___________________________________________________________________
        
       Lapis: A Web Framework for Lua
        
       Author : thunderbong
       Score  : 142 points
       Date   : 2024-05-25 10:56 UTC (12 hours ago)
        
 (HTM) web link (leafo.net)
 (TXT) w3m dump (leafo.net)
        
       | prezjordan wrote:
       | I find Lua so dang pleasing to look at
        
         | christophilus wrote:
         | I agree, but I miss static types. Has anyone here ever used
         | Nelua[0]?
         | 
         | [0] https://nelua.io/
        
           | iTokio wrote:
           | Luau from Roblox is gradually typed and has great support
        
           | stefanos82 wrote:
           | I do and I'm quite pleased with it.
        
           | otikik wrote:
           | Teal, man
        
         | ngrilly wrote:
         | I read too fast and thought you wrote something like "I like
         | Lua so dang please look at it" :)
        
         | CableNinja wrote:
         | Yea, but who starts an array index at 1!?!?
        
           | jecel wrote:
           | Algol 68, APL, AWK, COBOL, Fortran, Julia, Mathematica and
           | Wolfram Language, MATLAB and Octave, PL/I, RPG, R, Smalltalk,
           | etc (including Lua).
        
       | raytopia wrote:
       | Lapis is the framework that itch.io uses. [1] It also uses
       | MoonScript [2] as the programming language which was also written
       | by the creator of itch.io/Lapis.
       | 
       | 1. https://leafo.net/posts/introducing_itchio.html
       | 
       | 2. https://moonscript.org/
        
         | natrys wrote:
         | One thing people might need to keep in mind is that Lapis isn't
         | particularly interested in adding features that itch.io doesn't
         | need. Been almost a decade since websocket support was
         | requested e.g.
         | 
         | https://github.com/leafo/lapis/issues/233
        
           | CaptainOfCoit wrote:
           | What in that issue says that Lapis would only implement
           | things needed for itch.io? Seems there is a off-hand comment
           | by a non-contributor that it seems to be like that, but
           | hardly a confirmation it actually is like that.
        
           | xrd wrote:
           | What about SSE? If that's there, then I'm happy without
           | websockets.
        
             | biftek wrote:
             | Looks like you can bypass the lapis renderer and use
             | ngx.print() and ngx.header() to control the response
             | yourself
             | 
             | Look under skip_render here:
             | https://leafo.net/lapis/reference/actions.html#render-
             | option...
        
           | dubcanada wrote:
           | This is completely incorrect comment. There is no rejection
           | of any form, it is logical that the main developer who used
           | it to build itch.io is not going to put in the effort to do
           | something they don't care about. But the product is open
           | source, anyone can write that functionality, and I am sure it
           | would be accepted. What you are complaining about is a
           | developer who is not willing to put in free effort for a
           | feature you care about, but are not willing to contribute to.
        
             | johnchristopher wrote:
             | > But the product is open source, anyone can write that
             | functionality, and I am sure it would be accepted.
             | 
             | I have often read on HN that not accepting a PR for a
             | feature that is not tangential to the core business of the
             | project is valid and understandable when the maintainer
             | believes it will require too much resources (bug triage,
             | fixes, documentation, short or long term support in the
             | forums, etc.) from him.
        
               | johnchristopher wrote:
               | I am sorry, I wish I could rephrase "from him" with a
               | neutral pronoun but it's too late for editing. English
               | isn't my first language and I don't have the same
               | reflexes when writing.
        
             | natrys wrote:
             | > What you are complaining about is a developer who is not
             | willing to put in free effort for a feature you care about,
             | but are not willing to contribute to.
             | 
             | How exactly is this complaining? I am merely making an
             | observation, not even in the earshot of their devs. I had
             | evaluated Lapis years ago, but quickly moved on when it
             | didn't seem adequate. I didn't complain about that in their
             | issue tracker then, and I am not going out of my way to
             | bring this up now because I am holding a grudge like you
             | are implying. Whether or not they add websocket today
             | wouldn't matter to me in the least, I am simply indifferent
             | to it.
             | 
             | > it is logical that the main developer who used it to
             | build itch.io is not going to put in the effort to do
             | something they don't care about
             | 
             | There are plenty of frameworks that add features well
             | beyond what the devs need for their own products. All I am
             | saying is it might be more _logical_ for other people here
             | to use those instead. Of course people can come to this
             | conclusion on their own, but highlighting what I believe to
             | be a key information may save that time.
        
             | mardifoufs wrote:
             | I don't get this sentiment. Just as the maintainer is
             | allowed to do whatever they want with their project, random
             | people on the internet can also warn other people about
             | downsides of said project. Absolutely nothing GP said
             | implied that they felt entitled to a feature.
             | 
             | It is useful information for potential users to know how
             | the project works and if it might not fit them well.
             | There's no contract or agreement between the maintainer and
             | users. Users are free to talk about the project. As long as
             | they don't demand anything I don't see the issue at all.
        
           | leafo wrote:
           | Lapis is very dependent on the server backend it is running
           | in, generally OpenResty.
           | 
           | Last I investigated, the ergonomics of the websockets API in
           | OpenResty didn't really seem like a good candidate for
           | building websocket based applications. As an example, there's
           | no trivial way to keep track of all connected clients and
           | broadcast a message to them without overly complicated
           | solutions. It's not trivial to listen to events from
           | different asynchronous sources at the same time. (probably
           | other things too but I don't remember right now)
           | OpenResty/Nginx is not a general purpose event loop. The fact
           | that it's primarily an HTTP webserver is evident in the
           | design of the interfaces that are made available.
           | 
           | That said, there's nothing stopping you from and utilizing
           | the `ngx` APIs directly, there are just a few considerations
           | to be made with database connection pooling, but generally
           | you can `require` any Lapis module and use it anywhere in Lua
           | code. For websockets in OpenResty look here:
           | https://github.com/openresty/lua-resty-websocket
           | 
           | The reason the issue is still open is not because I'm not
           | interested in adding it, but because I didn't feel Lapis
           | could provide a useful abstraction at this time.
        
             | natrys wrote:
             | This is valuable context behind understanding the issue. I
             | apologise for the unfounded accusation, though in my
             | defence the issue probably could have used this
             | clarification.
             | 
             | In any case, I sympathise with being constrained by
             | design/interface of underlying technology. One one hand, I
             | suspect like most people I lack the knowledge of Nginx
             | internals or its Lua API. But on the other hand, it's cool
             | that one has an escape hatch in terms of being able to
             | leverage other solutions from the underlying platform.
             | 
             | My last two cents on this matter (not a criticism or
             | demand), since the docs are beginner friendly, perhaps a
             | likewise friendly guide on dropping down to `ngx` API for
             | the rare case when such escape hatches are needed (e.g.
             | cookbook for this websocket scenario) could be beneficial
             | for end user, even if the primary focus of Lapis is to
             | enable one to _not_ have to do that.
        
       | pfd1986 wrote:
       | Great name! (Portuguese word for 'pencil')
        
         | jszymborski wrote:
         | Huh, here I was just assuming it was a reference to "lapis
         | lazuli" but seeing as lua is Portuguese for moon, "pencil"
         | makes most sense here.
         | 
         | Thanks!
        
         | qsort wrote:
         | It's Latin for "stone". Also used in Italian as a
         | regional/alternative word for "pencil".
        
           | wonks wrote:
           | As in "lua rock"?
        
             | Lalabadie wrote:
             | Moon rock, I suppose
        
       | VWWHFSfQ wrote:
       | We started out using lapis in nginx but unfortunately had to
       | abandon it because it basically takes away all the power of using
       | regular location {}. You have to mount your whole app under like
       | location / which is lame for an nginx-native framework.
       | 
       | It's got some nice utilities that we use, but we ended up just
       | using regular location {} routes each with their own
       | content_by_lua code block and none of the lapis routing/handler
       | stuff.
        
         | pacifika wrote:
         | Why is that a problem?
        
           | VWWHFSfQ wrote:
           | Because we want to use rewrites, jumps, named handlers, etc.
           | in nginx too. But you can't do that once you delegate all
           | your routing to Lua. At that point all nginx is doing is a
           | socket event loop.
           | 
           | We weren't happy to lose all the power of nginx just to use a
           | framework.
        
             | binary132 wrote:
             | I would think you would treat the OpenRESTy component as
             | just an executable binary application server just as you
             | would with any other webservice, and put your nginx stuff
             | in front of it, just like you would with any other
             | webserver's front end lb. I agree that it does sound nice
             | to handle it as another component in a regular nginx
             | config, but it doesn't sound like a dealbreaker. Just treat
             | the nginx stuff as incidental to the implementation and it
             | seems like it would be no big deal.
        
         | xrd wrote:
         | Do you know if you can use lapis to proxy to a backend,
         | essentially getting the benefits of nginx proxy, but perhaps
         | allowing you to layer an authz/authen handler on top using
         | lapis? Thanks for your comment.
        
         | leafo wrote:
         | I suppose I haven't really fully considered this use case,
         | but...
         | 
         | There's no requirement to put your entire app in a location /
         | {} block. You can freely use as many location blocks as you
         | want, and those that you want to be rendered by Lapis can call
         | serve to the app as normal.
         | 
         | eg.
         | 
         | location = /exact-match { content_by_lua
         | 'require("lapis").serve("app")'; }
         | 
         | location /directory-match { content_by_lua
         | 'require("lapis").serve("app")'; }
         | 
         | Keep in mind pattern matching will still happen in the app: You
         | will need to define the routes handled by Lapis within the
         | definition of the Lapis app. Why is it done this way?
         | Primarily, for named routes. Typically you want to be able to
         | generate the URL of a resource within your app's code, so by
         | having routes defined in Lua you can easily reference those.
         | Secondly, easy parameter parsing and the parameter validation.
         | 
         | > It's got some nice utilities that we use, but we ended up
         | just using regular location {} routes each with their own
         | content_by_lua code block and none of the lapis routing/handler
         | stuff.
         | 
         | Although it's very possible to pick and choose what components
         | to use, keep in mind that the `serve` function does some
         | important work with connection pooling. If you are using any
         | query related functionality outside of a dispatch it will open
         | and close connections per request, which is not ideal for
         | performance.
        
       | xena wrote:
       | I used to use Lapis for my website, it is a lovely framework. For
       | a long time it was what I reached for when I needed something
       | like Rails but didn't want to deal with Rails.
       | 
       | Been thinking about using Moonscript for some Kubernetes
       | templates, I love its table creation shorthand.
        
       | xrd wrote:
       | Not knowing much about MoonScript and only knowing a tiny bit of
       | Lua, does anyone have a recommendation on which is "better" if
       | you are starting from where I'm at with these languages?
       | 
       | MoonScript looks class based; I avoid classes like the plague in
       | JavaScript because of "this" but maybe that is the wrong starting
       | assessment?
        
         | _heimdall wrote:
         | I wouldn't run from classes just because JS historically has,
         | though coming from JS I'd lean towards lua for a more familiar
         | function calling syntax.
        
         | elpocko wrote:
         | MoonScript supports classes via keyword, while in Lua you have
         | to implement them yourself. That's about it. You can ignore
         | them, even more so than in JS.
         | 
         | MoonScript is dead anyway. Check out yuescript instead:
         | https://github.com/pigpigyyy/Yuescript
        
           | hnax wrote:
           | lua-classy (https://github.com/siffiejoe/lua-classy) works
           | like gem and is fast!
        
             | elpocko wrote:
             | It's 10x larger than it needs to be, and seems to do a lot
             | of unnecessary stuff. I would call this one _hopelessly
             | bloated and overengineered_ and recommend something like
             | https://github.com/Yonaba/30log instead.
        
         | otikik wrote:
         | Start with Lua. Moonscript produces Lua so you will have to
         | deal with Lua if you're ever to debug a Moonscript program. The
         | opposite isn't true
        
         | thefaux wrote:
         | I would strongly recommend just learning vanilla lua. The
         | beauty of lua is that it is lightweight and runs anywhere so it
         | is worth learning on its own terms. Wrapper languages come and
         | go, but lua 5.1 is still highly usable even though it hasn't
         | changed its feature set in 15 years (and never will).
        
       | orange_fritter wrote:
       | I've spent probably 200 hours with MoonScript, was obsessed with
       | it for a bit, and love it 90% of the time. The problem is that
       | MoonScript's grammar is INCREDIBLY permissive. Common typos(often
       | involving spaces) don't break your code, whereas in Lua or Python
       | the mistake wouldn't compile.
       | 
       | MoonScript is awesome but I lean on compilers pretty heavily to
       | catch my mistakes, so I sadly and regrettably admitted that I was
       | more productive with other toolchains.
        
       ___________________________________________________________________
       (page generated 2024-05-25 23:02 UTC)