first commit

This commit is contained in:
yangshangbo
2025-04-10 18:14:01 +08:00
commit 8b18de9693
26 changed files with 270858 additions and 0 deletions
+160
View File
@@ -0,0 +1,160 @@
module hono
import net.urllib
import net.http
import regex
import time
type Handler = fn (req Request) http.Response
struct RequestHandler {
path string
handler Handler = unsafe { nil }
}
struct Router {
mut:
handlers struct {
mut:
get []RequestHandler
post []RequestHandler
put []RequestHandler
delete []RequestHandler
patch []RequestHandler
head []RequestHandler
options []RequestHandler
}
}
pub struct Hono {
mut:
server http.Server = http.Server{}
router Router = Router{}
}
pub fn (mut app Hono) get(path string, handler Handler) {
app.router.handlers.get << RequestHandler{path, handler}
}
pub fn (mut app Hono) post(path string, handler Handler) {
app.router.handlers.post << RequestHandler{path, handler}
}
pub fn (mut app Hono) put(path string, handler Handler) {
app.router.handlers.put << RequestHandler{path, handler}
}
pub fn (mut app Hono) delete(path string, handler Handler) {
app.router.handlers.delete << RequestHandler{path, handler}
}
pub fn (mut app Hono) patch(path string, handler Handler) {
app.router.handlers.patch << RequestHandler{path, handler}
}
pub fn (mut app Hono) head(path string, handler Handler) {
app.router.handlers.head << RequestHandler{path, handler}
}
pub fn (mut app Hono) options(path string, handler Handler) {
app.router.handlers.options << RequestHandler{path, handler}
}
struct ServerHanler {
app Hono
}
fn ServerHanler.new(app Hono) ServerHanler {
return ServerHanler{
app: app
}
}
fn match_path_with_regex(real_path string, reg_path string) (bool, regex.RE) {
start := time.now()
mut one_more_star_reg := regex.regex_opt(r'\*{2,}') or { panic(err) }
repl_on_e_more_star_fn := fn (re regex.RE, in_txt string, start int, end int) string {
if in_txt.ends_with('*') {
return r'(\w+/){0,}\w+'
}
return r'(\w+//){0,}\w+'
}
mut replaced_path := one_more_star_reg.replace_by_fn(reg_path, repl_on_e_more_star_fn)
replaced_path = replaced_path.replace('*', r'\w+')
mut pamam_reg := regex.regex_opt(r':\w+') or { panic(err) }
repl_fn := fn (re regex.RE, in_txt string, start int, end int) string {
match_str := in_txt[start..end]
return '(?P<${match_str[1..]}>\\w+)'
}
replaced_path = pamam_reg.replace_by_fn(replaced_path, repl_fn)
replaced_path = replaced_path + '$'
mut reg := regex.regex_opt(replaced_path) or { panic(err) }
end := time.now()
println('Regex compile time: ${end - start}')
return reg.matches_string(real_path), reg
}
fn (s ServerHanler) handle(req http.Request) http.Response {
mut res := http.Response{
status_code: 404
body: 'Not Found'
}
handlers := match req.method {
.get {
s.app.router.handlers.get
}
.post {
s.app.router.handlers.post
}
.put {
s.app.router.handlers.put
}
.delete {
s.app.router.handlers.delete
}
.patch {
s.app.router.handlers.patch
}
.head {
s.app.router.handlers.head
}
.options {
s.app.router.handlers.options
}
else {
[]
}
}
for handler in handlers {
url := urllib.parse(req.url) or {
urllib.URL{
path: '/'
}
}
match_result, mut replaced_path_reg := match_path_with_regex(url.path, handler.path)
if match_result {
mut param_map := map[string]string{}
mut pamam_reg := regex.regex_opt(r':\w+') or { panic(err) }
all_params := pamam_reg.find_all_str(handler.path)
for param in all_params {
param_name := param[1..]
group := replaced_path_reg.get_group_by_name(url.path, param_name)
param_map[param_name] = group
}
query_map := url.query().to_map()
res = handler.handler(Request{
url: url.path
param: param_map
query: query_map
})
break
}
}
return res
}
pub fn (mut app Hono) listen(port string) {
app.server.addr = port
app.server.handler = ServerHanler.new(app)
app.server.listen_and_serve()
}