vieter/src/web/parse.v

81 lines
1.9 KiB
V

module web
import net.urllib
import net.http
// Method attributes that should be ignored when parsing, as they're used
// elsewhere.
const attrs_to_ignore = ['auth']
// Parsing function attributes for methods and path.
fn parse_attrs(name string, attrs []string) ?([]http.Method, string) {
if attrs.len == 0 {
return [http.Method.get], '/$name'
}
mut x := attrs.clone()
mut methods := []http.Method{}
mut path := ''
for i := 0; i < x.len; {
attr := x[i]
attru := attr.to_upper()
m := http.method_from_str(attru)
if attru == 'GET' || m != .get {
methods << m
x.delete(i)
continue
}
if attr.starts_with('/') {
if path != '' {
return IError(http.MultiplePathAttributesError{})
}
path = attr
x.delete(i)
continue
}
i++
}
if x.len > 0 && x.any(!web.attrs_to_ignore.contains(it)) {
return IError(http.UnexpectedExtraAttributeError{
attributes: x
})
}
if methods.len == 0 {
methods = [http.Method.get]
}
if path == '' {
path = '/$name'
}
// Make path lowercase for case-insensitive comparisons
return methods, path.to_lower()
}
// Extracts query parameters from a URL.
fn parse_query_from_url(url urllib.URL) map[string]string {
mut query := map[string]string{}
for v in url.query().data {
query[v.key] = v.value
}
return query
}
// Extract form data from an HTTP request.
fn parse_form_from_request(request http.Request) ?(map[string]string, map[string][]http.FileData) {
mut form := map[string]string{}
mut files := map[string][]http.FileData{}
if request.method in methods_with_form {
ct := request.header.get(.content_type) or { '' }.split(';').map(it.trim_left(' \t'))
if 'multipart/form-data' in ct {
boundary := ct.filter(it.starts_with('boundary='))
if boundary.len != 1 {
return error('detected more that one form-data boundary')
}
form, files = http.parse_multipart_form(request.data, boundary[0][9..])
} else {
form = http.parse_form(request.data)
}
}
return form, files
}