diff --git a/std/net/curl.d b/std/net/curl.d index 2fcbf9431..6aec366c6 100644 --- a/std/net/curl.d +++ b/std/net/curl.d @@ -2419,8 +2419,8 @@ struct HTTP @system @property void onReceiveHeader(void delegate(in char[] key, in char[] value) callback) { - import std.algorithm.searching : startsWith; - import std.regex : regex, match; + import std.algorithm.searching : findSplit, startsWith; + import std.string : indexOf, chomp; import std.uni : toLower; // Wrap incoming callback in order to separate http status line from @@ -2447,21 +2447,18 @@ struct HTTP return; } - // Normal http header - auto m = match(cast(char[]) header, regex("(.*?): (.*)$")); - - auto fieldName = m.captures[1].toLower().idup; + auto m = header.findSplit(": "); + auto fieldName = m[0].toLower(); + auto fieldContent = m[2].chomp; if (fieldName == "content-type") { - auto mct = match(cast(char[]) m.captures[2], - regex("charset=([^;]*)", "i")); - if (!mct.empty && mct.captures.length > 1) - charset = mct.captures[1].idup; + auto io = indexOf(fieldContent, "charset=", No.caseSensitive); + if (io != -1) + charset = fieldContent[io + "charset=".length .. $].findSplit(";")[0].idup; } - - if (!m.empty && callback !is null) - callback(fieldName, m.captures[2]); - headersIn[fieldName] = m.captures[2].idup; + if (!m[1].empty && callback !is null) + callback(fieldName, fieldContent); + headersIn[fieldName] = fieldContent.idup; } catch (UTFException e) { @@ -2479,20 +2476,27 @@ struct HTTP /// Parse status line, as received from / generated by cURL. private static bool parseStatusLine(const char[] header, out StatusLine status) @safe { - import std.conv : to; - import std.regex : regex, match; + import std.algorithm.searching : findSplit, startsWith; + import std.conv : to, ConvException; - const m = match(header, regex(r"^HTTP/(\d+)(?:\.(\d+))? (\d+)(?: (.*))?$")); - if (m.empty) - return false; // Invalid status line - else + if (!header.startsWith("HTTP/")) + return false; + + try { - status.majorVersion = to!ushort(m.captures[1]); - status.minorVersion = m.captures[2].length ? to!ushort(m.captures[2]) : 0; - status.code = to!ushort(m.captures[3]); - status.reason = m.captures[4].idup; + const m = header["HTTP/".length .. $].findSplit(" "); + const v = m[0].findSplit("."); + status.majorVersion = to!ushort(v[0]); + status.minorVersion = v[1].length ? to!ushort(v[2]) : 0; + const s2 = m[2].findSplit(" "); + status.code = to!ushort(s2[0]); + status.reason = s2[2].idup; return true; } + catch (ConvException e) + { + return false; + } } @safe unittest @@ -2505,6 +2509,12 @@ struct HTTP // The HTTP2 protocol is binary; cURL generates this fake text header. assert(parseStatusLine("HTTP/2 200", status) && status == StatusLine(2, 0, 200, null)); + + assert(!parseStatusLine("HTTP/2", status)); + assert(!parseStatusLine("HTTP/2 -1", status)); + assert(!parseStatusLine("HTTP/2 200", status)); + assert(!parseStatusLine("HTTP/2.X 200", status)); + assert(!parseStatusLine("HTTP|2 200", status)); } /** Time condition enumeration as an alias of $(REF CurlTimeCond, etc,c,curl)