Greetings to all,
For those that like to experiment, here is a TCL extension that helps you build a Web Server in 20 lines of code: https://github.com/jerily/twebserver
In short, it is NOT an application server, it is a TCL loadable module, and it does NOT try to do things that other extensions already accomplish (or will accomplish in the future).
Here is an example without threads:
package require twebserverproc process_request {request_dict} {
return "HTTP/1.1 200 OK\n\ntest message request_dict=$request_dict\n"
}
proc process_conn {conn addr port} {
if { [catch {
set request [::twebserver::read_conn $conn]
set reply [process_request [::twebserver::parse_request $request]]
::twebserver::write_conn $conn $reply
} errmsg] } {
puts "error: $errmsg"
}
::twebserver::close_conn $conn
}
set config_dict [dict create]
set server_handle [::twebserver::create_server $config_dict process_conn]
::twebserver::add_context $server_handle localhost "../certs/host1/key.pem" "../certs/host1/cert.pem"
::twebserver::add_context $server_handle www.example.com "../certs/host2/key.pem" "../certs/host2/cert.pem"
::twebserver::listen_server $server_handle 4433
::twebserver::destroy_server $server_handle
And, here is an example with threads (requires installing Thread extension):
package require twebserver
package require Threadset thread_script {
package require twebserver
proc thread_process_request {request_dict} {
return "HTTP/1.1 200 OK\n\ntest message request_dict=$request_dict\n"
}
proc thread_process_conn {conn addr port} {
after 1000 [list ::twebserver::close_conn $conn]
if { [catch {
set request [::twebserver::read_conn $conn]
set reply [thread_process_request [::twebserver::parse_request $request]]
::twebserver::write_conn $conn $reply
} errmsg] } {
puts "error: $errmsg"
}
::twebserver::close_conn $conn
}
}
set pool [::tpool::create -minworkers 5 -maxworkers 20 -idletime 40 -initcmd $thread_script]
proc process_conn {conn addr port} {
global pool
::tpool::post -detached -nowait $pool [list thread_process_conn $conn $addr $port]
}
set max_request_read_bytes [expr { 10 * 1024 * 1024 }]
set max_read_buffer_size [expr { 1024 * 1024 }]
set config_dict [dict create max_request_read_bytes $max_request_read_bytes max_read_buffer_size $max_read_buffer_size]
set server_handle [::twebserver::create_server $config_dict process_conn]
::twebserver::add_context $server_handle localhost "../certs/host1/key.pem" "../certs/host1/cert.pem"
::twebserver::add_context $server_handle www.example.com "../certs/host2/key.pem" "../certs/host2/cert.pem"
::twebserver::listen_server $server_handle 4433
::twebserver::destroy_server $server_handle
In my opinion, it is also good for educational purposes. The extension is not more than 1500 lines of C code and about half of it are the tables for encoding and decoding URI components. Furthermore, it allows you to build your framework to serve the requests prepared by twebserver without relying on the Web Server for auxiliary commands. I kind of like it. I hope you will too.