Send 103 Early Hints response. Args: headers: List of (name, value) header tuples, typically Link headers Example: [('Link', '</style.css>; rel=preload; as=style')] Raises: InvalidHeaderName: If a header name is not a valid HTTP token.
(headers)
| 138 | - Calls after response has started are silently ignored |
| 139 | """ |
| 140 | def send_early_hints(headers): |
| 141 | """Send 103 Early Hints response. |
| 142 | |
| 143 | Args: |
| 144 | headers: List of (name, value) header tuples, typically Link headers |
| 145 | Example: [('Link', '</style.css>; rel=preload; as=style')] |
| 146 | |
| 147 | Raises: |
| 148 | InvalidHeaderName: If a header name is not a valid HTTP token. |
| 149 | InvalidHeader: If a header value contains invalid characters. |
| 150 | """ |
| 151 | # Don't send after response has started - would break framing |
| 152 | if resp.headers_sent: |
| 153 | return |
| 154 | |
| 155 | # Don't send to HTTP/1.0 clients - they don't support 1xx responses |
| 156 | if req.version < (1, 1): |
| 157 | return |
| 158 | |
| 159 | # Build 103 response |
| 160 | response = b"HTTP/1.1 103 Early Hints\r\n" |
| 161 | for name, value in headers: |
| 162 | if isinstance(name, bytes): |
| 163 | name = name.decode('latin-1') |
| 164 | if isinstance(value, bytes): |
| 165 | value = value.decode('latin-1') |
| 166 | |
| 167 | # Validate header name and value using the same checks as |
| 168 | # Response.process_headers — defense-in-depth against |
| 169 | # HTTP response splitting via CRLF injection. |
| 170 | if not TOKEN_RE.fullmatch(name): |
| 171 | raise InvalidHeaderName('%r' % name) |
| 172 | if not HEADER_VALUE_RE.fullmatch(value): |
| 173 | # Pass only the name — the invalid value may contain |
| 174 | # sensitive data that shouldn't cross security boundaries |
| 175 | # via exception propagation (browsers/proxies may forward |
| 176 | # it to untrusted parties). |
| 177 | raise InvalidHeader('%r' % name) |
| 178 | |
| 179 | value = value.strip(" \t") |
| 180 | response += f"{name}: {value}\r\n".encode('latin-1') |
| 181 | response += b"\r\n" |
| 182 | |
| 183 | util.write(sock, response) |
| 184 | |
| 185 | return send_early_hints |
| 186 |
nothing calls this directly
no test coverage detected