v / vlib / picohttpparser / request.v
97 lines · 80 sloc · 2.1 KB · f09826e928f9612bab9299faefff7cf34a503362
Raw
1module picohttpparser
2
3const max_headers = 100
4
5pub struct Header {
6pub mut:
7 name string
8 value string
9}
10
11pub struct Request {
12mut:
13 prev_len int
14pub mut:
15 method string
16 path string
17 headers [max_headers]Header
18 num_headers int
19 body string
20}
21
22// Pret contains the nr of bytes read, a negative number indicates an error
23struct Pret {
24pub mut:
25 err string
26 // -1 indicates a parse error and -2 means the request is parsed
27 ret int
28}
29
30// parse_request parses a raw HTTP request and returns the number of bytes read.
31// -1 indicates a parse error and -2 means the request is parsed
32@[inline]
33pub fn (mut r Request) parse_request(s string) !int {
34 mut buf := s.str
35 buf_end := unsafe { s.str + s.len }
36
37 mut pret := Pret{}
38 // if prev_len != 0, check if the request is complete
39 // (a fast countermeasure against slowloris)
40 if r.prev_len != 0 && unsafe { is_complete(buf, buf_end, r.prev_len, mut pret) == nil } {
41 if pret.ret == -1 {
42 return error(pret.err)
43 }
44 return pret.ret
45 }
46
47 buf = r.phr_parse_request(buf, buf_end, mut pret)
48 if pret.ret == -1 {
49 return error(pret.err)
50 }
51
52 if unsafe { buf == nil } {
53 return pret.ret
54 }
55
56 pret.ret = unsafe { buf - s.str }
57
58 r.body = unsafe { (&s.str[pret.ret]).vstring_literal_with_len(s.len - pret.ret) }
59 r.prev_len = s.len
60
61 // return nr of bytes
62 return pret.ret
63}
64
65// parse_request_path sets the `path` and `method` fields
66@[inline]
67pub fn (mut r Request) parse_request_path(s string) !int {
68 mut buf := s.str
69 buf_end := unsafe { s.str + s.len }
70
71 mut pret := Pret{}
72 r.phr_parse_request_path(buf, buf_end, mut pret)
73 if pret.ret == -1 {
74 return error(pret.err)
75 }
76
77 return pret.ret
78}
79
80// parse_request_path_pipeline can parse the `path` and `method` of HTTP/1.1 pipelines.
81// Call it again to parse the next request
82@[inline]
83pub fn (mut r Request) parse_request_path_pipeline(s string) !int {
84 mut buf := unsafe { s.str + r.prev_len }
85 buf_end := unsafe { s.str + s.len }
86
87 mut pret := Pret{}
88 r.phr_parse_request_path_pipeline(buf, buf_end, mut pret)
89 if pret.ret == -1 {
90 return error(pret.err)
91 }
92
93 if pret.ret > 0 {
94 r.prev_len = pret.ret
95 }
96 return pret.ret
97}
98