Estou tentando comparar duas variáveis de servidor como parte de uma condição de reescrita de URL. Mas primeiro, algum contexto...
No IIS, se você solicitar http://www.example.com/foo
e foo
for um diretório, o IIS enviará um redirecionamento 302 "Objeto movido" http://www.example.com/foo/
como um "redirecionamento de cortesia" (Fonte).
Se você estiver usando IIS+ARR como proxy reverso com descarregamento de SSL, a solicitação que o nó IIS de back-end recebe será por http, não por https.
Combine esses dois comportamentos e os redirecionamentos de cortesia do IIS eliminarão o SSL. O redirecionamento de cortesia usa o mesmo esquema da solicitação que o IIS recebeu (Fonte), http neste caso em vez de https.
Gostaria de criar uma regra de reescrita de saída que compare o URL de entrada com o cabeçalho Location de saída e reescreva-o de http para https neste caso:
- A resposta é um redirecionamento:
{RESPONSE_STATUS}
é 302 - A solicitação recebida foi via SSL:
{HTTPS}
está "ativada" - O URL recebido não termina com uma barra.
- O cabeçalho do local de saída termina em uma barra.
Todos os itens acima são tratados na pré-condição. A parte complicada é a última parte:
- O caminho do cabeçalho Location de saída é o mesmo do URL de entrada com uma barra anexada.
Abaixo está o código que tenho até agora. A pré-condição e a reescrita do cabeçalho funcionam bem. No entanto, a condição causa um erro 500 (erro do módulo de reescrita de URL), provavelmente porque estou usando {REQUEST_URI}
no padrão. Tentei separar a condição em duas e usar grupos de captura, mas também não funcionou. Alguma ideia?
<rule name="Fix: Courtesy Redirect + SSL Offloading = SSL dropped" preCondition="Courtesy Redirect Drops SSL" enabled="true">
<match serverVariable="RESPONSE_LOCATION" pattern="^http://(.+/)$" />
<conditions>
<add input="{RESPONSE_LOCATION}" pattern="{REQUEST_URI}/" />
</conditions>
<action type="Rewrite" value="https://{R:1}" />
</rule>
<preConditions>
<preCondition name="Courtesy Redirect Drops SSL">
<add input="{RESPONSE_STATUS}" pattern="^302$" />
<add input="{HTTPS}" pattern="^on$" />
<add input="{REQUEST_URI}" pattern=".*[^/]$" />
<add input="{RESPONSE_LOCATION}" pattern="^http://.+/$" />
</preCondition>
</preConditions>
Responder1
Você pode usar umprovedor de reescrita personalizado.Um provedor é um código C# que transforma uma string em outra string. Você pode então usá-lo de maneira semelhante a como usaria o mapa de reescrita:
Você pode escolher um separador que não seja válido em um URL. (Talvez use espaço ou algo parecido. Usarei |
para que fique visível neste post, mas você deve escolher alguma outra string.)
Você escreverá uma regra para definir o valor da variável do servidor IsItMatching
. O valor da variável do servidor será definido usando seu provedor de reescrita de URL personalizado:
{provider_name:{server_variable_1}|{server_variable_2}}
O código C# que implementa o provedor fará isso (pseudocódigo, sem verificação de erros):
string Rewrite(string input)
{
string[] inputVariables = input.split(separator);
if (inputVariables[0] == inputVariables[1] + "/")
return "yes";
else
return "no";
}
Então você escreverá mais uma regra para verificar se o valor da IsItMatching
variável do servidor é “sim” ou “não”.