@@ -165,6 +165,133 @@ function split_scopes(value)
165165 return String[p for p in parts if ! isempty (p)]
166166end
167167
168+ function parse_www_authenticate (header:: AbstractString )
169+ challenges = WWWAuthenticateChallenge[]
170+ idx = firstindex (header)
171+ stop = lastindex (header)
172+ while true
173+ idx = skip_delimiters (header, idx, stop)
174+ idx > stop && break
175+ scheme, idx = read_token (header, idx, stop)
176+ isempty (scheme) && break
177+ params = Dict {String,String} ()
178+ token = nothing
179+ seen_param = false
180+ while true
181+ idx = skip_spaces (header, idx, stop)
182+ idx > stop && break
183+ if header[idx] == ' ,'
184+ next_idx = Base. nextind (header, idx)
185+ peek_idx = skip_delimiters (header, next_idx, stop)
186+ peek_token, after_peek = read_token (header, peek_idx, stop)
187+ if isempty (peek_token)
188+ idx = after_peek
189+ continue
190+ end
191+ if after_peek <= stop && header[after_peek] == ' ='
192+ idx = peek_idx
193+ else
194+ idx = next_idx
195+ break
196+ end
197+ end
198+ key_start = idx
199+ key, idx = read_token (header, idx, stop)
200+ isempty (key) && break
201+ idx = skip_spaces (header, idx, stop)
202+ if idx <= stop && header[idx] == ' ='
203+ idx = Base. nextind (header, idx)
204+ idx = skip_spaces (header, idx, stop)
205+ value, idx = read_value (header, idx, stop)
206+ params[String (key)] = value
207+ seen_param = true
208+ else
209+ if seen_param || token != = nothing
210+ idx = key_start
211+ break
212+ end
213+ token = String (key)
214+ end
215+ end
216+ push! (challenges, WWWAuthenticateChallenge (String (scheme); token, params))
217+ end
218+ return challenges
219+ end
220+
221+ function skip_spaces (str, idx, stop)
222+ while idx <= stop
223+ c = str[idx]
224+ if c == ' ' || c == ' \t '
225+ idx = Base. nextind (str, idx)
226+ else
227+ break
228+ end
229+ end
230+ return idx
231+ end
232+
233+ function skip_delimiters (str, idx, stop)
234+ while idx <= stop
235+ c = str[idx]
236+ if c == ' ' || c == ' \t ' || c == ' ,'
237+ idx = Base. nextind (str, idx)
238+ else
239+ break
240+ end
241+ end
242+ return idx
243+ end
244+
245+ function read_token (str, idx, stop)
246+ start = idx
247+ while idx <= stop
248+ c = str[idx]
249+ if c == ' ' || c == ' \t ' || c == ' =' || c == ' ,' || c == ' "'
250+ break
251+ end
252+ idx = Base. nextind (str, idx)
253+ end
254+ idx == start && return " " , idx
255+ last = Base. prevind (str, idx)
256+ return String (str[start: last]), idx
257+ end
258+
259+ function read_value (str, idx, stop)
260+ idx > stop && return " " , idx
261+ if str[idx] == ' "'
262+ idx = Base. nextind (str, idx)
263+ buf = IOBuffer ()
264+ escaped = false
265+ while idx <= stop
266+ c = str[idx]
267+ if escaped
268+ write (buf, c)
269+ escaped = false
270+ elseif c == ' \\ '
271+ escaped = true
272+ elseif c == ' "'
273+ idx = Base. nextind (str, idx)
274+ break
275+ else
276+ write (buf, c)
277+ end
278+ idx = Base. nextind (str, idx)
279+ end
280+ return String (take! (buf)), idx
281+ end
282+ start = idx
283+ while idx <= stop
284+ c = str[idx]
285+ if c == ' ,' || c == ' ' || c == ' \t '
286+ break
287+ end
288+ idx = Base. nextind (str, idx)
289+ end
290+ idx == start && return " " , idx
291+ last = Base. prevind (str, idx)
292+ return String (str[start: last]), idx
293+ end
294+
168295function extract_auth_challenges (headers:: HTTP.Headers )
169296 challenges = MCPAuthenticationChallenge[]
170297 for (name, value) in headers
0 commit comments