48
48
--- @private
49
49
local parser = {}
50
50
51
+ --- @class rest.Result
52
+ --- @field requests rest.Response_[]
53
+ --- @field statistics table<string,string> Response statistics
54
+
55
+ --- @class rest.Response_
56
+ --- @field request rest.RequestCore
57
+ --- @field response rest.Response
58
+
59
+ --- @class rest.RequestCore
60
+ --- @field method string
61
+ --- @field url string
62
+ --- @field http_version string
63
+ --- @field headers table<string,string[]>
64
+
51
65
--- @package
52
66
--- @param str string
53
- --- @return rest.Response.status
54
- function parser .parse_verbose_status (str )
55
- local version , code , text = str :match (" ^(%S+) (%d+) ?(.*)" )
67
+ --- @return rest.RequestCore ?
68
+ function parser .parse_req_info (str )
69
+ local method , url , version = str :match (" ^([A-Z]+) (.+) (HTTP/[%d%.]+)" )
70
+ if not method then
71
+ return
72
+ end
73
+ return {
74
+ method = method ,
75
+ url = url ,
76
+ http_version = version ,
77
+ headers = {},
78
+ }
79
+ end
80
+
81
+ function parser .parse_req_header (str , requests )
82
+ local info = parser .parse_req_info (str )
83
+ if info then
84
+ table.insert (requests , {
85
+ request = info ,
86
+ response = {},
87
+ })
88
+ return
89
+ end
90
+ local req = requests [# requests ].request
91
+ local key , value = parser .parse_header_pair (str )
92
+ if key then
93
+ if not req .headers [key ] then
94
+ req .headers [key ] = {}
95
+ end
96
+ table.insert (req .headers [key ], value )
97
+ else
98
+ log .error (" Error while parsing verbose curl output header:" , str )
99
+ end
100
+ end
101
+
102
+ --- @package
103
+ --- @param str string
104
+ --- @return rest.Response.status ?
105
+ function parser .parse_res_status (str )
106
+ local version , code , text = str :match (" ^(HTTP/[%d%.]+) (%d+) ?(.*)" )
107
+ if not version then
108
+ return
109
+ end
56
110
return {
57
111
version = version ,
58
112
code = tonumber (code ),
@@ -73,22 +127,49 @@ function parser.parse_header_pair(str)
73
127
end
74
128
75
129
--- @package
130
+ --- @param str string
131
+ function parser .parse_res_header (str , requests )
132
+ local status = parser .parse_res_status (str )
133
+ if status then
134
+ -- reset response object
135
+ requests [# requests ].response = {
136
+ status = status ,
137
+ headers = {},
138
+ }
139
+ return
140
+ end
141
+ local res = requests [# requests ].response
142
+ local key , value = parser .parse_header_pair (str )
143
+ if key then
144
+ if not res .headers [key ] then
145
+ res .headers [key ] = {}
146
+ end
147
+ table.insert (res .headers [key ], value )
148
+ else
149
+ log .error (" Error while parsing verbose curl output header:" , str )
150
+ end
151
+ end
152
+
153
+ --- @package
154
+ --- @param idx number
76
155
--- @param line string
77
- --- @return { prefix : string,str : string ?}| nil
78
- function parser .parse_verbose_line ( line )
156
+ --- @return { idx : number, prefix: string,str : string ?}| nil
157
+ function parser .lex_verbose_line ( idx , line )
79
158
local prefix , str = line :match (" (.) ?(.*)" )
159
+ log .debug (" line" , idx , line )
80
160
if not prefix then
81
- log .error (" Error while parsing verbose curl output: \n " .. line )
161
+ log .error (( " Error while parsing verbose curl output at line %d: " ): format ( idx ), line )
82
162
return
83
163
end
84
164
return {
165
+ idx = idx ,
85
166
prefix = prefix ,
86
167
str = str ,
87
168
}
88
169
end
89
170
90
171
local _VERBOSE_PREFIX_META = " *"
91
- local _VERBOSE_PREFIX_REQ_HEADER = " >"
172
+ local VERBOSE_PREFIX_REQ_HEADER = " >"
92
173
local _VERBOSE_PREFIX_REQ_BODY = " }"
93
174
local VERBOSE_PREFIX_RES_HEADER = " <"
94
175
-- NOTE: we don't parse response body with trace output. response body will
@@ -114,35 +195,32 @@ function parser.parse_stat_pair(str)
114
195
end
115
196
116
197
--- @param lines string[]
117
- --- @return rest.Response
198
+ --- @return rest.Result
118
199
function parser .parse_verbose (lines )
119
- local response = {
120
- headers = {},
200
+ --- @type rest.Result
201
+ local result = {
202
+ --- @type rest.Response_[]
203
+ requests = {},
204
+ --- @type table<string,string> Response statistics
121
205
statistics = {},
122
206
}
123
- vim .iter (lines ):map (parser .parse_verbose_line ):each (function (ln )
124
- if ln .prefix == VERBOSE_PREFIX_RES_HEADER then
125
- if not response .status then
126
- -- response status
127
- response .status = parser .parse_verbose_status (ln .str )
128
- else
129
- -- response header
130
- local key , value = parser .parse_header_pair (ln .str )
131
- if key then
132
- if not response .headers [key ] then
133
- response .headers [key ] = {}
134
- end
135
- table.insert (response .headers [key ], value )
136
- end
137
- end
207
+ -- ignore last newline
208
+ if lines [# lines ] == " " then
209
+ lines [# lines ] = nil
210
+ end
211
+ vim .iter (lines ):enumerate ():map (parser .lex_verbose_line ):each (function (ln )
212
+ if ln .prefix == VERBOSE_PREFIX_REQ_HEADER then
213
+ parser .parse_req_header (ln .str , result .requests )
214
+ elseif ln .prefix == VERBOSE_PREFIX_RES_HEADER then
215
+ parser .parse_res_header (ln .str , result .requests )
138
216
elseif ln .prefix == VERBOSE_PREFIX_STAT then
139
217
local key , value = parser .parse_stat_pair (ln .str )
140
218
if key then
141
- response .statistics [key ] = value
219
+ result .statistics [key ] = value
142
220
end
143
221
end
144
222
end )
145
- return response
223
+ return result
146
224
end
147
225
148
226
--- Builder ---
330
408
331
409
--- Send request via `curl` cli
332
410
--- @param request rest.Request Request data to be passed to cURL
333
- --- @return nio.control.Future future Future containing rest.Response
411
+ --- @return nio.control.Future future Future containing rest.Result
334
412
function curl .request (request )
335
413
local progress_handle = progress .handle .create ({
336
414
title = " Executing" ,
@@ -352,9 +430,9 @@ function curl.request(request)
352
430
progress_handle :report ({
353
431
message = " Parsing response..." ,
354
432
})
355
- local response = parser .parse_verbose (vim .split (sc .stderr , " \n " ))
356
- response .body = sc .stdout
357
- future .set (response )
433
+ local result = parser .parse_verbose (vim .split (sc .stderr , " \n " ))
434
+ result . requests [ # result . requests ]. response .body = sc .stdout
435
+ future .set (result )
358
436
progress_handle :report ({
359
437
message = " Success" ,
360
438
})
0 commit comments