HTTP_URL、REQUEST_URI与其他IIS变量的差异及存在意义咨询
Great question—this is such a common point of confusion when working with IIS rewrite rules, since the official docs often skip over these nuanced distinctions. Let’s break down each variable, their hidden differences, and why so many seemingly identical ones exist:
First, a Critical Distinction: Server Variables vs. Rewrite Backreferences
Let’s start with {R:1} because it’s not actually a server variable at all—it’s a rewrite rule backreference. In your example, your regex probably captured the full path (like ^/(.*)$), so {R:1} matched /path/to/file.ext. But this value depends entirely on the regex in your rewrite rule: if you’d written ^/path/(.*)$, {R:1} would be to/file.ext instead. It’s tied directly to your rule’s pattern, not the original request.
Server Variable Deep Dive (Beyond Query Strings)
Now let’s look at the actual server variables, where the real hidden differences lie:
{URL} vs. {PATH_INFO} vs. {URL_PATH_INFO}
At first glance these look identical, but their behavior diverges when dealing with extended paths beyond script mappings:
{URL}: IIS’s internal request path (decoded, no query string). This is the full path IIS uses to map the request to a handler (e.g., ASP.NET, PHP). If you request/app.php/extra/path,{URL}will be/app.php/extra/path.{PATH_INFO}: A CGI/ISAPI standard variable that refers to the part of the URL after the script/handler mapping. Using the same example/app.php/extra/path, if.phpis mapped to your PHP handler,{PATH_INFO}will be/extra/path(the part beyondapp.php).{URL_PATH_INFO}: IIS’s wrapper aroundPATH_INFO—behavior is nearly identical, but there are tiny edge-case differences in classic vs. integrated pipeline modes. For most use cases, you can treat them the same.
{HTTP_URL} vs. {REQUEST_URI} vs. {UNENCODED_URL}
These all include the query string in your example, but their encoding and purpose differ:
{UNENCODED_URL}: The raw, unmodified URL as it was sent by the client, including all original URL-encoded characters (e.g.,%20stays%20instead of becoming a space). Use this when you need to preserve the exact request encoding (critical for handling special characters or legacy systems).{HTTP_URL}: The decoded version of the full request path + query string, parsed directly from the HTTP request line by IIS. It’s IIS’s native representation of the full request path.{REQUEST_URI}: Added to IIS to compatible with Apache and CGI/PHP ecosystems. Its behavior matches Apache’sREQUEST_URI(decoded path + query string), making it the go-to choice if you’re migrating Apache rules or running apps that expect this variable (like most PHP frameworks).
Why Do So Many "Identical" Variables Exist?
It all boils down to compatibility and historical context:
- Multi-standard support: IIS needs to work with CGI, ISAPI, Apache, and its own internal request pipeline. Each variable maps to a different standard (e.g.,
PATH_INFOfor CGI,REQUEST_URIfor Apache). - Encoding needs: Some scenarios require raw encoded URLs, others need decoded paths—having separate variables avoids forcing you to re-encode/decode manually.
- Legacy compatibility: Older IIS versions and applications relied on specific variables, so newer versions keep them around to avoid breaking existing code.
Quick Usage Cheat Sheet
- Use
{REQUEST_URI}for Apache-compatible rules or PHP apps - Use
{UNENCODED_URL}when you need to preserve raw client request encoding - Use
{PATH_INFO}if you’re working with script extensions and need the trailing path segment - Remember
{R:n}is a rule-specific backreference, not a global server variable
内容的提问来源于stack exchange,提问作者Rudey

