Como deixar seu site IIS mais inteligente

21 views
Skip to first unread message

Christian Figueiredo

unread,
May 10, 2021, 5:00:31 PM5/10/21
to ColdFusion Brasil
Eae pessoal. Tudo bem?

Estou compartilhando com vocês uma idéia boa do web.config! Depois vocês me digam o que acharam...

Antes de vocês copiarem esse web.config, recomendo que vocês baixem a extensão Rewrite do IIS no site https://www.iis.net/downloads/microsoft/url-rewrite 

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpProtocol>
            <customHeaders>
                <remove name="X-Powered-By" />
                <add name="Access-Control-Allow-Credentials" value="true" />
                <add name="Access-Control-Allow-Methods" value="DELETE, GET, OPTIONS, POST, PUT" />
                <add name="Access-Control-Max-Age" value="600" />
                <add name="Access-Control-Allow-Origin" value="*" />
                <add name="Access-Control-Allow-Headers" value="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With" />
                <add name="Api-Version" value="2" />
            </customHeaders>
        </httpProtocol>
        <handlers>
            <remove name="WebDAV" />
            <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
            <remove name="asp_as_html" />
            <remove name="asp_as_htm" />
            <remove name="OPTIONSVerbHandler" />
            <remove name="TRACEVerbHandler" />
            <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="DELETE,GET,OPTIONS,POST,PUT" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
            <add name="asp_as_html" path="*.html" verb="DELETE,GET,OPTIONS,POST,PUT" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" />
            <add name="asp_as_htm" path="*.htm" verb="DELETE,GET,OPTIONS,POST,PUT" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" />
        </handlers>
        <modules>
            <remove name="WebDAVModule" />
        </modules>
        <security>
            <requestFiltering>
                <verbs allowUnlisted="false">
                    <add verb="DELETE" allowed="true" />
                    <add verb="GET" allowed="true" />
                    <add verb="OPTIONS" allowed="true" />
                    <add verb="POST" allowed="true" />
                    <add verb="PUT" allowed="true" />
                </verbs>
                <fileExtensions>
                    <add fileExtension=".cfm" allowed="true" />
                    <remove fileExtension=".cfm" />
                    <add fileExtension=".cfc" allowed="true" />
                    <remove fileExtension=".cfc" />
                </fileExtensions>
            </requestFiltering>
        </security>
        <defaultDocument>
            <files>
                <clear />
                <add value="index.cfm" />
            </files>
        </defaultDocument>
        <directoryBrowse enabled="true" />
        <urlCompression doStaticCompression="true" doDynamicCompression="true" />
        <rewrite>
            <outboundRules>
                <preConditions>
                    <preCondition name="ResponseIsHtml1">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                    </preCondition>
                </preConditions>
            </outboundRules>
            <rules>
                <rule name="General Level 1" stopProcessing="true">
                    <match url="^([A-Za-z][A-Za-z0-9\-_]+)(/)?$" ignoreCase="false" />
                    <action type="Rewrite" url="/index.cfm?level1={R:1}" appendQueryString="true" />
                    <conditions>
                        <add input="{SCRIPT_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{PATH_INFO}" pattern="^/rest(/)?$" ignoreCase="false" negate="true" />
                    </conditions>
                </rule>
                <rule name="General Level 2" stopProcessing="true">
                    <match url="^([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)(/)?$" ignoreCase="false" />
                    <action type="Rewrite" url="/index.cfm?level1={R:1}&amp;level2={R:2}" appendQueryString="true" />
                    <conditions>
                        <add input="{SCRIPT_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{PATH_INFO}" pattern="^/rest/([A-Za-z][A-Za-z0-9\-_]+)(/)?$" ignoreCase="false" negate="true" />
                    </conditions>
                </rule>
                <rule name="General Level 3" stopProcessing="true">
                    <match url="^([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)(/)?$" ignoreCase="false" />
                    <action type="Rewrite" url="/index.cfm?level1={R:1}&amp;level2={R:2}&amp;level3={R:3}" appendQueryString="true" />
                    <conditions>
                        <add input="{SCRIPT_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{PATH_INFO}" pattern="^/rest/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)(/)?$" ignoreCase="false" negate="true" />
                    </conditions>
                </rule>
                <rule name="General Level 4" stopProcessing="true">
                    <match url="^([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)(/)?$" ignoreCase="false" />
                    <action type="Rewrite" url="/index.cfm?level1={R:1}&amp;level2={R:2}&amp;level3={R:3}&amp;level4={R:4}" appendQueryString="true" />
                    <conditions>
                        <add input="{SCRIPT_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{PATH_INFO}" pattern="^/rest/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)(/)?$" ignoreCase="false" negate="true" />
                    </conditions>
                </rule>
                <rule name="General Level 5" stopProcessing="true">
                    <match url="^([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)(/)?$" ignoreCase="false" />
                    <action type="Rewrite" url="/index.cfm?level1={R:1}&amp;level2={R:2}&amp;level3={R:3}&amp;level4={R:4}&amp;level5={R:5}" appendQueryString="true" />
                    <conditions>
                        <add input="{SCRIPT_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{PATH_INFO}" pattern="^/rest/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)/([A-Za-z][A-Za-z0-9\-_]+)(/)?$" ignoreCase="false" negate="true" />
                    </conditions>
                </rule>
            </rules>
        </rewrite>
        <httpErrors errorMode="Custom">
            <remove statusCode="400" />
            <error statusCode="400" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="401" />
            <error statusCode="401" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="402" />
            <error statusCode="402" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="403" />
            <error statusCode="403" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="404" />
            <error statusCode="404" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="405" />
            <error statusCode="405" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="406" />
            <error statusCode="406" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="408" />
            <error statusCode="408" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="414" />
            <error statusCode="414" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="415" />
            <error statusCode="415" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="429" />
            <error statusCode="429" path="/error.cfm" responseMode="ExecuteURL" />
            <remove statusCode="500" />
            <error statusCode="500" path="/error.cfm" responseMode="ExecuteURL" />
        </httpErrors>
    </system.webServer>
    <system.web>
        <customErrors mode="On">
            <error statusCode="404" redirect="/" />
        </customErrors>
    </system.web>
</configuration>

Com o Rewrite, vocês podem testar seu site da seguinte forma:
Level 1: http://[seusubdominio.]seudominio.com.br/qualquer-coisa
Level 2: http://[seusubdominio.]seudominio.com.br/qualquer-coisa/do-seu-gosto
Pode ficar tranquilo porque esse recurso de transferir os níveis de redirecionamento para as variáveis de URL não interferem na busca dos arquivos de diretório, muito menos nas chamadas de API REST. Se você reparar bem, para cada regra de redirecionamento, eu coloquei uma exceção logo abaixo.
Uma observação: esses redirecionamentos aceitam somente os caracteres numéricos, de A até Z e de a até z, além do traço ou hífem, como você preferir chamar. Eu configurei o redirecionamento como case sensitive (diferenciar maiúsculas de minúsculas) na propriedade ignoreCase="false". Se você preferir que seja case INsensitive, só trocar para true.
Outra observação: se você está acostumado a colocar links para chamar o index.cfm sem explicitar o nome do arquivo, provavelmente poderá dar erro, pois esse recurso privilegia o redirecionamento que sempre será exibido na index.cfm da raiz do seu site. Você pode personalizar esse redirecionamento depois, caso seu index.cfm não seja o arquivo padrão configurado no IIS. Da mesma forma, você poderá alterar os nomes das váriáveis do escopo url de level1, level2 e assim por diante em cada regra. Da mesma forma, pode criar até mais níveis! Por que não?

Outro ponto importante será o fim da TELA CINZA de erro do ColdFusion e o fim do evento onMissingTemplate no seu Application.cfc. Como o onMissingTemplate funciona quando o IIS não encontra uma página cfm ou um componente cfc, o IIS retorna o status HTTP 404 (File Not Found). Para o erro 404 o IIS coloca a página que você quiser no lugar, sem mudar o URL. Nesse caso, configurei para a página error.cfm. O processo funciona da mesma forma quando o ColdFusion retorna ao IIS o erro 500 que representa a exceção geradora da famosa tela cinzenta! Nesse caso, configurei para a mesma página error.cfm que você também pode personalizar. A grande vantagem desse recurso é que você pode apresentar uma tanto uma tela 404 quanto uma tela 500, ambas amigáveis! E o onMissingTemplate funciona somente para os arquivos do ColdFusion! Já esse recurso funciona para qualquer tipo de arquivo! Falando em tipo de arquivo, existe uma particularidade para as páginas .NET. Nesse caso, a Microsoft configurou o IIS para gerar a variável de URL chamada aspxerrorpath. Você pode criar um plano de ação no seu evento onRequestStart para quando essa variável de URL aparecer. Essa particularidade do .NET eu incluí na tag <customErrors>
Message has been deleted

Christian Figueiredo

unread,
May 10, 2021, 9:33:34 PM5/10/21
to ColdFusion Brasil
Uma correção: não é hífem, é hífen...

E o redirecionamento aceita underline (_) também!

Outra coisa importante: Para testar, esqueci de pedir para fazer um dump do escopo URL!

andreas

unread,
May 12, 2021, 4:16:53 AM5/12/21
to cfbr...@googlegroups.com
Grande Christian, perdoe não ter respondido antes. Eu acho muito importante vc receber um feedback, más até agora não tive como. O tempo anda muito corrido. 

Eu queria muito te agradecer pelo conteúdo postado. Ainda não tive a oportunidade de me aprofundizar nisso, mas eu o farei logo que tenha o tempo. Más no que eu vi até agora, eu gostei muito. Para ser sincero, acho que é um dos primeiros conteúdos cfml em Português que tem em atualidade. Precisamos mais disso para a galera cfml. Muito obrigado por compartilhar!


--
--
Você recebeu este e-mail pois está cadastrado na lista ColdFusion Brasil
Para CANCELAR sua assinatura escreva para cfbrasil+u...@googlegroups.com
Para ASSINAR a lista escreva para cfbrasil+...@googlegroups.com
O endereço para ENVIO DE MENSAGENS da lista é cfbr...@googlegroups.com
REGRAS em http://groups.google.com/group/cfbrasil/web/regras-de-boa-convivncia-na-lista
Outras opções disponíveis em http://groups.google.com/group/cfbrasil

---
You received this message because you are subscribed to the Google Groups "ColdFusion Brasil" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cfbrasil+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cfbrasil/c714d1cd-f33d-408c-b4dc-014621693150n%40googlegroups.com.

Christian Figueiredo

unread,
May 12, 2021, 5:23:51 PM5/12/21
to ColdFusion Brasil
Valew Andreas! Inveja de um poliglota como você! Eu mal sei o verbo to be e me viro como posso!

Brincadeira que eu trabalhei na Atos e uma época eu tinha que lidar com os indianos para responder em auditorias...

Nesse fim de semana eu estava montando um guia de boas práticas sobre construção de API's REST que acabou afundando por conta de tantas mudanças das 2 últimas atualizações do 2018...

Vou fazer uns testes mais aprofundados para trazer tudo com plena certeza e nos mínimos detalhes...

Antes de mais nada, muitíssimo obrigado pelo feedback! Espero que muita gente tenha bons proveitos com essa idéia!


Deus abençoe a todos nós CFer's!


Reply all
Reply to author
Forward
0 new messages