Added HTTP server class to stdlib and an example server written in 100% pure Fun. (0.37.28)
This commit is contained in:
parent
aa8701a5a1
commit
10b75596cd
6 changed files with 142 additions and 2 deletions
|
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(fun VERSION 0.37.27 LANGUAGES C)
|
||||
project(fun VERSION 0.37.28 LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
|
|
|||
30
examples/class_test.fun
Executable file
30
examples/class_test.fun
Executable file
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env fun
|
||||
|
||||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-12-28
|
||||
*/
|
||||
|
||||
class Other(number val)
|
||||
fun _construct(this, val)
|
||||
this.v = val
|
||||
|
||||
class Test()
|
||||
fun _construct(this)
|
||||
val = Other(123)
|
||||
this.a = val
|
||||
print("a set")
|
||||
|
||||
t = Test()
|
||||
print(t.a.v)
|
||||
|
||||
/* Expected output:
|
||||
a set
|
||||
123
|
||||
*/
|
||||
10
examples/data/htdocs/index.html
Normal file
10
examples/data/htdocs/index.html
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Fun HTTP Server</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Welcome to the Fun HTTP Server!</h1>
|
||||
<p>This page is served from <code>./examples/data/htdocs/index.html</code>.</p>
|
||||
</body>
|
||||
</html>
|
||||
22
examples/extra/http_server.fun
Executable file
22
examples/extra/http_server.fun
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env fun
|
||||
|
||||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-12-28
|
||||
*/
|
||||
|
||||
#include <net/http_server.fun>
|
||||
|
||||
port = 8080
|
||||
htdocs = "./examples/data/htdocs"
|
||||
|
||||
server = HTTPServer(port)
|
||||
server.set_htdocs(htdocs)
|
||||
|
||||
server.start()
|
||||
78
lib/net/http_server.fun
Normal file
78
lib/net/http_server.fun
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-12-28
|
||||
*/
|
||||
|
||||
#include <io/socket.fun>
|
||||
#include <strings.fun>
|
||||
|
||||
class HTTPServer(number port)
|
||||
fun _construct(this, port)
|
||||
this.port = port
|
||||
srv = TcpServer(port, 10)
|
||||
this.server = srv
|
||||
this.htdocs = "./"
|
||||
|
||||
fun set_htdocs(this, path)
|
||||
this.htdocs = to_string(path)
|
||||
|
||||
fun start(this)
|
||||
if (this.server.listen() <= 0)
|
||||
print("HTTPServer: failed to listen on port " + to_string(this.port))
|
||||
return 0
|
||||
print("HTTPServer: serving " + this.htdocs + " on port " + to_string(this.port))
|
||||
while true
|
||||
client_fd = this.server.accept()
|
||||
if (client_fd > 0)
|
||||
this.handle_client(client_fd)
|
||||
return 1
|
||||
|
||||
fun handle_client(this, fd)
|
||||
request = sock_recv(fd, 4096)
|
||||
if (len(request) == 0)
|
||||
sock_close(fd)
|
||||
return 0
|
||||
|
||||
// Basic request parsing
|
||||
lines = str_split(request, "\n")
|
||||
if (len(lines) == 0)
|
||||
sock_close(fd)
|
||||
return 0
|
||||
|
||||
first_line = lines[0]
|
||||
parts = str_split(first_line, " ")
|
||||
if (len(parts) < 2)
|
||||
sock_close(fd)
|
||||
return 0
|
||||
|
||||
method = parts[0]
|
||||
path = parts[1]
|
||||
|
||||
if (path == "/")
|
||||
path = "/index.html"
|
||||
|
||||
full_path = this.htdocs + path
|
||||
content = read_file(full_path)
|
||||
|
||||
if (len(content) > 0)
|
||||
this.send_response(fd, 200, "OK", content)
|
||||
else
|
||||
this.send_response(fd, 404, "Not Found", "<h1>404 Not Found</h1>")
|
||||
|
||||
sock_close(fd)
|
||||
return 1
|
||||
|
||||
fun send_response(this, fd, status_code, status_text, body)
|
||||
resp = "HTTP/1.1 " + to_string(status_code) + " " + status_text + "\r\n"
|
||||
resp = resp + "Content-Type: text/html\r\n"
|
||||
resp = resp + "Content-Length: " + to_string(len(body)) + "\r\n"
|
||||
resp = resp + "Connection: close\r\n"
|
||||
resp = resp + "\r\n"
|
||||
resp = resp + body
|
||||
sock_send(fd, resp)
|
||||
|
|
@ -93,7 +93,7 @@ fun str_replace_all(s, from, to)
|
|||
out = []
|
||||
number i = 0
|
||||
while i < n
|
||||
if (i + lf <= n) && (substr(src, i, lf) == f)
|
||||
if ((i + lf <= n) && (substr(src, i, lf) == f))
|
||||
push(out, t)
|
||||
i = i + lf
|
||||
else
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue