-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathdispatch.mbt
More file actions
70 lines (68 loc) · 2.03 KB
/
Copy pathdispatch.mbt
File metadata and controls
70 lines (68 loc) · 2.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
///|
/// Split a raw HTTP request-target into its path and query string.
///
/// Routes match against the path; the query is retained separately on the
/// `HttpRequest`. A `#fragment` is never used for routing, so it is stripped
/// from the query rather than exposed.
fn split_request_target(target : String) -> (String, String) {
let (path, rest) = match target.find("?") {
Some(q) => (target[:q].to_owned(), target[q + 1:].to_owned())
None => (target, "")
}
let query = match rest.find("#") {
Some(f) => rest[:f].to_owned()
None => rest
}
(path, query)
}
///|
/// Whether a request carries a body: POST/PUT/PATCH always may, and any
/// method with an explicit (non-empty) `content-length` or a
/// `transfer-encoding` (i.e. chunked) frame is treated as having a body.
/// The same rule is used by every backend so bodies are read consistently.
fn request_has_body(
http_method : String,
headers : Map[@http.CaseInsensitiveString, StringView],
) -> Bool {
match http_method {
"POST" | "PUT" | "PATCH" => true
_ =>
headers.get("transfer-encoding") is Some(_) ||
headers
.get("content-length")
.map(value => value.to_owned().trim() != "0")
.unwrap_or(false)
}
}
///|
pub async fn dispatch_http(
mocket : Mocket,
http_method : String,
url : String,
headers : Map[@http.CaseInsensitiveString, StringView],
raw_body : Bytes,
) -> HttpResponse {
let (path, query) = split_request_target(url)
let (params, handler) = match mocket.find_route(http_method, path) {
Some((h, p)) => (p, h)
_ => ({}, handle_not_found())
}
let event = {
req: { http_method, url: path, query, raw_body, headers, },
res: HttpResponse::new(OK),
params,
}
let responder = mocket.execute_middlewares(event, handler) catch {
err => {
if @async.is_cancellation_error(err) {
raise err
}
mocket.handle_request_error(event, err)
}
}
responder.options(event.res)
let buf = Buffer()
responder.output(buf)
event.res.raw_body = buf.to_bytes()
event.res
}