---
title: Enforce HTTPS on an action
summary: Redirect non-HTTPS requests to HTTPS, with an app-setting-controlled exemption for local requests.
status: draft
owner: andmil
last_reviewed: 2026-09-15
library: SAIF.Web.API
reference_type: package
operation_id: OP-07
trigger: Web API action-filter pipeline, before action execution, on any decorated controller/action.
---

# Enforce HTTPS on an action

`RequireSSLAttribute.OnActionExecuting(HttpActionContext)` redirects a non-HTTPS request to HTTPS unless a local-request exemption applies.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-07 |
| **Trigger** | Web API action-filter pipeline, before action execution, on any decorated controller/action. |
| **Inputs** | `HttpActionContext`, `appSettings["RequireSSLForLocal"]` |
| **Outputs** | none (side effect: HTTP redirect) |
| **Primary components** | `RequireSSLAttribute.OnActionExecuting`, `RequireSSLAttribute.RequiresSSL` |
| **Entry point** | `src/SAIF.Web.API/RequireSSLAttribute.cs` |

## Steps

1. Evaluate `actionContext.Request.RequestUri.Scheme.ToLower() != Uri.UriSchemeHttps`.
   - If already HTTPS, skip to step 6.
2. Call `RequiresSSL`: initialize `requireSSL = true` ([BR-WEBAPI-012](../business-rules.md#br-webapi-012-https-required-unless-local-exemption-applies)).
   - Secure-by-default.
3. If `actionContext.Request.IsLocal()`, look for an app-setting key literally equal to `"RequireSSLForLocal"` in `ConfigurationManager.AppSettings.AllKeys` ([BR-WEBAPI-012](../business-rules.md#br-webapi-012-https-required-unless-local-exemption-applies)).
   - Non-local requests always require SSL.
   - `SAIF.Common.Extensions.IsLocal()` is implemented in `SAIF.Framework.Core`; its internal steps could not be embedded — the package is not indexed for this run.**
4. If the key exists, `bool.TryParse` its value into `requireSSL`; if the key is absent, set `requireSSL = false` ([BR-WEBAPI-012](../business-rules.md#br-webapi-012-https-required-unless-local-exemption-applies)).
   - An unparseable value leaves `requireSSL = false` (a failed `TryParse` sets the `out` parameter to `false`).
5. If the scheme is not HTTPS **and** `RequiresSSL` returned true, build `new UriBuilder(requestUri) { Scheme = Uri.UriSchemeHttps, Port = 443 }` and call `HttpContext.Current.Response.Redirect` ([BR-WEBAPI-013](../business-rules.md#br-webapi-013-redirect-non-https-requests-to-https)).
   - Uses `HttpContext.Current` (web-host only); `Response.Redirect` without `endResponse:false` raises `ThreadAbortException` by design.*
6. Call `base.OnActionExecuting(actionContext)`.

## Process flow

```mermaid
flowchart TD
	Start([Action filter pipeline]) --> Scheme{Scheme is HTTPS?}
	Scheme -->|Yes| Base[base.OnActionExecuting]
	Scheme -->|No| Init["requireSSL = true<br>(default)"]
	Init --> Local{IsLocal request?}
	Local -->|No| Redirect
	Local -->|Yes| KeyCheck{"RequireSSLForLocal key<br>present?"}
	KeyCheck -->|No| NotRequired["requireSSL = false"]
	KeyCheck -->|Yes| Parse["bool.TryParse value into<br>requireSSL"]
	NotRequired --> Decide{requireSSL?}
	Parse --> Decide
	Decide -->|Yes| Redirect["Redirect to HTTPS on<br>port 443"]
	Decide -->|No| Base
	Redirect --> Base
```

## Failure and edge-case behavior
- `HttpContext.Current` is web-host only; a self-hosted scenario would see `null` at redirect time.*
- The redirect raises `ThreadAbortException` by design (no `endResponse:false` argument supplied).*

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- `src/SAIF.Web.API/RequireSSLAttribute.cs`
