|
19 | 19 |
|
20 | 20 | import CoreFoundation
|
21 | 21 |
|
22 |
| - |
23 |
| -extension _HTTPURLProtocol { |
24 |
| - /// An HTTP header being parsed. |
25 |
| - /// |
26 |
| - /// It can either be complete (i.e. the final CR LF CR LF has been |
27 |
| - /// received), or partial. |
28 |
| - internal enum _ParsedResponseHeader { |
29 |
| - case partial(_ResponseHeaderLines) |
30 |
| - case complete(_ResponseHeaderLines) |
31 |
| - init() { |
32 |
| - self = .partial(_ResponseHeaderLines()) |
33 |
| - } |
34 |
| - } |
35 |
| - /// A type safe wrapper around multiple lines of headers. |
36 |
| - /// |
37 |
| - /// This can be converted into an `HTTPURLResponse`. |
38 |
| - internal struct _ResponseHeaderLines { |
39 |
| - let lines: [String] |
40 |
| - init() { |
41 |
| - self.lines = [] |
42 |
| - } |
43 |
| - init(headerLines: [String]) { |
44 |
| - self.lines = headerLines |
45 |
| - } |
46 |
| - } |
47 |
| -} |
48 |
| - |
49 |
| -extension _HTTPURLProtocol._ParsedResponseHeader { |
50 |
| - /// Parse a header line passed by libcurl. |
51 |
| - /// |
52 |
| - /// These contain the <CRLF> ending and the final line contains nothing but |
53 |
| - /// that ending. |
54 |
| - /// - Returns: Returning nil indicates failure. Otherwise returns a new |
55 |
| - /// `ParsedResponseHeader` with the given line added. |
56 |
| - func byAppending(headerLine data: Data) -> _HTTPURLProtocol._ParsedResponseHeader? { |
57 |
| - // The buffer must end in CRLF |
58 |
| - guard |
59 |
| - 2 <= data.count && |
60 |
| - data[data.endIndex - 2] == _HTTPCharacters.CR && |
61 |
| - data[data.endIndex - 1] == _HTTPCharacters.LF |
62 |
| - else { return nil } |
63 |
| - let lineBuffer = data.subdata(in: Range(data.startIndex..<data.endIndex-2)) |
64 |
| - guard let line = String(data: lineBuffer, encoding: String.Encoding.utf8) else { return nil} |
65 |
| - return byAppending(headerLine: line) |
66 |
| - } |
67 |
| - /// Append a status line. |
68 |
| - /// |
69 |
| - /// If the line is empty, it marks the end of the header, and the result |
70 |
| - /// is a complete header. Otherwise it's a partial header. |
71 |
| - /// - Note: Appending a line to a complete header results in a partial |
72 |
| - /// header with just that line. |
73 |
| - private func byAppending(headerLine line: String) -> _HTTPURLProtocol._ParsedResponseHeader { |
74 |
| - if line.isEmpty { |
75 |
| - switch self { |
76 |
| - case .partial(let header): return .complete(header) |
77 |
| - case .complete: return .partial(_HTTPURLProtocol._ResponseHeaderLines()) |
78 |
| - } |
79 |
| - } else { |
80 |
| - let header = partialResponseHeader |
81 |
| - return .partial(header.byAppending(headerLine: line)) |
82 |
| - } |
83 |
| - } |
84 |
| - private var partialResponseHeader: _HTTPURLProtocol._ResponseHeaderLines { |
85 |
| - switch self { |
86 |
| - case .partial(let header): return header |
87 |
| - case .complete: return _HTTPURLProtocol._ResponseHeaderLines() |
88 |
| - } |
89 |
| - } |
90 |
| -} |
91 |
| -private extension _HTTPURLProtocol._ResponseHeaderLines { |
92 |
| - /// Returns a copy of the lines with the new line appended to it. |
93 |
| - func byAppending(headerLine line: String) -> _HTTPURLProtocol._ResponseHeaderLines { |
94 |
| - var l = self.lines |
95 |
| - l.append(line) |
96 |
| - return _HTTPURLProtocol._ResponseHeaderLines(headerLines: l) |
97 |
| - } |
98 |
| -} |
99 | 22 | internal extension _HTTPURLProtocol._ResponseHeaderLines {
|
100 | 23 | /// Create an `NSHTTPRULResponse` from the lines.
|
101 | 24 | ///
|
|
0 commit comments