Codea Web Server (Also on WebRepo)

Hi all,

After some recent comments about having a separate program running alongside Codea (on iPad) for debugging purposes and things like that I thought I’d make a start.

I hope to integrate some sort of OSC support within the webpage at some point to allow bi-directional communication between the browser and the running Codea instance but this is certainly a start :smile:

So here it is, a very simple web server that serves a web page to a browser running alongside Codea:

-- Basic Web Server

local socket = require("socket")

— This is the served content
local body = [[
Hello Codea World!
]]

local function webserver_update()
    -- wait for a connection from any client
    local client = server:accept()
    if client then
        -- Make sure we don't take too long to respond to the client
        client:settimeout(1 / 60)
        
        -- Receive the request
        local line, err = client:receive()
        
        -- If no error then send our response
        if not err then
            client:send("HTTP/1.0 200 Success \\r\
\\r\
" .. body)
        end
        
        -- Close the client object
        client:close()
    end
end

local function webserver_loop()
    -- This is beautiful if I do say so myself...
    -- This will 'always' fail (as long as the silly url doesn't exist)
    -- so the fail callback will always be called outside of our main update loop.
    http.request("http://imnotarealurl.lua", function() end, function()
        webserver_update()
        webserver_loop() — Loop again!
    end)
end

function setup()
    server = assert(socket.bind("127.0.0.1", 8888))
    server:settimeout(0.001) -- minimise waiting
    local ip, port = server:getsockname()
    print("Connect to http://" .. ip .. ":" .. port)
    
    -- Kick off the async web server loop
    webserver_loop()
end

function draw()
    background(128)
end

I’m also incredibly pleased with how well the async update loop ‘hack’ panned out. It runs totally asynchronous to the main project loop!

Hopefully this is useful to some of you.

Cheers,
Steppers

UPDATE 15-Nov-2021:
Version 1.1.0 is also available on WebRepo

An improved library version has also been added to WebRepo.

It now serves files from an asset source folder, handles missing files and only requires a single line to use!

WebServer(asset.documents.SiteSource)

@Steppers - this looks amazing. Need to play with this a little to understand just what I can use it for.

On the bi-directional idea that has already been implemented in Codea with Aircode in that you can link to an editor in a browser on a PC/Mac. I still use it occasionally but it is a bit prone to crashing as it is live linked coding.

I think a better idea would be a module for an external editor where updates are not immediate but posted when ‘complete’. You could potentially use one of many editors like Notepad+, Visual Code etc etc.

@Bri_G Small debug server now too! (also on WebRepo)

It only supports reading of variables at the moment but I expect I can probably extend it some more to add editing :smile:

Downloaded the web repo version, but the server doesn’t load. I get the message “Safari cannot open the page because it could not contact to the server”.

@UberGoober Are you on iPad running safari & Codea side-by-side?

Yes

What URL are you using in Safari?

http://localhost/ is what pops up automatically

try localhost:8888, that looks like the URL stepper’s serving.

This is interesting indeed. I am going to have to try it and see what I can do with it. Quite nice.

The new version seems to want localhost:80

@RonJeffries It should be using port 80 by default as that’s what most http web servers use.

The url localhost on it’s own is working just fine for me.

@Steppers I don’t understand what the do…end blocks are about. That seems to be a trick that I don’t know.

It’d be good to see an example of setting up the resources, but I can probably fumble my way through …

I’ve not used socket. It seems that client:receive() is adding a blank at the end of the input? I can’t find any docs that suggest that happens. I’d appreciate some hints as I play with this. Thanks!

Very interesting!

yes working for me as well, I’m now trying to work out how to use the GET. Do I need to encode with %20 etc?

@RonJeffries the do … end blocks just create a scope for the local variable so it doesn’t stick around afterwards.

As for the resources, local server = WebServer(asset.documents["web-server"], 80) will start a web server that serves html files from the web-server folder inside Codea’s folder in the files app. By default if you pass it a blank path, say http://localhost/ rather than http://localhost/test.html then it will serve an index.html file if one’s available.

As for socket peculiarities, I’m still figuring it out myself but using http://www.promixis.com/lua/luasocket/reference.html for reference.

You may need to encode spaces as %20 at the moment unfortunately. I think luasocket has a URL escape function somewhere that could be used.

This is still a WIP on my part though so improvements will come.

OK, I’m not reading the thing properly. More study required. It’s cool, for sure.

localhost:8888 still does nothing. Also see attached image.

@UberGoober Give this one a try, most of the socket based backend has been rewritten and it seems much more reliable now.

I also think this is progress (see screenshot) :smiley:

See screenshot.

Safari truncates the “:80” no matter what I do.

Btw, if you put the urls in their own print() statement they can be copied directly from the output panel, letting people then paste them right into their browser.

(The copying is a hidden feature I only learned about in the last few months, and I’ve been coming here for years.)