Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2afd947d0 | ||
|
|
cfde1b4306 | ||
|
|
0a4e5d50f3 |
+83
-4
@@ -399,13 +399,20 @@ fn parse_http_request_usockets(raw string) (string, string, map[string]string, s
|
|||||||
|
|
||||||
// 4. 检测 HTTP 版本 - "HTTP/1.0" vs "HTTP/1.1"
|
// 4. 检测 HTTP 版本 - "HTTP/1.0" vs "HTTP/1.1"
|
||||||
// 请求行格式: "GET /path HTTP/1.1\r\n"
|
// 请求行格式: "GET /path HTTP/1.1\r\n"
|
||||||
|
// HTTP/1.x 版本字符串固定为 8 字符,直接检查第 8 个字符
|
||||||
mut version_start := path_end + 1
|
mut version_start := path_end + 1
|
||||||
for version_start < line_end && raw[version_start] == ` ` {
|
for version_start < line_end && raw[version_start] == ` ` {
|
||||||
version_start++
|
version_start++
|
||||||
}
|
}
|
||||||
if version_start < line_end {
|
// "HTTP/1.0" 或 "HTTP/1.1",检查索引 7 的字符(0-based)
|
||||||
version_str := raw[version_start..line_end]
|
if version_start + 7 < line_end {
|
||||||
is_http11 = !version_str.contains('1.0')
|
is_http11 = raw[version_start + 7] != `0`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对于 HTTP/1.0,检查 Connection 头是否包含 keep-alive
|
||||||
|
// 参考 Go net/http: wantsHttp10KeepAlive() 只检查 Connection 头的值
|
||||||
|
if !is_http11 {
|
||||||
|
is_http11 = has_connection_keep_alive(raw, line_end, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 查找 body(\r\n\r\n 之后)
|
// 5. 查找 body(\r\n\r\n 之后)
|
||||||
@@ -421,7 +428,79 @@ fn parse_http_request_usockets(raw string) (string, string, map[string]string, s
|
|||||||
return method, path, query_map, body, is_http11
|
return method, path, query_map, body, is_http11
|
||||||
}
|
}
|
||||||
|
|
||||||
// 快速解析 query string(单次遍历,避免 split)
|
// 检查 Connection 头是否包含 keep-alive(参考 Go net/http 实现)
|
||||||
|
// 只检查 "Connection:" 头的值,避免误判请求体中的内容
|
||||||
|
@[inline]
|
||||||
|
fn has_connection_keep_alive(raw string, headers_start int, len int) bool {
|
||||||
|
mut i := headers_start
|
||||||
|
|
||||||
|
// 遍历每一行头部
|
||||||
|
for i < len - 12 { // 至少需要 "Connection:" + 一些值
|
||||||
|
// 跳过 \r\n
|
||||||
|
if raw[i] == `\r` && i + 1 < len && raw[i + 1] == `\n` {
|
||||||
|
i += 2
|
||||||
|
// 检查是否到达头部结束(空行)
|
||||||
|
if i < len - 1 && raw[i] == `\r` && raw[i + 1] == `\n` {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否是 "Connection:" 头(不区分大小写)
|
||||||
|
if (raw[i] == `C` || raw[i] == `c`) && i + 11 < len {
|
||||||
|
// 检查 "onnection:"
|
||||||
|
if (raw[i+1] == `o` || raw[i+1] == `O`) &&
|
||||||
|
(raw[i+2] == `n` || raw[i+2] == `N`) &&
|
||||||
|
(raw[i+3] == `n` || raw[i+3] == `N`) &&
|
||||||
|
(raw[i+4] == `e` || raw[i+4] == `E`) &&
|
||||||
|
(raw[i+5] == `c` || raw[i+5] == `C`) &&
|
||||||
|
(raw[i+6] == `t` || raw[i+6] == `T`) &&
|
||||||
|
(raw[i+7] == `i` || raw[i+7] == `I`) &&
|
||||||
|
(raw[i+8] == `o` || raw[i+8] == `O`) &&
|
||||||
|
(raw[i+9] == `n` || raw[i+9] == `N`) &&
|
||||||
|
raw[i+10] == `:` {
|
||||||
|
// 找到 Connection 头,检查值是否包含 keep-alive
|
||||||
|
mut value_start := i + 11
|
||||||
|
// 跳过空格
|
||||||
|
for value_start < len && raw[value_start] == ` ` {
|
||||||
|
value_start++
|
||||||
|
}
|
||||||
|
// 查找行尾
|
||||||
|
mut value_end := value_start
|
||||||
|
for value_end < len && raw[value_end] != `\r` && raw[value_end] != `\n` {
|
||||||
|
value_end++
|
||||||
|
}
|
||||||
|
// 在值中查找 "keep-alive"(不区分大小写)
|
||||||
|
return contains_keep_alive_token(raw, value_start, value_end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查字符串片段是否包含 keep-alive token
|
||||||
|
@[inline]
|
||||||
|
fn contains_keep_alive_token(raw string, start int, end int) bool {
|
||||||
|
// 查找 "keep-alive" 或 "Keep-Alive"(支持多值如 "keep-alive, upgrade")
|
||||||
|
mut i := start
|
||||||
|
for i <= end - 10 {
|
||||||
|
if raw[i] == `k` || raw[i] == `K` {
|
||||||
|
if (raw[i+1] == `e` || raw[i+1] == `E`) &&
|
||||||
|
(raw[i+2] == `e` || raw[i+2] == `E`) &&
|
||||||
|
(raw[i+3] == `p` || raw[i+3] == `P`) &&
|
||||||
|
raw[i+4] == `-` &&
|
||||||
|
(raw[i+5] == `a` || raw[i+5] == `A`) &&
|
||||||
|
(raw[i+6] == `l` || raw[i+6] == `L`) &&
|
||||||
|
(raw[i+7] == `i` || raw[i+7] == `I`) &&
|
||||||
|
(raw[i+8] == `v` || raw[i+8] == `V`) &&
|
||||||
|
(raw[i+9] == `e` || raw[i+9] == `E`) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}// 快速解析 query string(单次遍历,避免 split)
|
||||||
@[inline]
|
@[inline]
|
||||||
fn parse_query_string_fast(raw string, start int, end int) map[string]string {
|
fn parse_query_string_fast(raw string, start int, end int) map[string]string {
|
||||||
mut query_map := map[string]string{}
|
mut query_map := map[string]string{}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Module {
|
Module {
|
||||||
name: 'hono'
|
name: 'hono'
|
||||||
description: 'A high-performance V language web framework inspired by Hono.js, featuring hybrid routing, LRU cache, middleware support, and more.'
|
description: 'A high-performance V language web framework inspired by Hono.js, featuring hybrid routing, LRU cache, middleware support, and more.'
|
||||||
version: '0.7.7'
|
version: '0.7.8'
|
||||||
license: 'MIT'
|
license: 'MIT'
|
||||||
dependencies: []
|
dependencies: []
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user