Skip to content

Commit bff2f8b

Browse files
Update docs to v2.4.5
1 parent 125bc91 commit bff2f8b

20 files changed

+1020
-83
lines changed

blacksheep/docs/application.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,156 @@ the environment variable `APP_SHOW_ERROR_DETAILS` to control whether the
4949
application displays detailed error information. Setting
5050
`APP_SHOW_ERROR_DETAILS=1` or `APP_SHOW_ERROR_DETAILS=True` enables this
5151
feature.
52+
5253
///
5354

5455
/// admonition | Settings strategy
5556

5657
BlackSheep project templates include a strategy to handle application
5758
settings and configuration roots. Refer to [_Getting started with the MVC project template_](./mvc-project-template.md)
5859
for more information.
60+
5961
///
6062

63+
## EnvironmentSettings
64+
65+
Starting from BlackSheep 2.4.4, the `Application` object includes an `env_settings`
66+
property that provides runtime access to environment-based configuration settings.
67+
The `Application` object automatically attaches an `EnvironmentSettings` instance that
68+
contains configuration values read from environment variables. This feature provides
69+
transparency and enables runtime inspection of the application's configuration, which
70+
is useful for debugging, testing, and administrative purposes.
71+
72+
### Accessing Environment Settings
73+
74+
You can access the environment settings through the `env_settings` property:
75+
76+
```python
77+
from blacksheep import Application
78+
79+
app = Application()
80+
81+
# Access environment settings at runtime
82+
print(f"Show error details: {app.env_settings.show_error_details}")
83+
print(f"Force HTTPS: {app.env_settings.force_https}")
84+
print(f"HTTP scheme: {app.env_settings.http_scheme}")
85+
```
86+
87+
### Available Environment Settings
88+
89+
The `EnvironmentSettings` object includes the following properties (all read-only):
90+
91+
| Property | Environment Variable | Type | Default | Description |
92+
| -------------------- | ------------------------ | ------------ | ------- | --------------------------------------------- |
93+
| `env` | `APP_ENV` | `str` | `"production"` | Application environment (e.g., "local", "dev", "production") |
94+
| `show_error_details` | `APP_SHOW_ERROR_DETAILS` | `bool` | `False` | Whether to display detailed error information |
95+
| `mount_auto_events` | `APP_MOUNT_AUTO_EVENTS` | `bool` | `True` | Whether to automatically mount application events |
96+
| `use_default_router` | `APP_DEFAULT_ROUTER` | `bool` | `True` | Whether to use the default router |
97+
| `add_signal_handler` | `APP_SIGNAL_HANDLER` | `bool` | `False` | Whether to add signal handlers for graceful shutdown |
98+
| `http_scheme` | `APP_HTTP_SCHEME` | `str | None` | `None` | Explicitly set request scheme (`http` or `https`) |
99+
| `force_https` | `APP_FORCE_HTTPS` | `bool` | `False` | Whether to force HTTPS scheme and enable HSTS |
100+
101+
Refer to [_Settings_](./settings.md) for more information.
102+
103+
### Practical Use Cases
104+
105+
#### Testing and Assertions
106+
107+
Environment settings are particularly useful for testing configuration:
108+
109+
```python
110+
import os
111+
from blacksheep import Application
112+
113+
# Set environment variable
114+
os.environ["APP_FORCE_HTTPS"] = "true"
115+
116+
app = Application()
117+
118+
# Assert configuration in tests
119+
assert app.env_settings.force_https is True
120+
assert app.env_settings.http_scheme is None # Not set
121+
122+
# Clean up
123+
del os.environ["APP_FORCE_HTTPS"]
124+
```
125+
126+
#### Health Check Endpoints
127+
128+
Create health check endpoints that expose configuration information:
129+
130+
```python
131+
from blacksheep import Application, get
132+
133+
app = Application()
134+
135+
@get("/health")
136+
async def health_check():
137+
return {
138+
"status": "healthy",
139+
"config": {
140+
"force_https": app.env_settings.force_https,
141+
"http_scheme": app.env_settings.http_scheme,
142+
"show_error_details": app.env_settings.show_error_details
143+
}
144+
}
145+
```
146+
147+
#### Admin Tools and Configuration Inspection
148+
149+
Build administrative interfaces that display current configuration:
150+
151+
```python
152+
from blacksheep import Application, get
153+
from blacksheep.server.authorization import auth
154+
155+
app = Application()
156+
157+
@auth(roles=["admin"])
158+
@get("/admin/config")
159+
async def admin_config():
160+
"""Administrative endpoint to inspect application configuration"""
161+
return {
162+
"environment_settings": {
163+
"show_error_details": app.env_settings.show_error_details,
164+
"force_https": app.env_settings.force_https,
165+
"http_scheme": app.env_settings.http_scheme,
166+
},
167+
"runtime_info": {
168+
"debug_mode": app.debug,
169+
"middleware_count": len(app.middlewares),
170+
}
171+
}
172+
```
173+
174+
#### Debugging and Development
175+
176+
Use environment settings for conditional debugging logic:
177+
178+
```python
179+
from blacksheep import Application
180+
181+
app = Application()
182+
183+
@app.on_start
184+
async def configure_logging():
185+
if app.env_settings.show_error_details:
186+
# Enable verbose logging in development
187+
import logging
188+
logging.getLogger().setLevel(logging.DEBUG)
189+
print("Debug logging enabled due to APP_SHOW_ERROR_DETAILS=true")
190+
```
191+
192+
### Benefits of Runtime Configuration Access
193+
194+
1. **Transparency**: Easy inspection of how the application is configured
195+
2. **Testing**: Reliable assertions about configuration state in tests
196+
3. **Debugging**: Quick access to configuration values during development
197+
4. **Monitoring**: Health checks and admin endpoints can expose configuration
198+
5. **Conditional Logic**: Runtime decisions based on configuration values
199+
200+
The `EnvironmentSettings` object is read-only, ensuring that configuration remains stable throughout the application lifecycle while still providing full visibility into the current settings.
201+
61202
### Configuring exceptions handlers
62203

63204
The BlackSheep `Application` object has an `exceptions_handlers` dictionary

blacksheep/docs/authentication.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ app.use_authentication().add(
767767
valid_audiences=["my-service"],
768768
valid_issuers=["my-issuer"],
769769
algorithms=["HS256"], # ⟵ symmetric algorithms: HS256, HS384, HS512
770-
auth_mode="JWT Symmetric"
770+
scheme="JWT Symmetric"
771771
)
772772
)
773773

@@ -840,7 +840,7 @@ app.use_authentication().add(
840840
valid_audiences=["internal-api"],
841841
valid_issuers=["internal-issuer"],
842842
algorithms=["HS256"],
843-
auth_mode="JWT Internal"
843+
scheme="JWT Internal"
844844
)
845845
)
846846

@@ -851,7 +851,7 @@ app.use_authentication().add(
851851
valid_audiences=["external-client-id"],
852852
valid_issuers=["https://login.microsoftonline.com/tenant-id/v2.0"],
853853
algorithms=["RS256"],
854-
auth_mode="JWT External"
854+
scheme="JWT External"
855855
)
856856
)
857857
```

blacksheep/docs/authorization.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class ExampleAuthHandler(AuthenticationHandler):
4242
def __init__(self):
4343
pass
4444

45-
async def authenticate(self, context: Request) -> Optional[Identity]:
45+
async def authenticate(self, context: Request) -> Identity | None:
4646
header_value = context.get_first_header(b"Authorization")
4747
if header_value:
4848
# TODO: parse and validate the value of the authorization
@@ -62,7 +62,7 @@ app.use_authorization().add(Policy(Authenticated, AuthenticatedRequirement()))
6262

6363

6464
@get("/")
65-
async def for_anybody(user: Optional[User]):
65+
async def for_anybody(user: User | None):
6666
if user is None:
6767
return json({"anonymous": True})
6868

@@ -138,7 +138,7 @@ class ExampleAuthHandler(AuthenticationHandler):
138138
def __init__(self):
139139
pass
140140

141-
async def authenticate(self, context: Request) -> Optional[Identity]:
141+
async def authenticate(self, context: Request) -> Identity | None:
142142
header_value = context.get_first_header(b"Authorization")
143143
if header_value:
144144
# TODO: parse and validate the value of the authorization
@@ -173,7 +173,7 @@ app.use_authorization().add(Policy(Authenticated, AuthenticatedRequirement())).a
173173

174174

175175
@get("/")
176-
async def for_anybody(user: Optional[User]):
176+
async def for_anybody(user: User | None):
177177
# This method can be used by anybody
178178
if user is None:
179179
return json({"anonymous": True})
@@ -220,7 +220,7 @@ from blacksheep.server.authorization import allow_anonymous
220220

221221
@allow_anonymous()
222222
@get("/")
223-
async def for_anybody(user: Optional[User]):
223+
async def for_anybody(user: User | None):
224224
if user is None:
225225
return json({"anonymous": True})
226226

@@ -248,7 +248,7 @@ class GitHubAuthHandler(AuthenticationHandler):
248248
def scheme(self) -> str:
249249
return "github"
250250

251-
async def authenticate(self, context: Request) -> Optional[Identity]:
251+
async def authenticate(self, context: Request) -> Identity | None:
252252
...
253253

254254

0 commit comments

Comments
 (0)