Commit c62092e
Add HTTP Response Compression Support (#3003)
## Why make this change?
Closes #2711
DAB does not currently support response compression (gzip/brotli), which
can reduce payload sizes by ~79% for large JSON responses. This is
especially beneficial for REST and GraphQL endpoints over slow or
high-latency networks.
## What is this change?
Adds response compression middleware with configurable compression
levels.
**Configuration Model:**
- `CompressionLevel` enum: `optimal`, `fastest`, `none`
- `CompressionOptions` record with JSON converter and validation
- Default: `optimal`
**Runtime Behavior:**
- Gzip and Brotli providers enabled for HTTPS
- Applies to REST, GraphQL, and MCP endpoints
- Logs compression level on startup (silent when `none`)
**Schema & CLI:**
```json
{
"runtime": {
"compression": {
"level": "optimal"
}
}
}
```
## How was this tested?
- [ ] Integration Tests
- [x] Unit Tests
Added 3 tests in `ConfigureOptionsTests.cs` covering all compression
levels.
## Sample Request(s)
**CLI Configuration:**
```bash
dab configure --runtime.compression.level fastest
```
**Sample Request/Response:**
```
GET /api/employees HTTP/1.1
Accept-Encoding: gzip, br
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Type: application/json
```
**Startup Output (when enabled):**
```
Response compression enabled with level 'Optimal' for REST, GraphQL, and MCP endpoints.
```
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>⭐ [Enhancement]: Add Compression</issue_title>
> <issue_description>Data API builder does not currently support
response compression (e.g., gzip or brotli), which can significantly
reduce payload size and improve performance over slow or high-latency
networks. Compression is especially beneficial for large JSON responses,
common in REST and GraphQL endpoints. Adding support at the server
level—either via built-in middleware or integration guidance—would help
DAB serve clients more efficiently. This is a common feature in modern
web APIs and would be a strong addition to the roadmap.
>
> **Sample request**
>
> ``` text
> GET /api/employees HTTP/1.1
> Host: api.example.com
> Accept-Encoding: gzip, deflate, br
> ```
>
> **Sample response**
>
> ```text
> HTTP/1.1 200 OK
> Content-Encoding: gzip
> Content-Type: application/json
> Content-Length: 920
> ```
>
> **Payload impact**
>
> | Payload Type | Uncompressed (bytes) | Gzipped (bytes) | Compression
Savings |
> |-|-|-|-|
> | Large JSON array | 4,356 | 920 | ~79% |
>
> ## Configuration Update
>
> ```json
> {
> "runtime": {
> "compression": {
> "level": "fastest" | "optimal" | "none" <default: optimal>
> }
> }
> }
> ```
>
> ## CLI update
>
> ```text
> dab configure --runtime.compression.level fastest
> ```
>
> ## Starter JSON Schema section
>
> ```json
> {
> "runtime": {
> "type": "object",
> "properties": {
> "compression": {
> "type": "object",
> "description": "Configures HTTP response compression settings.",
> "properties": {
> "level": {
> "type": "string",
> "enum": ["fastest", "optimal", "none"],
> "default": "optimal",
> "description": "Specifies the response compression level."
> }
> },
> "additionalProperties": false
> }
> }
> }
> }
> ```
>
> ## Basic ASPNET implementation
>
> ```csharp
> var builder = WebApplication.CreateBuilder(args);
>
> builder.Services.AddResponseCompression(options =>
> {
> options.EnableForHttps = true;
> options.Providers.Add<GzipCompressionProvider>();
> });
> builder.Services.Configure<GzipCompressionProviderOptions>(options =>
> {
> options.Level = CompressionLevel.Fastest;
> });
>
> var app = builder.Build();
>
> app.UseResponseCompression();
>
> // map endpoints and controllers
>
> app.Run();
> ```
>
> ## FAQ
>
> 1. **Is this backwards compatible?**
> Yes. Clients that don’t request compression (via `Accept-Encoding`)
receive uncompressed responses exactly as before.
>
> 2. **Does this require a special client?**
> No. Most modern browsers and HTTP clients (like curl, Postman, fetch,
axios) already support compressed responses out-of-the-box.
>
> 3. **Does this impact controller logic?**
> No. Compression is handled at the middleware level, completely
separate from your controller logic or data access code.
>
> 4. **What is the compute cost compared to bandwidth savings?**
> Compression uses CPU but reduces payload size dramatically. In most
APIs, the tradeoff favors compression—especially for large or repetitive
JSON responses. The `CompressionLevel.Fastest` option balances speed and
size.
>
> 5. **Does this work over HTTPS?**
> Yes. Response compression is fully supported over HTTPS and can be
explicitly enabled with `EnableForHttps = true`.
>
> 6. **Can it be customized for specific MIME types?**
> Yes. You can add custom MIME types (e.g., `application/graphql+json`)
if needed.
>
> 7. **What compression formats are supported?**
> Gzip is most common, but Brotli and Deflate are also supported in
ASP.NET Core with the appropriate providers.
>
> 8. **Does it work with REST and GraphQL?**
> Yes. Compression applies to all HTTP responses regardless of the
endpoint type, including both REST and GraphQL APIs.
>
> 9. **Does Hot Chocolate support it?**
> Hot Chocolate runs on ASP.NET Core and inherits its middleware
pipeline, so response compression works with it automatically—no special
configuration needed in Hot Chocolate itself.</issue_description>
>
> <agent_instructions>You are a senior microsoft engineer dedicated to
terse code and changing as little code as possible in order to complete
the task.</agent_instructions>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> </comments>
>
</details>
- Fixes #2636
<!-- START COPILOT CODING AGENT TIPS -->
---
✨ Let Copilot coding agent [set things up for
you](https://github.com/Azure/data-api-builder/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.
---------
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: JerryNixon <[email protected]>1 parent 6f62845 commit c62092e
11 files changed
Lines changed: 628 additions & 1 deletion
File tree
- schemas
- src
- Cli.Tests
- Cli
- Commands
- Config
- Converters
- ObjectModel
- Service.Tests/Configuration
- Service
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
424 | 424 | | |
425 | 425 | | |
426 | 426 | | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
427 | 440 | | |
428 | 441 | | |
429 | 442 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
540 | 540 | | |
541 | 541 | | |
542 | 542 | | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
543 | 571 | | |
544 | 572 | | |
545 | 573 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
| 51 | + | |
51 | 52 | | |
52 | 53 | | |
53 | 54 | | |
| |||
105 | 106 | | |
106 | 107 | | |
107 | 108 | | |
| 109 | + | |
| 110 | + | |
108 | 111 | | |
109 | 112 | | |
110 | 113 | | |
| |||
212 | 215 | | |
213 | 216 | | |
214 | 217 | | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
215 | 221 | | |
216 | 222 | | |
217 | 223 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
849 | 849 | | |
850 | 850 | | |
851 | 851 | | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
852 | 867 | | |
853 | 868 | | |
854 | 869 | | |
| |||
1226 | 1241 | | |
1227 | 1242 | | |
1228 | 1243 | | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
| 1250 | + | |
| 1251 | + | |
| 1252 | + | |
| 1253 | + | |
| 1254 | + | |
| 1255 | + | |
| 1256 | + | |
| 1257 | + | |
| 1258 | + | |
| 1259 | + | |
| 1260 | + | |
| 1261 | + | |
| 1262 | + | |
| 1263 | + | |
| 1264 | + | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| 1274 | + | |
1229 | 1275 | | |
1230 | 1276 | | |
1231 | 1277 | | |
| |||
Lines changed: 104 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| |||
28 | 29 | | |
29 | 30 | | |
30 | 31 | | |
31 | | - | |
| 32 | + | |
| 33 | + | |
32 | 34 | | |
33 | 35 | | |
34 | 36 | | |
| |||
39 | 41 | | |
40 | 42 | | |
41 | 43 | | |
| 44 | + | |
42 | 45 | | |
43 | 46 | | |
44 | 47 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
320 | 320 | | |
321 | 321 | | |
322 | 322 | | |
| 323 | + | |
323 | 324 | | |
324 | 325 | | |
325 | 326 | | |
| |||
0 commit comments