Releases: Neoteroi/BlackSheep
Releases · Neoteroi/BlackSheep
v2.5.1
v2.5.0
- Add native HTTP/2 support to the HTTP client with automatic protocol detection via ALPN (Application-Layer Protocol Negotiation). The client now automatically uses HTTP/2 when the server supports it, with seamless fallback to HTTP/1.1.
- Add new
HTTP2Connectionclass using theh2library for HTTP/2 protocol handling. - Add new
HTTP11Connectionclass using theh11library for consistent HTTP/1.1 handling. - Both connection types use
asyncio.open_connectionstreams for a unified architecture. - HTTP/2 connections support stream multiplexing, allowing multiple concurrent requests over a single TCP connection.
- Add
http2parameter toClientSession(defaults toTrue) to control HTTP/2 usage. - Protocol detection is performed once per host and cached for efficiency.
- Add
h2>=4.0.0,<5.0.0as a new dependency. - Refactor HTTP/1.1 client implementation to use the
h11library instead of custom request writing methods fromblacksheep.scribe. This provides a more robust and standards-compliant HTTP/1.1 state machine, and creates consistency with the HTTP/2 implementation pattern. - The new
HTTP11Connectionclass replaces theasyncio.Protocol-based approach with a streams-based implementation. - Remove the legacy
ClientConnectionclass. - Both HTTP/1.1 and HTTP/2 implementations follow the same architectural pattern.
- Remove the option of passing the event loop to the constructor of client classes.
- Stop using
httptoolsfor anything. - Correct bugs in the code serving static files:
HTTP 304should not be returned forRangerequests, and handling of ranges.
v2.4.6
- Fix CRLF injection vulnerability in the BlackSheep HTTP Client, reported by Jinho Ju (@tr4ce-ju).
- Add a
SECURITY.mdfile. - Fix #646.
- Modify the
Cookiereprto not include the value in full, as it can contain secrets that would leak in logs. - Improve type annotations for several modules, by @tyzhnenko.
v2.4.5
v2.4.4
- Add support for annotated types in
OpenAPIHandlerreturn types, by @tyzhnenko. This feature is important to support automatic generation of OpenAPI Documentation when returning instances ofResponse(e.g.Annotated[Response, ProductDetails]). - Introduce
MiddlewareListandMiddlewareCategoryto simplify middleware management and ordering of middlewares (see #620). Middlewares are now automatically sorted by category (INIT, SESSION, AUTH, AUTHZ, BUSINESS, MESSAGE) and optional priority within each category. This ensures proper execution order (e.g., CORS before authentication, authentication before authorization) without requiring developers to manually manage middleware insertion order. The system maintains backward compatibility while providing a more intuitive and error-resistant approach to middleware configuration. The same improvement is applied both to theApplicationand to theClientSessionclasses. - Add support for
list[str]as a value forno-cacheandprivatedirectives in code handling cache control headers, by @karpetrosyan. - Fix bug #619, that caused surprising behavior (requiring an explicit fallback or catch-all route to handle web requests that didn't match any route, otherwise middlewares would be bypassed for the defined
NotFoundexception handler). - Change the text of
Bad Requestresponse body when the input from the client causes aTypeErrorwhen trying to bind to an instance of the expected type (it reduces the amount of details sent to the client). - Improve the user experience by ignoring extra properties in request body by default, when mapping to user-defined dataclasses, Pydantic v2 models, or classes (see #614). Previously, extra properties were not ignored by default and required the user to explicitly code their input classes to allow extra properties. This is also done for sub-properties, lists, and dictionaries. The user can still control how exactly input bodies from clients are converted using custom binders or altering
blacksheep.server.bindings.class_converters. - Add support for specifying OpenAPI tags for controllers. This simplifies handling tags for documentation (#616).
- Improve the build matrix to build wheels for
arm64architecture for Linux and Windows, and usecibuildwheelfor Ubuntu and Windows, by @bymoye and @RobertoPrevato. - Update type annotations to Python >= 3.10.
- Fix bug that would prevent union types described using pipes from being properly represented in OpenAPI specification.
- Add support for alternative programming-style naming for generic types in OpenAPI specification files. When enabled, type names use underscore notation closer to actual type annotations (e.g.,
PaginatedSet_Addressinstead ofPaginatedSetOfAddress,Dict_str_intinstead ofDictOfstrAndint). This can be controlled via theprogramming_namesparameter inDefaultSerializeror theAPP_OPENAPI_PROGRAMMING_NAMESenvironment variable, setting it to a truthy value ('1' or 'true'). - Make
EnvironmentSettingsread-only, refactor to not usedataclass. - Attach
EnvironmentSettingsto theApplicationobject for runtime inspection, which is useful for: transparency and debugging, testing (assert app.env_settings.force_https is True), health check endpoints or admin tools can expose configuration. - Add
HTTPSchemeMiddlewareto set request scheme when running behind reverse proxies or load balancers with TLS termination. See #631. - Add support for
APP_HTTP_SCHEMEenvironment variable to explicitly set the request scheme tohttporhttps. - Add support for
APP_FORCE_HTTPSenvironment variable to force HTTPS scheme and automatically enable HSTS (HTTP Strict Transport Security) headers. - Add automatic scheme middleware configuration via
configure_scheme_middleware()- applied during application startup when eitherAPP_HTTP_SCHEMEorAPP_FORCE_HTTPSis set. EnvironmentSettingsnow includeshttp_schemeandforce_httpsproperties that are automatically populated from environment variables.- Request scheme is now automatically configured based on environment settings, to simplify correct URL generation in proxied environments (e.g. OIDC redirections).
- Improve the
generate_secretto usesecrets.token_urlsafe(48)by default. - Improve
OpenIDSettings,CookieAuthentication, andAntiForgeryHandlerto handle secrets using theSecretclass fromessentials.secrets. Passing secrets asstrdirectly issues a deprecation warning and won't be supported in2.5.xor2.6.x.
Several issues were reported by @ockan, including issues in the documentation.
v2.4.3
- Add Python
3.14and remove3.9from the build matrix. - Drop support for Python
3.9(it reached EOL in October 2025). - Fix bug #605, that prevented the
JWTBearerAuthenticationscheme from being documented properly in OpenAPI Specification files. - Deprecate the
auth_modeparameter for theJWTBearerAuthenticationconstructor, and add a newschemeparameter that will replace it. - Improve the code to not require returning an empty
Identity()object in authentication handlers when authentication is not successful. - Upgrade
GuardPostto1.0.4, as it includes improved features and a built-in strategy to protect against brute-force authentication attempts (opt-in). - Upgrade
pydanticto a version supported by Python 3.14. - Remove support for Pydantic v1 in Python 3.14. Support for Pydantic v1 will be removed soon.
- Fix regression causing an import error when trying to use OpenAPI features without installing dependencies for JWT validation #606.
- Add verification step to the main workflow to verify that basic functionalities work without optional dependencies.
v2.4.2
- Add significant improvements to authentication and authorization features.
- Add built-in support for API Key Authentication.
- Add built-in support for Basic Authentication.
- Add built-in support for JWT Bearer authentication validating JWTs signed using symmetric encryption (previously the built-in classes only supported using asymmetric encryption to validate JWTs).
- Improve the
JWTBearerAuthenticationclass to support validating JWTs with both asymmetric and symmetric encryption. - Improve the code that generates OpenAPI Documentation to automatically include security
securitySchemesandsecuritysections byAuthenticationhandlers configured in the application. The feature can be extended with user-defined authentication handlers. - Improve the
@authdecorator to support specifying sufficient roles to authorize requests (@auth(roles=["admin"])). - Upgrade
GuardPostto1.0.3, as it includes improved features to handle roles and JWT validation using symmetric encryption. - Upgrade
essentialsto1.1.8as it includes aSecretclass to handle secrets in code. This class is used for safe handling of secrets in API Keys, Basic Credentials, and symmetric encryption for JWT Bearer authentication. It will be used in the future in all circumstances where BlackSheep code needs user-defined secrets. - Remove the code that required four env variables to be configured for the OTLP exporter (in the
use_open_telemetry_otlpfunction), because it didn't cover legitimate use cases supported by the OpenTelemetry SDK. It is responsibility of the developers to configure env variables according to their preference for OTLP. - The framework has been tested for
cryptography>=46.0.0and therefore update the dependency tocryptography>=45.0.2,<47.0.0.
"""
This example shows a basic example of API Key and Basic Authentication in BlackSheep.
uvicorn apitest:app --port 44777
curl http://127.0.0.1:44777 -H "X-API-Key: Foo"
"""
from dataclasses import dataclass
from essentials.secrets import Secret
from openapidocs.v3 import Info
from blacksheep import Application, get
from blacksheep.server.authentication.apikey import APIKey, APIKeyAuthentication
from blacksheep.server.authentication.basic import BasicAuthentication, BasicCredentials
from blacksheep.server.authorization import auth, allow_anonymous
from blacksheep.server.openapi.v3 import OpenAPIHandler
app = Application()
app.use_authentication().add(
APIKeyAuthentication(
APIKey(
secret=Secret("$API_SECRET"), # Obtained from API_SECRET env var
roles=["user"],
),
param_name="X-API-Key",
)
).add(
BasicAuthentication(
BasicCredentials(
username="admin",
password=Secret("$ADMIN_PASSWORD"), # Obtained from ADMIN_PASSWORD env var
roles=["admin"],
)
)
)
app.use_authorization()
# See the generated docs and how they include security sections
docs = OpenAPIHandler(info=Info(title="Example API", version="0.0.1"))
docs.bind_app(app)
@dataclass
class Foo:
foo: str
@allow_anonymous()
@get("/")
async def get_foo() -> Foo:
return Foo("Hello!")
@auth()
@get("/claims")
async def get_claims(request):
return request.user.claims
@auth(roles=["admin"], authentication_schemes=["Basic"])
@get("/for-admins")
async def for_admins_only(request):
return request.user.claims
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, port=44777)Tip
For a tutorial on OTLP and how it can be used with BlackSheep and an
OpenTelemetry Collector self-hosted in Kubernetes, see:
https://robertoprevato.github.io/K8sStudies/k3s/monitoring/
This tutorial explains how to self-host a monitoring stack in a single node in Kubernetes,
but the BlackSheep OTLP example is applicable to Grafana Cloud, too.
v2.4.1
- Correct bug in controller inheritance that would prevent argument types and return type hints from working as expected (#594). By @martinmkhitaryan.
- Improve the code responsible of mapping input request parameters into instances of desired types. Change the inner workings of
blacksheep.server.bindingsto make the code more configurable and easier to maintain. - Add support for
StrEnumandIntEnumto binders for request handlers' parameters. See #588. Enums can be mapped by key and by value. The class that matchesStrEnummake case sensitive checks; override the__missing__method of your user-defined enums to support case insensitive checks; or define a customStrEnumConverterclass. This feature requiresPython >= 3.11. - Add support for
Literalto binders for request handlers' parameters. See #588. String literals are case sensitive by default. - Minor breaking change. Remove the dependency on
python-dateutil(#544), which was always used to parse inputdatetimeparameters. The datetime parsing logic is replaced with a function that only supports the most common ISO formats:%Y-%m-%dT%H:%M:%S.%f,%Y-%m-%dT%H:%M:%S,%Y-%m-%d, and is much more performant for such formats. The new code API offers a simple way to keep usingpython-dateutilfor those who desire doing so. - Fix erroneous assumption when parsing a request body declared as
bytes. When the declared requested input body isbytes, the framework has been corrected to not require URL-safe base64 encoded data, and to read the input body as-is. - Add support for defining
convertfunctions in customBoundValueclasses that are used to convert Python objects from parsed JSON into more specific classes. - Correct bug that prevented request body input to be mapped properly to a
listusing the default logic. - Upgrade
pytest-asyncioto the latest version. Fix #596. - Fix a Cython segmentation fault happening when the user defines an exception handler with a wrong signature (#592), or that contains a bug and causes exceptions itself. Replace the Application
exception_handlersdictionary with a user defined dictionary that validates values, and change a piece of code that causes a recursive error when an exception handler itself is buggy. - Add support for specifying the status code in view functions (#591).
- Fix
licensefield inpyproject.toml.
v2.4.0
- SOME BREAKING CHANGES. Modify the built-in sessions to support any kind
of storage for the session information. It still defaults to storing sessions
in cookies, but allows defining a customSessionStoreto store information
where desired. Fix #542. Read the updated documentation on Sessions for more information. - Remove
charset-normalizerdependency. This library was used only when a
UnicodeDecodeErrorexception occurred when parsing the body of a web
request. This can happen in two circumstances: when the client sends a
payload specifying the wrong encoding in theContent-Typerequest header,
or when the client sends a payload that is notUTF-8encoded and without
specifying the charset encoding. Fix #581. - Now the framework always returns
Bad Requestwith a useful error message
in the response payload, in the circumstances described in the point above. - Correct bug in the
parse_charsetfunction that prevented proper parsing and
optimal handling of input encodings different thanUTF8. Parsing still
worked in this case because of the automatic fallback to
charset-normalizer. - Correct the output of
request.charsetwhen the charset is obtained from the
'Content-Type' request header.
v2.3.2
- Add built-in features to enable
OpenTelemetrylogging for all web requests and exceptions,
based on the examples provided in the BlackSheep-Examples repository. See docs here. - Fix #577. Server-Sent Events should be written with
\ninstead of\r\n.