Skip to content

Commit 295a604

Browse files
DockFlare v3.0.5: A Tale of Two Toggles
## [v3.0.5] - 2025-10-14 ### Added - **HTTP/2 Origin Support:** Added support for enabling HTTP/2 protocol between `cloudflared` and origin services via the new `dockflare.http2_origin` label and UI controls. Required for gRPC services. Only applies to HTTP/HTTPS services. - **Disable Chunked Encoding Support:** Added support for disabling chunked transfer encoding over HTTP/1.1 via the new `dockflare.disable_chunked_encoding` label and UI controls. Useful for WSGI servers (Flask, Django, FastAPI) and other origins that don't properly support chunked requests. Only applies to HTTP/HTTPS services.
2 parents 9181304 + 4afac29 commit 295a604

File tree

11 files changed

+116
-5
lines changed

11 files changed

+116
-5
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
---
99

10+
## [v3.0.5] - 2025-10-14
11+
12+
### Added
13+
- **HTTP/2 Origin Support:** Added support for enabling HTTP/2 protocol between `cloudflared` and origin services via the new `dockflare.http2_origin` label and UI controls. Required for gRPC services. Only applies to HTTP/HTTPS services.
14+
- **Disable Chunked Encoding Support:** Added support for disabling chunked transfer encoding over HTTP/1.1 via the new `dockflare.disable_chunked_encoding` label and UI controls. Useful for WSGI servers (Flask, Django, FastAPI) and other origins that don't properly support chunked requests. Only applies to HTTP/HTTPS services.
15+
16+
---
17+
1018
## [v3.0.4] - 2025-10-11
1119

1220
### Added

README.MD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
</p>
1212

1313
<p align="center">
14-
<a href="https://github.com/ChrispyBacon-dev/DockFlare/releases"><img src="https://img.shields.io/badge/Release-v3.0.4-blue.svg?style=for-the-badge" alt="Release"></a>
14+
<a href="https://github.com/ChrispyBacon-dev/DockFlare/releases"><img src="https://img.shields.io/badge/Release-v3.0.5-blue.svg?style=for-the-badge" alt="Release"></a>
1515
<a href="https://hub.docker.com/r/alplat/dockflare"><img src="https://img.shields.io/docker/pulls/alplat/dockflare?style=for-the-badge" alt="Docker Pulls"></a>
1616
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/Made%20with-Python-1f425f.svg?style=for-the-badge" alt="Python"></a>
1717
<a href="https://github.com/ChrispyBacon-dev/DockFlare/blob/main/LICENSE.MD"><img src="https://img.shields.io/badge/License-GPL--3.0-blue.svg?style=for-the-badge" alt="License"></a>

dockflare/app/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def _get_int_env(name, default, minimum=None):
3434
return default
3535

3636
# --- DockFlare Version ---
37-
APP_VERSION = "v3.0.4"
37+
APP_VERSION = "v3.0.5"
3838
# --- web: https://dockflare.app ---
3939
# --- github: https://github.com/ChrispyBacon-dev/DockFlare ---
4040

dockflare/app/core/docker_handler.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ def process_container_start(container_obj):
157157
service_label = get_label(labels, "service")
158158
zone_name_label = get_label(labels, "zonename")
159159
no_tls_verify_label = get_label(labels, "no_tls_verify", "false").lower() in ["true", "1", "t", "yes"]
160+
http2_origin_label = get_label(labels, "http2_origin", "false").lower() in ["true", "1", "t", "yes"]
161+
disable_chunked_encoding_label = get_label(labels, "disable_chunked_encoding", "false").lower() in ["true", "1", "t", "yes"]
160162

161163
if hostname_label and service_label:
162164
if is_valid_hostname(hostname_label) and is_valid_service(service_label):
@@ -166,6 +168,8 @@ def process_container_start(container_obj):
166168
"no_tls_verify": no_tls_verify_label,
167169
"origin_server_name": default_originsrvname_label.strip() if default_originsrvname_label else None,
168170
"http_host_header": default_http_host_header_label.strip() if default_http_host_header_label else None,
171+
"http2_origin": http2_origin_label,
172+
"disable_chunked_encoding": disable_chunked_encoding_label,
169173
"access_group": default_access_group,
170174
"access_policy_type": default_access_policy_type_label,
171175
"access_app_name": default_access_app_name_label,
@@ -194,6 +198,10 @@ def process_container_start(container_obj):
194198
no_tls_verify_indexed = no_tls_verify_indexed_val.lower() in ["true", "1", "t", "yes"]
195199
originsrvname_indexed_val = get_label(labels, f"{index}.originsrvname", default_originsrvname_label)
196200
http_host_header_indexed_val = get_label(labels, f"{index}.httpHostHeader", default_http_host_header_label)
201+
http2_origin_indexed_val = get_label(labels, f"{index}.http2_origin", str(http2_origin_label).lower())
202+
http2_origin_indexed = http2_origin_indexed_val.lower() in ["true", "1", "t", "yes"]
203+
disable_chunked_encoding_indexed_val = get_label(labels, f"{index}.disable_chunked_encoding", str(disable_chunked_encoding_label).lower())
204+
disable_chunked_encoding_indexed = disable_chunked_encoding_indexed_val.lower() in ["true", "1", "t", "yes"]
197205

198206
access_groups_indexed = get_label(labels, f"{index}.access.groups")
199207
raw_access_group_indexed = get_label(labels, f"{index}.access.group") if not access_groups_indexed else None
@@ -244,6 +252,8 @@ def process_container_start(container_obj):
244252
"no_tls_verify": no_tls_verify_indexed,
245253
"origin_server_name": originsrvname_indexed_val.strip() if originsrvname_indexed_val else None,
246254
"http_host_header": http_host_header_indexed_val.strip() if http_host_header_indexed_val else None,
255+
"http2_origin": http2_origin_indexed,
256+
"disable_chunked_encoding": disable_chunked_encoding_indexed,
247257
"access_group": access_group_indexed,
248258
"access_policy_type": access_policy_type_indexed,
249259
"access_app_name": access_app_name_indexed,
@@ -285,6 +295,8 @@ def process_container_start(container_obj):
285295
no_tls_verify_from_item = config_item["no_tls_verify"]
286296
origin_server_name_from_item = config_item.get("origin_server_name")
287297
http_host_header_from_item = config_item.get("http_host_header")
298+
http2_origin_from_item = config_item.get("http2_origin", False)
299+
disable_chunked_encoding_from_item = config_item.get("disable_chunked_encoding", False)
288300

289301
target_zone_id = None
290302
detected_zone_name = zone_name_from_item
@@ -349,6 +361,12 @@ def process_container_start(container_obj):
349361
if existing_rule.get("http_host_header") != http_host_header_from_item:
350362
existing_rule["http_host_header"] = http_host_header_from_item
351363
rule_data_changed = True
364+
if existing_rule.get("http2_origin") != http2_origin_from_item:
365+
existing_rule["http2_origin"] = http2_origin_from_item
366+
rule_data_changed = True
367+
if existing_rule.get("disable_chunked_encoding") != disable_chunked_encoding_from_item:
368+
existing_rule["disable_chunked_encoding"] = disable_chunked_encoding_from_item
369+
rule_data_changed = True
352370

353371
existing_rule["source"] = "docker"
354372
if master_tunnel_id and existing_rule.get("tunnel_id") != master_tunnel_id:
@@ -384,6 +402,8 @@ def process_container_start(container_obj):
384402
"no_tls_verify": no_tls_verify_from_item,
385403
"origin_server_name": origin_server_name_from_item,
386404
"http_host_header": http_host_header_from_item,
405+
"http2_origin": http2_origin_from_item,
406+
"disable_chunked_encoding": disable_chunked_encoding_from_item,
387407
"access_app_id": None,
388408
"access_policy_type": None,
389409
"access_app_config_hash": None,

dockflare/app/core/state_manager.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ def load_state():
143143
rule_copy.setdefault("zone_name", None)
144144
rule_copy.setdefault("no_tls_verify", False)
145145
rule_copy.setdefault("origin_server_name", None)
146+
rule_copy.setdefault("http2_origin", False)
147+
rule_copy.setdefault("disable_chunked_encoding", False)
146148

147149
tunnel_name = rule_copy.get("tunnel_name")
148150
if not tunnel_name or tunnel_name == "dockflare-tunnel":
@@ -500,6 +502,8 @@ def save_state():
500502
"no_tls_verify": rule.get("no_tls_verify", False),
501503
"origin_server_name": rule.get("origin_server_name"),
502504
"http_host_header": rule.get("http_host_header"),
505+
"http2_origin": rule.get("http2_origin", False),
506+
"disable_chunked_encoding": rule.get("disable_chunked_encoding", False),
503507
"access_app_id": rule.get("access_app_id"),
504508
"access_policy_type": rule.get("access_policy_type"),
505509
"access_app_config_hash": rule.get("access_app_config_hash"),

dockflare/app/core/tunnel_manager.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ def _build_ingress_entry_from_rule(rule_details):
261261
http_host_header = rule_details.get("http_host_header") or rule_details.get("httpHostHeader")
262262
if http_host_header:
263263
origin_request["httpHostHeader"] = http_host_header
264+
if rule_details.get("http2_origin"):
265+
origin_request["http2Origin"] = True
266+
if rule_details.get("disable_chunked_encoding"):
267+
origin_request["disableChunkedEncoding"] = True
264268
if origin_request:
265269
entry["originRequest"] = origin_request
266270
return entry
@@ -299,7 +303,9 @@ def _ingress_to_comparable(rule):
299303
no_tls = bool(origin.get("noTLSVerify"))
300304
origin_name = origin.get("originServerName") or ""
301305
http_host = origin.get("httpHostHeader") or ""
302-
return (hostname, service, path, no_tls, origin_name, http_host)
306+
http2_origin = bool(origin.get("http2Origin"))
307+
disable_chunked = bool(origin.get("disableChunkedEncoding"))
308+
return (hostname, service, path, no_tls, origin_name, http_host, http2_origin, disable_chunked)
303309

304310

305311
def _is_catch_all_rule(rule):

dockflare/app/static/js/main.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,12 @@ function initializeEditRuleModal() {
229229
const httpHostHeaderField = modal.querySelector('#edit_manual_http_host_header');
230230
if (httpHostHeaderField) httpHostHeaderField.value = details.http_host_header || '';
231231

232+
const http2OriginField = modal.querySelector('#edit_http2_origin');
233+
if (http2OriginField) http2OriginField.checked = details.http2_origin || false;
234+
235+
const disableChunkedEncodingField = modal.querySelector('#edit_disable_chunked_encoding');
236+
if (disableChunkedEncodingField) disableChunkedEncodingField.checked = details.disable_chunked_encoding || false;
237+
232238
const tunnelDisplay = modal.querySelector('#edit_rule_tunnel_value');
233239
const zoneDisplay = modal.querySelector('#edit_rule_zone_value');
234240
const agentHint = modal.querySelector('#edit_rule_agent_hint');

dockflare/app/templates/docs/Container-Labels.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ These labels control the fundamental routing and service definition for a contai
1616
| `dockflare.no_tls_verify` | If set to `true`, disables TLS certificate verification for the connection between `cloudflared` and your origin service. Useful for origins with self-signed certificates. | `dockflare.no_tls_verify=true` |
1717
| `dockflare.originsrvname` | Sets a specific Server Name Indication (SNI) hostname for the TLS connection to the origin. This is also known as "Origin Server Name" in the Cloudflare dashboard. | `dockflare.originsrvname=internal.service.local` |
1818
| `dockflare.httpHostHeader` | Overrides the `Host` header sent from `cloudflared` to your origin service. | `dockflare.httpHostHeader=custom-host.internal` |
19+
| `dockflare.http2_origin` | If set to `true`, enables HTTP/2 protocol for the connection between `cloudflared` and your origin service. Required for gRPC services. Only applies to HTTP/HTTPS services. | `dockflare.http2_origin=true` |
20+
| `dockflare.disable_chunked_encoding` | If set to `true`, disables chunked transfer encoding over HTTP/1.1. Useful for WSGI servers (Flask, Django, FastAPI) and other origins that don't properly support chunked requests. Only applies to HTTP/HTTPS services. | `dockflare.disable_chunked_encoding=true` |
1921

2022
> **Tip:** Starting with DockFlare v3.0, you can skip `dockflare.zonename` for most workloads. The master detects the correct Cloudflare zone by matching the hostname suffix and only falls back to the configured default zone when it cannot find a match. Provide the label when you intentionally want to place a record in a different zone.
2123

dockflare/app/templates/status_page.html

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,13 @@ <h3 class="font-bold text-xs uppercase opacity-80">Last Action</h3>
196196
{% endif %}
197197
{% if details.http_host_header %}
198198
<span class="badge badge-info badge-xs ml-1" title="HTTP Host Header: {{ details.http_host_header }}">Host: {{ details.http_host_header | truncate(20, True) }}</span>
199-
{% endif %}
199+
{% endif %}
200+
{% if details.http2_origin %}
201+
<span class="badge badge-success badge-xs ml-1" title="HTTP/2 protocol enabled for origin connection">HTTP/2 Origin</span>
202+
{% endif %}
203+
{% if details.disable_chunked_encoding %}
204+
<span class="badge badge-info badge-xs ml-1" title="Chunked transfer encoding disabled for HTTP/1.1">No Chunked Encoding</span>
205+
{% endif %}
200206
</div>
201207
</td>
202208
<td class="p-3 whitespace-nowrap">
@@ -503,6 +509,20 @@ <h4 class="text-md font-semibold mb-2">Access Policy (Optional)</h4>
503509
<span class="label-text-alt">Overrides the <code>Host</code> header sent to your origin server. Useful for origins expecting a different hostname than the public one. (Only applies to HTTP/HTTPS services).</span>
504510
</label>
505511
</div>
512+
<div id="manual_http2_origin_div" class="form-control">
513+
<label class="label cursor-pointer justify-start gap-2">
514+
<input type="checkbox" name="manual_http2_origin" id="manual_http2_origin" class="checkbox checkbox-sm" />
515+
<span class="label-text">Enable HTTP/2 Origin</span>
516+
</label>
517+
<div class="text-xs opacity-60 ml-8">Enable HTTP/2 protocol between Cloudflare and your origin server. Required for gRPC services. (Only applies to HTTP/HTTPS services).</div>
518+
</div>
519+
<div id="manual_disable_chunked_encoding_div" class="form-control">
520+
<label class="label cursor-pointer justify-start gap-2">
521+
<input type="checkbox" name="manual_disable_chunked_encoding" id="manual_disable_chunked_encoding" class="checkbox checkbox-sm" />
522+
<span class="label-text">Disable Chunked Encoding</span>
523+
</label>
524+
<div class="text-xs opacity-60 ml-8">Disables chunked transfer encoding over HTTP/1.1. Useful for WSGI servers (Flask, Django) and other origins that don't support chunked requests. (Only applies to HTTP/HTTPS services).</div>
525+
</div>
506526
</div>
507527
</div>
508528
<div id="manual_rule_feedback" class="hidden alert mt-4"></div>
@@ -640,6 +660,20 @@ <h4 class="text-md font-semibold mb-2">Access Policy (Optional)</h4>
640660
<span class="label-text-alt">Overrides the <code>Host</code> header sent to your origin server. Useful for origins expecting a different hostname than the public one. (Only applies to HTTP/HTTPS services).</span>
641661
</label>
642662
</div>
663+
<div id="edit_http2_origin_div" class="form-control">
664+
<label class="label cursor-pointer justify-start gap-2">
665+
<input type="checkbox" name="edit_http2_origin" id="edit_http2_origin" class="checkbox checkbox-sm" />
666+
<span class="label-text">Enable HTTP/2 Origin</span>
667+
</label>
668+
<div class="text-xs opacity-60 ml-8">Enable HTTP/2 protocol between Cloudflare and your origin server. Required for gRPC services. (Only applies to HTTP/HTTPS services).</div>
669+
</div>
670+
<div id="edit_disable_chunked_encoding_div" class="form-control">
671+
<label class="label cursor-pointer justify-start gap-2">
672+
<input type="checkbox" name="edit_disable_chunked_encoding" id="edit_disable_chunked_encoding" class="checkbox checkbox-sm" />
673+
<span class="label-text">Disable Chunked Encoding</span>
674+
</label>
675+
<div class="text-xs opacity-60 ml-8">Disables chunked transfer encoding over HTTP/1.1. Useful for WSGI servers (Flask, Django) and other origins that don't support chunked requests. (Only applies to HTTP/HTTPS services).</div>
676+
</div>
643677
</div>
644678
</div>
645679
<div class="modal-action mt-8 pt-4 border-t border-base-300">

0 commit comments

Comments
 (0)