| @@ -207,8 +207,37 @@ | ||
| 207 | 207 | ); |
| 208 | 208 | } |
| 209 | 209 | |
| 210 | 210 | /** |
| 211 | + * Build the URL alternation for a server rule. | |
| 212 | + * | |
| 213 | + * The nginx snippet mirrored the cookie and user-agent exclusions but | |
| 214 | + * not this one, so an excluded URL was only excluded while its page was | |
| 215 | + * cold. That is mostly masked — PHP refuses to write a static file for | |
| 216 | + * an excluded URL, so there is usually nothing for nginx to serve — but | |
| 217 | + * it bites whenever a page was cached BEFORE the rule existed: the file | |
| 218 | + * is already on disk, nginx never consults PHP, and the exclusion is | |
| 219 | + * silently ignored until the next purge. (#169) | |
| 220 | + * | |
| 221 | + * `excluded_urls` uses the same glob/substring dialect as the cookie | |
| 222 | + * list, so build_alternation() does the work — including skipping the | |
| 223 | + * `~raw regex` entries, which are PHP-side only. An empty list yields an | |
| 224 | + * empty regex and the caller must omit the rule entirely rather than | |
| 225 | + * emit one that matches every request. | |
| 226 | + * | |
| 227 | + * @param string[] $patterns Raw `excluded_urls` setting. | |
| 228 | + * @return array{regex:string,skipped:int} | |
| 229 | + */ | |
| 230 | + public static function url_rule( array $patterns ): array { | |
| 231 | + $built = self::build_alternation( $patterns ); | |
| 232 | + | |
| 233 | + return array( | |
| 234 | + 'regex' => implode( '|', $built['parts'] ), | |
| 235 | + 'skipped' => $built['skipped'], | |
| 236 | + ); | |
| 237 | + } | |
| 238 | + | |
| 239 | + /** | |
| 211 | 240 | * Translate a list of glob/substring patterns into escaped regex |
| 212 | 241 | * alternation parts, mirroring Glob_Matcher's semantics as closely as |
| 213 | 242 | * a server config can. |
| 214 | 243 | * |