Skip to content

Commit 000edec

Browse files
Merge pull request #299082 from MicrosoftDocs/main
Merged by Learn.Build PR Management system
2 parents e4fbfdd + a817547 commit 000edec

28 files changed

+456
-79
lines changed

articles/application-gateway/application-gateway-troubleshooting-502.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ services: application-gateway
55
author: greg-lindsay
66
ms.service: azure-application-gateway
77
ms.topic: troubleshooting
8-
ms.date: 05/19/2023
8+
ms.date: 04/29/2025
99
ms.author: greglin
1010
ms.custom: devx-track-azurepowershell
1111
---
@@ -87,9 +87,9 @@ The following table lists the values associated with the default health probe:
8787
8888
### Solution
8989
90-
* Host value of the request will be set to 127.0.0.1. Ensure that a default site is configured and is listening at 127.0.0.1.
90+
* Host value of the request is set to 127.0.0.1. Ensure that a default site is configured and is listening at 127.0.0.1.
9191
* Protocol of the request is determined by the BackendHttpSetting protocol.
92-
* URI Path will be set to */*.
92+
* URI Path is set to */*.
9393
* If BackendHttpSetting specifies a port other than 80, the default site should be configured to listen at that port.
9494
* The call to `protocol://127.0.0.1:port` should return an HTTP result code of 200. This code should be returned within the 30-second timeout period.
9595
* Ensure the configured port is open and there are no firewall rules or Azure Network Security Groups blocking incoming or outgoing traffic on the port configured.
@@ -130,7 +130,7 @@ Validate that the Custom Health Probe is configured correctly, as shown in the p
130130
131131
### Cause
132132
133-
When a user request is received, the application gateway applies the configured rules to the request and routes it to a backend pool instance. It waits for a configurable interval of time for a response from the backend instance. By default, this interval is **20** seconds. In Application Gateway v1, if the application gateway doesn't receive a response from backend application in this interval, the user request gets a 502 error. In Application Gateway v2, if the application gateway doesn't receive a response from the backend application in this interval, the request will be tried against a second backend pool member. If the second request fails the user request gets a 504 error.
133+
When a user request is received, the application gateway applies the configured rules to the request and routes it to a backend pool instance. It waits for a configurable interval of time for a response from the backend instance. By default, this interval is **20** seconds. In Application Gateway v1, if the application gateway doesn't receive a response from backend application in this interval, the user request gets a 502 error. In Application Gateway v2, if the application gateway doesn't receive a response from the backend application in this interval, the request is tried against a second backend pool member. If the second request fails the user request gets a 504 error.
134134
135135
### Solution
136136
@@ -192,17 +192,17 @@ If all the instances of BackendAddressPool are unhealthy, then the application g
192192

193193
Ensure that the instances are healthy and the application is properly configured. Check if the backend instances can respond to a ping from another VM in the same VNet. If configured with a public end point, ensure a browser request to the web application is serviceable.
194194

195-
## Upstream SSL certificate does not match
195+
## Upstream SSL certificate doesn't match
196196

197197
### Cause
198198

199-
The TLS certificate installed on backend servers does not match the hostname received in the Host request header.
199+
The TLS certificate installed on backend servers doesn't match the hostname received in the Host request header.
200200

201-
In scenarios where End-to-end TLS is enabled, a configuration that is achieved by editing the appropriate "Backend HTTP Settings", and changing there the configuration of the "Backend protocol" setting to HTTPS, it is mandatory to ensure that the CNAME of the TLS certificate installed on backend servers matches the hostname coming to the backend in the HTTP host header request.
201+
In scenarios where End-to-end TLS is enabled, a configuration that is achieved by editing the appropriate "Backend HTTP Settings", and changing there the configuration of the "Backend protocol" setting to HTTPS, it's mandatory to ensure that the DNS NAME of the TLS certificate installed on backend servers matches the hostname coming to the backend in the HTTP host header request.
202202

203-
As a reminder, the effect of enabling on the "Backend HTTP Settings" the option of protocol HTTPS rather than HTTP, will be that the second part of the communication that happens between the instances of the Application Gateway and the backend servers will be encrypted with TLS.
203+
As a reminder, the effect of enabling on the "Backend HTTP Settings" the option of protocol HTTPS rather than HTTP, is that the second part of the communication that happens between the instances of the Application Gateway and the backend servers are encrypted with TLS.
204204

205-
Due to the fact that by default Application Gateway sends the same HTTP host header to the backend as it receives from the client, you will need to ensure that the TLS certificate installed on the backend server, is issued with a CNAME that matches the host name received by that backend server in the HTTP host header.
205+
Due to the fact that by default Application Gateway sends the same HTTP host header to the backend as it receives from the client, you need to ensure that the TLS certificate installed on the backend server, is issued with a DNS NAME that matches the host name received by that backend server in the HTTP host header.
206206
Remember that, unless specified otherwise, this hostname would be the same as the one received from the client.
207207

208208
For example:
@@ -211,16 +211,16 @@ Imagine that you have an Application Gateway to serve the https requests for dom
211211

212212
On that Application Gateway you should have a listener for the host www.contoso.com with a rule that has the "Backed HTTP Setting" forced to use protocol HTTPS (ensuring End-to-end TLS). That same rule could have configured a backend pool with two VMs running IIS as Web servers.
213213

214-
As we know enabling HTTPS in the "Backed HTTP Setting" of the rule will make the second part of the communication that happens between the Application Gateway instances and the servers in the backend to use TLS.
214+
As we know enabling HTTPS in the "Backed HTTP Setting" of the rule makes the second part of the communication that happens between the Application Gateway instances and the servers in the backend to use TLS.
215215

216-
If the backend servers do not have a TLS certificate issued for the CNAME www.contoso.com or *.contoso.com, the request will fail with **Server Error: 502 - Web server received an invalid response while acting as a gateway or proxy server** because the upstream SSL certificate (the certificate installed on the backend servers) will not match the hostname in the host header, and hence the TLS negotiation will fail.
216+
If the backend servers do not have a TLS certificate issued for the DNS NAME www.contoso.com or *.contoso.com, the request fails with **Server Error: 502 - Web server received an invalid response while acting as a gateway or proxy server** because the upstream SSL certificate (the certificate installed on the backend servers) doesn't match the hostname in the host header, and hence the TLS negotiation fails.
217217

218218

219219
www.contoso.com --> APP GW front end IP --> Listener with a rule that configures "Backend HTTP Settings" to use protocol HTTPS rather than HTTP --> Backend Pool --> Web server (needs to have a TLS certificate installed for www.contoso.com)
220220

221221
## Solution
222222

223-
it is required that the CNAME of the TLS certificate installed on the backend server, matches the host name configured in the HTTP backend settings, otherwise the second part of the End-to-end communication that happens between the instances of the Application Gateway and the backend, will fail with "Upstream SSL certificate does not match", and will throw back a **Server Error: 502 - Web server received an invalid response while acting as a gateway or proxy server**
223+
It's required that the DNS NAME of the TLS certificate installed on the backend server, matches the host name configured in the HTTP backend settings, otherwise the second part of the End-to-end communication that happens between the instances of the Application Gateway and the backend, fails with "Upstream SSL certificate doesn't match", and throws back a **Server Error: 502 - Web server received an invalid response while acting as a gateway or proxy server**
224224

225225

226226
## Next steps
149 KB
Loading
20.5 KB
Loading
202 KB
Loading
117 KB
Loading
137 KB
Loading
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
---
2+
title: How to use SignalR Service with Azure Front Door
3+
description: This article provides information about using Azure SignalR Service with Azure Front Door.
4+
author: kevinguo-ed
5+
ms.author: kevinguo
6+
ms.date: 04/10/2025
7+
ms.service: azure-signalr-service
8+
ms.topic: how-to
9+
---
10+
11+
# How to use Azure SignalR Service with Azure Front Door
12+
13+
Azure Front Door is a modern cloud-native application delivery network (ADN) that provides dynamic site acceleration, global load balancing, TLS termination, and application layer security. It operates at the HTTP/HTTPS layer (Layer 7) and acts as the entry point for web applications—routing and optimizing traffic based on attributes such as URL paths, latency, and health status of backends.
14+
15+
A key benefit of Azure Front Door is its native support for WebSocket and WebSocket Secure (WSS) connections. This support enables real-time, bi-directional communication between clients and backend services without requiring any special configuration.
16+
17+
In this guide, we demonstrate how to use Azure Front Door with Azure SignalR Service to front-end your real-time applications. By routing traffic through Front Door, you can:
18+
19+
- Apply WebSocket support with global reach and edge acceleration,
20+
- Apply centralized security policies, such as WAF rules and rate limiting,
21+
- Reduce public exposure of your backend services.
22+
23+
As shown in the diagram, you configure Azure Front Door to route WebSocket traffic to your SignalR-powered application backend. This setup ensures that your real-time functionality benefits from low-latency, scalable, and secure traffic handling through Azure’s global edge network.
24+
25+
## Set up and configure Azure Front Door
26+
27+
### Create an Azure SignalR Service resource
28+
29+
Follow [the article](./signalr-quickstart-azure-signalr-service-arm-template.md) and create a SignalR Service resource
30+
31+
### Create an Azure Front Door resource
32+
33+
On the [Azure portal](https://portal.azure.com/), search for **Front Door** and **Create**.
34+
35+
:::image type="content" source="./media/signalr-howto-work-with-azure-front-door/create-front-door.jpg" alt-text="Screenshot of creating an Azure Front Door resource.":::
36+
37+
38+
### Quick test
39+
Conduct quick tests to verify that SignalR endpoint is healthy and Azure Front Door resource is correctly configured.
40+
41+
Send a request to `<your-SignalR-resource-endpoint>/client` and it should return _400_ with error message _'hub' query parameter is required._ This message means that the request arrived at SignalR Service and the service performed validation as expected.
42+
```bash
43+
curl -v <your-SignalR-resource-endpoint>/client
44+
```
45+
Returns
46+
```
47+
< HTTP/1.1 400 Bad Request
48+
< ...
49+
<
50+
'hub' query parameter is required.
51+
```
52+
Send a request to the same health endpoint of Azure SignalR through Azure Front Door `http://<the-hostname-of-your-Azure-Front-Door-resource>/client`. Go to the Overview tab of the created Azure Front Door resource, and locate the endpoint hostname.
53+
54+
:::image type="content" source="./media/signalr-howto-work-with-azure-front-door/afd-hostname.jpg" alt-text="Screenshot of the the hostname of Azure Front Door resource":::
55+
56+
```bash
57+
curl -I http://<the-hostname-of-your-Azure-Front-Door-resource>/client
58+
```
59+
It should also return _400_ with error message _'hub' query parameter is required._ This message confirms that the request successfully went through Azure Front Door to SignalR Service.
60+
61+
```
62+
< HTTP/1.1 400 Bad Request
63+
< ...
64+
<
65+
'hub' query parameter is required.
66+
```
67+
68+
### Run a SignalR sample app through Azure Front Door
69+
70+
Now that we can verify that the traffic can reach SignalR Service through Azure Front Door. Next, we use a barebone sample app to demonstrate Azure Front Door's ability to route WebSocket traffic without configuration. We take a step-by-step approach so that you can follow along, if needed.
71+
72+
#### Create the project
73+
```bash
74+
mkdir afd-demo
75+
cd afd-demo
76+
77+
touch afd-demo.csproj
78+
```
79+
80+
Paste in the content to the `afd-demo.csproj` file. This project uses only the "Microsoft.Azure.SignalR" package.
81+
```json
82+
<Project Sdk="Microsoft.NET.Sdk.Web">
83+
<PropertyGroup>
84+
<TargetFramework>net7.0</TargetFramework>
85+
<Nullable>enable</Nullable>
86+
<ImplicitUsings>enable</ImplicitUsings>
87+
<RootNamespace>afd_demo</RootNamespace>
88+
</PropertyGroup>
89+
<ItemGroup>
90+
<PackageReference Include="Microsoft.Azure.SignalR" Version="1.30.2" />
91+
</ItemGroup>
92+
</Project>
93+
```
94+
95+
#### Configure app settings
96+
Create an `appsettings.json` file and paste in the content. The values will be referenced in the `Program.cs` file, which we create in the next step.
97+
```bash
98+
touch appsettings.json
99+
```
100+
101+
[!INCLUDE [Connection string security comment](includes/signalr-connection-string-security-comment.md)]
102+
103+
```json
104+
{
105+
"Azure": {
106+
"SignalR": {
107+
"ConnectionString": "<the-connection-string-of-your-Azure-SignalR-resource>"
108+
},
109+
"AFD": {
110+
"Endpoint": "<the-endpoint-of-your-Azure-Front-Door-resource>"
111+
}
112+
}
113+
}
114+
```
115+
116+
#### Create `Program.cs` file
117+
```bash
118+
touch Program.cs
119+
```
120+
121+
Paste in the code to the `Program.cs` file. The web app defines a SignalR hub and serves `index.html` at the web root.
122+
```csharp
123+
using Microsoft.Azure.SignalR;
124+
var builder = WebApplication.CreateBuilder(args);
125+
126+
// Reads in the configuration from `appsettings.json`
127+
var azureSignalRConnectionString = builder.Configuration["Azure:SignalR:ConnectionString"];
128+
var afdEndpoint = builder.Configuration["Azure:AFD:Endpoint"];
129+
130+
builder.Services.AddSignalR().AddAzureSignalR(o =>
131+
{
132+
o.Endpoints = new Microsoft.Azure.SignalR.ServiceEndpoint[1]
133+
{
134+
new Microsoft.Azure.SignalR.ServiceEndpoint(azureSignalRConnectionString)
135+
{
136+
// Instructs SignalR server to return a `ClientEndpoint` to SignalR clients, with which they establish a connection. In our case, it's the endpoint of the Azure Front Door resource you just created.
137+
ClientEndpoint = new Uri(afdEndpoint),
138+
}
139+
};
140+
});
141+
142+
var app = builder.Build();
143+
app.UseStaticFiles();
144+
145+
app.UseRouting();
146+
147+
app.MapHub<DemoHub>("/demohub");
148+
149+
app.MapGet("/", async context =>
150+
{
151+
var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "index.html");
152+
context.Response.ContentType = "text/html";
153+
await context.Response.SendFileAsync(path);
154+
});
155+
156+
app.Run();
157+
```
158+
159+
#### Define a SignalR hub
160+
```bash
161+
mkdir hubs && cd hubs
162+
touch demohubs.cs
163+
```
164+
165+
Paste in the code to the `demohubs.cs` file. For simplicity, the hub exposes only `BroadcastMessage` method to SignalR client, which broadcasts the received message to all connected SignalR clients.
166+
```csharp
167+
using Microsoft.AspNetCore.SignalR;
168+
169+
public class DemoHub : Hub
170+
{
171+
public Task BroadcastMessage(string message) =>
172+
Clients.All.SendAsync("broadcastMessage", message);
173+
}
174+
```
175+
176+
#### Define Web UI
177+
Make sure you're at the root of the project folder.
178+
```bash
179+
mkdir wwwroot && cd wwwroot
180+
touch index.html
181+
```
182+
183+
Paste in the code to `index.html`. The user interface consists of a `<textarea>` to receive text input from user and a `<button>` to send the user input through a SignalR connection. Since we defined the SignalR server's behavior to broadcast received messages, you see the same message logged to the browser console.
184+
```html
185+
<!DOCTYPE html>
186+
<html>
187+
188+
<head>
189+
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
190+
<meta name="viewport" content="width=device-width">
191+
<meta http-equiv="Pragma" content="no-cache" />
192+
<meta http-equiv="Expires" content="0" />
193+
<title>Azure SignalR with Azure Front Door as the reverse proxy</title>
194+
</head>
195+
196+
<body>
197+
<div>
198+
<textarea id="message" style="display: block; width: 100%; padding: 5px 10px; max-width: 400px; margin-bottom: 8px;"
199+
placeholder="Your message..."></textarea>
200+
<button id="btn-send" disabled>Send</button>
201+
</div>
202+
203+
<!--Reference the SignalR library. -->
204+
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>
205+
206+
<script type="module">
207+
document.addEventListener("DOMContentLoaded", async function () {
208+
const connection = new signalR.HubConnectionBuilder()
209+
.withUrl("/demohub")
210+
.build();
211+
212+
connection.on("broadcastMessage", (msg) => {
213+
console.log(msg)
214+
})
215+
await connection.start();
216+
document.getElementById("btn-send").removeAttribute("disabled")
217+
218+
document.getElementById("btn-send").addEventListener("click", () => {
219+
const message = document.getElementById("message").value
220+
if (message !== "") {
221+
connection.send("broadcastMessage", message)
222+
document.getElementById("message").value = ""
223+
} else {
224+
alert("Message body is empty. Please enter message.")
225+
}
226+
})
227+
})
228+
</script>
229+
</body>
230+
231+
</html>
232+
```
233+
234+
#### Run the app and verify the flow of message through Azure Front Door
235+
That is all the code to the sample. Let's run the app.
236+
237+
```bash
238+
dotnet restore
239+
dotnet run
240+
```
241+
242+
Open http://localhost:5129 from the browser and use `F12` keyboard shortcut to open developer tools. Head to the network panel, you can see that the WebSocket connection is indeed established with Azure Front Door.
243+
244+
:::image type="content" source="./media/signalr-howto-work-with-azure-front-door/network-panel-afd.jpg" alt-text="Screenshot of the running app establishing a WebSocket connection with Azure Front Door.":::
245+
246+
Try to type something in the text box and hit the send button. You see the message is logged to browser console as expected.
247+
248+
:::image type="content" source="./media/signalr-howto-work-with-azure-front-door/console-log.jpg" alt-text="Screenshot of the received message in browser's console log.":::
249+
250+
You can also inspect the flow of messages in the network panel.
251+
252+
:::image type="content" source="./media/signalr-howto-work-with-azure-front-door/network-panel-flow-of-messages.jpg" alt-text="Screenshot of flow of messages in the network panel.":::
253+
254+
255+

articles/container-apps/TOC.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,8 @@
498498
href: billing.md
499499
- name: Quotas
500500
href: quotas.md
501+
- name: Make quota requests
502+
href: quota-requests.md
501503
- name: Product updates
502504
items:
503505
- name: What's new
101 KB
Loading
7.39 KB
Loading

0 commit comments

Comments
 (0)