Azure App Service is a service used to create and deploy scalable, mission-critical web apps.
Hello Aryaa Kotian,
The redirect issue in your WordPress reverse proxy setup where the homepage loads correctly on webtier.idealake.com but other pages bounce to apptier.idealake.com with a 200 status (no 301 redirect) happens because the URL Rewrite rule in web.config isn't properly preserving the original host header or handling WordPress's internal URL generation, causing the backend app tier to respond with absolute URLs pointing to itself instead of the proxy domain. The wp-admin redirect to home is working as intended, but the 200 status on other pages indicates internal rewrites are leaking through without proxy masking. Azure App Service absolutely supports reverse proxies between two apps using the ReverseProxy extension and URL Rewrite it's a standard pattern for web/app tier separation but your rules need tweaks for WordPress's relative/absolute URL logic and header forwarding.
Root Cause
- Host Header Leakage: WordPress on the app tier generates links/forms based on its own domain (apptier.idealake.com) since the request host isn't forwarded correctly, leading to "internal" 200 responses that browsers interpret as valid but with wrong origins.
- No Outbound Rules: Inbound rewrites forward requests, but responses from app tier contain unrewritten URLs (e.g., in HTML links, Location headers), causing the leak.
- Extension Limitations: ReverseProxy(1.0.4) handles basic forwarding but needs ARR (Application Request Routing) enabled for full header preservation and outbound rewriting in IIS on Azure.
Step-by-Step Fix
1. Enable ARR and Update Web.config on Web Tier
First, ensure ARR is active (it's bundled in Azure App Service but proxy mode needs explicit config). Install/enable via Kudu if needed (Site Extensions > ARR), then revise your web.config for bidirectional rewriting:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<!-- Block/Redirect wp-admin to home -->
<rule name="Block wp-admin for public" stopProcessing="true">
<match url="^wp-admin(/.*)?$" ignoreCase="true" />
<action type="Redirect" url="https://webtier.idealake.com/" redirectType="Found" />
</rule>
<!-- Reverse proxy all other requests to app tier -->
<rule name="ReverseProxyToAppTier" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^webtier\.idealake\.com$" />
</conditions>
<action type="Rewrite" url="https://apptier.idealake.com/{R:1}" appendQueryString="true" logRewrittenUrl="true" />
<serverVariables>
<set name="HTTP_X_ORIGINAL_HOST" value="{HTTP_HOST}" />
<set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
<set name="HTTP_X_FORWARDED_PROTO" value="https" />
</serverVariables>
</rule>
</rules>
<!-- Outbound rules to rewrite app tier URLs back to web tier -->
<outboundRules rewriteBefore="true">
<rule name="ReverseProxyOutboundRule" preCondition="IsHtmlResponse">
<match filterByTags="A,Form,Img" pattern="^https?://apptier\.idealake\.com/(.*)" />
<action type="Rewrite" value="https://webtier.idealake.com/{R:1}" />
</rule>
<rule name="ReverseProxyOutboundRule2" preCondition="IsHtmlResponse">
<match filterByTags="A,Form,Img" pattern="^apptier\.idealake\.com/(.*)" />
<action type="Rewrite" value="https://webtier.idealake.com/{R:1}" />
</rule>
<preConditions>
<preCondition name="IsHtmlResponse">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
<!-- Enable ARR proxy globally (add if missing) -->
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
- Key Changes:
- Added conditions to match only webtier host.
- Server variables forward original host/proto to app tier (prevents WordPress from using backend domain).
- Outbound rules rewrite links/forms/images in HTML responses back to webtier (catches both http/https variants).
-
logRewrittenUrl="true"for debugging in Kudu logs.
Save, then restart the web tier App Service (Overview > Restart).
2. Update wp-config.php on App Tier
Your current config is mostly good (HTTPS detection, WP_HOME/SITEURL set to webtier), but add host header preservation and disable canonical redirects to stop internal URL generation:
<?php
// ... existing code ...
// Preserve original host from proxy
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
// Force all URLs to proxy domain
define('WP_HOME', 'https://webtier.idealake.com');
define('WP_SITEURL', 'https://webtier.idealake.com');
define('WP_CONTENT_URL', 'https://webtier.idealake.com/wp-content');
// Disable canonical redirects (prevents wp-admin/home leaks)
remove_action('template_redirect', 'redirect_canonical');
define('FORCE_SSL_ADMIN', true);
// Relative paths for content (helps with proxy)
define('DOMAIN_CURRENT_SITE', $_SERVER['HTTP_HOST']);
// ... rest of your config ...
- This ensures WordPress on app tier thinks it's running under webtier, generating correct URLs without redirects.
3. Test and Debug
- Clear Caches: On both tiers, clear WordPress cache (if using plugins like W3 Total Cache) and browser cache. Test incognito.
- Verify Flow:
- Homepage: webtier.idealake.com → Rewrites to apptier.idealake.com/ → Response rewritten back → Loads on webtier.
- Other pages: e.g., webtier.idealake.com/about → Rewrites to apptier.idealake.com/about → No leak to apptier.
- wp-admin: webtier.idealake.com/wp-admin → Redirects to webtier home (as per rule).
- Logs Check: In Azure portal > Web Tier App Service > Log stream (real-time) or Diagnose and solve problems > Application Logs. Look for rewrite matches (e.g., "Rewritten URL: https://apptier...") or 200s with wrong Location headers.
- Kudu Access: Site > Development Tools > Advanced Tools > Go > Debug console > LogFiles > Check for URL Rewrite logs.
- Common Pitfalls:
- If still 200 to apptier: Add
<set name="HTTP_X_ORIGINAL_URL" value="{R:1}" />in serverVariables for full path forwarding. - wp-admin access: For admin users, add IP whitelist or basic auth on web tier rule:
<conditions><add input="{REMOTE_ADDR}" pattern="your-ip" /></conditions>. - HTTPS Only: Ensure both apps have "HTTPS Only" enabled (Configuration > General settings).
- If still 200 to apptier: Add
4. Alternative: Use Azure Front Door for Robust Proxy
If web.config tweaks are finicky (WordPress can override rewrites), migrate to Azure Front Door as a global reverse proxy:
- Create Front Door > Backend pools: Add webtier as pool (no app tier exposure).
- Routing rules: Forward * to webtier pool, override host header to apptier for backend.
- Rules engine: Redirect wp-admin/* to /, rewrite others with host preservation.
- Benefits: Handles SSL termination, caching, and WAF—more reliable than ARR for production WordPress.
This setup works well for WordPress multi-tier (web for static/security, app for dynamic)—test incrementally (homepage first, then pages). If logs show specific errors (e.g., 502 on rewrite), share for fine-tuning.
Best Regards,
Jerald Felix