-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhttp_response.lasso
102 lines (83 loc) · 3.17 KB
/
http_response.lasso
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
define http_response => type {
data
private headerBytes::bytes,
private protocol::string,
private statusCode::integer,
private statusMsg::string,
private headers::map,
private body::bytes
public onCreate(response::bytes) => {
local(break) = #response->find('\r\n\r\n')
.'headerBytes' = #response->sub(1, #break + 3)
.'body' = #response->sub(#break + 4)
.populateHeaderInfo
}
// From curl->raw
public onCreate(response::staticarray) => {
local(header_data) = #response->get(2)
// For some reason, it keeps all the intermediate headers
// so remove all previous headers (such as auth chalenges)
local(headers) = array
local(break)
while(#break := #header_data->find('\r\n\r\n')) => {
#headers->insert(#header_data->sub(1, #break+3))
#header_data = #header_data->sub(#break+4)
}
.`headerBytes` = #headers->last
.'body' = #response->get(3)
.populateHeaderInfo
}
// Getters
public
headerBytes => .`headerBytes`,
protocol => .`protocol`,
statusCode => .`statusCode`,
statusMsg => .`statusMsg`,
headers => .`headers`,
body => .`body`
public headerString => .'headerBytes'->exportAs(`ISO-8859-1`)
public header(key::string) => .headers->find(#key)
public bodyString(charset::string) => .'body'->exportAs(#charset)
public bodyString => {
// Code adapted from include_url
// auto-discover charset
local(charset) = string_findregexp(.headerString, -find='(?i)charset\\s*=\\s*([\\w\\-]+)')
if(#charset->size >= 2) => {
#charset = #charset->get(2)
else
// charset not found in headers, try meta on page
#charset = string_findregexp(.'body', -find='(?i)charset\\s*=\\s*([\\w\\-]+)')
#charset->size >= 2
? #charset = #charset->get(2)
| #charset = 'utf-8'
}
#charset == 'ISO-8859-1'
? #charset = 'Windows-1252'
return .bodyString(#charset)
}
private populateHeaderInfo => {
local(tmp_headers) = .headerString->asCopy
local(end_status) = #tmp_headers->find('\r\n')
local(message) = #tmp_headers->sub(1, #end_status - 1)->split(' ')
#tmp_headers
->remove(1, #end_status + 1)
& replace('\r\n ' , ' ')
& replace('\r\n\t', '\t')
& removeTrailing('\r\n')
.'headers' = map
with header in #tmp_headers->split('\r\n')
let key = #header->sub(1, #header->find(':') - 1)
let val = #header->sub(#header->find(':') + 1)
let cur = .'headers'->find(#key)
do {
#val->trim
// Taking advantage of #cur being a references in the else clause
#cur == void
? .'headers'->insert(#key=#val)
| #cur->append(',' + #val)
}
.'protocol' = string(#message->get(1))
.'statusCode' = integer(#message->get(2))
.'statusMsg' = string(#message->get(3))
}
}