2020-01-23 05:26:30 +03:00
|
|
|
module picohttpparser
|
|
|
|
|
2023-07-12 09:40:16 +03:00
|
|
|
const (
|
|
|
|
max_headers = 100
|
|
|
|
)
|
|
|
|
|
|
|
|
pub struct Header {
|
|
|
|
pub mut:
|
|
|
|
name string
|
|
|
|
value string
|
|
|
|
}
|
|
|
|
|
2020-01-23 05:26:30 +03:00
|
|
|
pub struct Request {
|
2021-04-24 13:21:30 +03:00
|
|
|
mut:
|
2021-05-03 16:55:13 +03:00
|
|
|
prev_len int
|
2020-05-20 06:36:46 +03:00
|
|
|
pub mut:
|
2021-04-04 22:43:13 +03:00
|
|
|
method string
|
|
|
|
path string
|
2023-07-12 09:40:16 +03:00
|
|
|
headers [max_headers]Header
|
|
|
|
num_headers int
|
2021-04-04 22:43:13 +03:00
|
|
|
body string
|
2020-01-23 05:26:30 +03:00
|
|
|
}
|
|
|
|
|
2023-07-12 09:40:16 +03:00
|
|
|
// Pret contains the nr of bytes read, a negative number indicates an error
|
|
|
|
struct Pret {
|
|
|
|
pub mut:
|
|
|
|
err string
|
|
|
|
// -1 indicates a parse error and -2 means the request is parsed
|
|
|
|
ret int
|
|
|
|
}
|
|
|
|
|
|
|
|
// parse_request parses a raw HTTP request and returns the number of bytes read.
|
|
|
|
// -1 indicates a parse error and -2 means the request is parsed
|
2020-01-23 05:26:30 +03:00
|
|
|
[inline]
|
2023-07-12 09:40:16 +03:00
|
|
|
pub fn (mut r Request) parse_request(s string) !int {
|
|
|
|
mut buf := s.str
|
|
|
|
buf_end := unsafe { s.str + s.len }
|
|
|
|
|
|
|
|
mut pret := Pret{}
|
|
|
|
// if prev_len != 0, check if the request is complete
|
|
|
|
// (a fast countermeasure against slowloris)
|
|
|
|
if r.prev_len != 0 && unsafe { is_complete(buf, buf_end, r.prev_len, mut pret) == nil } {
|
|
|
|
if pret.ret == -1 {
|
|
|
|
return error(pret.err)
|
2021-02-15 18:15:52 +03:00
|
|
|
}
|
2023-07-12 09:40:16 +03:00
|
|
|
return pret.ret
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = r.phr_parse_request(buf, buf_end, mut pret)
|
|
|
|
if pret.ret == -1 {
|
|
|
|
return error(pret.err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if unsafe { buf == nil } {
|
|
|
|
return pret.ret
|
2020-01-23 05:26:30 +03:00
|
|
|
}
|
2023-07-12 09:40:16 +03:00
|
|
|
|
|
|
|
pret.ret = unsafe { buf - s.str }
|
|
|
|
|
|
|
|
r.body = unsafe { (&s.str[pret.ret]).vstring_literal_with_len(s.len - pret.ret) }
|
2021-04-24 13:21:30 +03:00
|
|
|
r.prev_len = s.len
|
2023-07-12 09:40:16 +03:00
|
|
|
|
|
|
|
// return nr of bytes
|
|
|
|
return pret.ret
|
2020-01-23 05:26:30 +03:00
|
|
|
}
|
|
|
|
|
2023-07-12 09:40:16 +03:00
|
|
|
// parse_request_path sets the `path` and `method` fields
|
2020-01-23 05:26:30 +03:00
|
|
|
[inline]
|
2023-07-12 09:40:16 +03:00
|
|
|
pub fn (mut r Request) parse_request_path(s string) !int {
|
|
|
|
mut buf := s.str
|
|
|
|
buf_end := unsafe { s.str + s.len }
|
|
|
|
|
|
|
|
mut pret := Pret{}
|
|
|
|
r.phr_parse_request_path(buf, buf_end, mut pret)
|
|
|
|
if pret.ret == -1 {
|
|
|
|
return error(pret.err)
|
2020-01-23 05:26:30 +03:00
|
|
|
}
|
2023-07-12 09:40:16 +03:00
|
|
|
|
|
|
|
return pret.ret
|
2020-01-23 05:26:30 +03:00
|
|
|
}
|
|
|
|
|
2023-07-12 09:40:16 +03:00
|
|
|
// parse_request_path_pipeline can parse the `path` and `method` of HTTP/1.1 pipelines.
|
|
|
|
// Call it again to parse the next request
|
2020-01-23 05:26:30 +03:00
|
|
|
[inline]
|
2023-07-12 09:40:16 +03:00
|
|
|
pub fn (mut r Request) parse_request_path_pipeline(s string) !int {
|
|
|
|
mut buf := unsafe { s.str + r.prev_len }
|
|
|
|
buf_end := unsafe { s.str + s.len }
|
|
|
|
|
|
|
|
mut pret := Pret{}
|
|
|
|
r.phr_parse_request_path_pipeline(buf, buf_end, mut pret)
|
|
|
|
if pret.ret == -1 {
|
|
|
|
return error(pret.err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if pret.ret > 0 {
|
|
|
|
r.prev_len = pret.ret
|
2020-01-23 05:26:30 +03:00
|
|
|
}
|
2023-07-12 09:40:16 +03:00
|
|
|
return pret.ret
|
2020-01-23 05:26:30 +03:00
|
|
|
}
|