Skip to content

Releases: Neoteroi/BlackSheep

v2.5.1

30 Jan 21:07
9accc9b

Choose a tag to compare

  • Fix problem in workflow and the PyPy distribution wheels.

v2.5.0

29 Jan 21:29
ebd7022

Choose a tag to compare

  • 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 HTTP2Connection class using the h2 library for HTTP/2 protocol handling.
  • Add new HTTP11Connection class using the h11 library for consistent HTTP/1.1 handling.
  • Both connection types use asyncio.open_connection streams for a unified architecture.
  • HTTP/2 connections support stream multiplexing, allowing multiple concurrent requests over a single TCP connection.
  • Add http2 parameter to ClientSession (defaults to True) to control HTTP/2 usage.
  • Protocol detection is performed once per host and cached for efficiency.
  • Add h2>=4.0.0,<5.0.0 as a new dependency.
  • Refactor HTTP/1.1 client implementation to use the h11 library instead of custom request writing methods from blacksheep.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 HTTP11Connection class replaces the asyncio.Protocol-based approach with a streams-based implementation.
  • Remove the legacy ClientConnection class.
  • 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 httptools for anything.
  • Correct bugs in the code serving static files: HTTP 304 should not be returned for Range requests, and handling of ranges.

v2.4.6

13 Jan 17:28

Choose a tag to compare

  • Fix CRLF injection vulnerability in the BlackSheep HTTP Client, reported by Jinho Ju (@tr4ce-ju).
  • Add a SECURITY.md file.
  • Fix #646.
  • Modify the Cookie repr to 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

15 Nov 20:34
1fcd119

Choose a tag to compare

  • Fix regression #636.

v2.4.4

15 Nov 18:12
9c6d06b

Choose a tag to compare

  • Add support for annotated types in OpenAPIHandler return types, by @tyzhnenko. This feature is important to support automatic generation of OpenAPI Documentation when returning instances of Response (e.g. Annotated[Response, ProductDetails]).
  • Introduce MiddlewareList and MiddlewareCategory to 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 the Application and to the ClientSession classes.
  • Add support for list[str] as a value for no-cache and private directives 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 NotFound exception handler).
  • Change the text of Bad Request response body when the input from the client causes a TypeError when 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 arm64 architecture for Linux and Windows, and use cibuildwheel for 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_Address instead of PaginatedSetOfAddress, Dict_str_int instead of DictOfstrAndint). This can be controlled via the programming_names parameter in DefaultSerializer or the APP_OPENAPI_PROGRAMMING_NAMES environment variable, setting it to a truthy value ('1' or 'true').
  • Make EnvironmentSettings read-only, refactor to not use dataclass.
  • Attach EnvironmentSettings to the Application object 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 HTTPSchemeMiddleware to set request scheme when running behind reverse proxies or load balancers with TLS termination. See #631.
  • Add support for APP_HTTP_SCHEME environment variable to explicitly set the request scheme to http or https.
  • Add support for APP_FORCE_HTTPS environment 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 either APP_HTTP_SCHEME or APP_FORCE_HTTPS is set.
  • EnvironmentSettings now includes http_scheme and force_https properties 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_secret to use secrets.token_urlsafe(48) by default.
  • Improve OpenIDSettings, CookieAuthentication, and AntiForgeryHandler to handle secrets using the Secret class from essentials.secrets. Passing secrets as str directly issues a deprecation warning and won't be supported in 2.5.x or 2.6.x.

Several issues were reported by @ockan, including issues in the documentation.

v2.4.3

19 Oct 07:23
8f82962

Choose a tag to compare

  • Add Python 3.14 and remove 3.9 from the build matrix.
  • Drop support for Python 3.9 (it reached EOL in October 2025).
  • Fix bug #605, that prevented the JWTBearerAuthentication scheme from being documented properly in OpenAPI Specification files.
  • Deprecate the auth_mode parameter for the JWTBearerAuthentication constructor, and add a new scheme parameter that will replace it.
  • Improve the code to not require returning an empty Identity() object in authentication handlers when authentication is not successful.
  • Upgrade GuardPost to 1.0.4, as it includes improved features and a built-in strategy to protect against brute-force authentication attempts (opt-in).
  • Upgrade pydantic to 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

04 Oct 08:16
433ae98

Choose a tag to compare

  • 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 JWTBearerAuthentication class to support validating JWTs with both asymmetric and symmetric encryption.
  • Improve the code that generates OpenAPI Documentation to automatically include security securitySchemes and security sections by Authentication handlers configured in the application. The feature can be extended with user-defined authentication handlers.
  • Improve the @auth decorator to support specifying sufficient roles to authorize requests (@auth(roles=["admin"])).
  • Upgrade GuardPost to 1.0.3, as it includes improved features to handle roles and JWT validation using symmetric encryption.
  • Upgrade essentials to 1.1.8 as it includes a Secret class 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_otlp function), 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.0 and therefore update the dependency to cryptography>=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

28 Sep 15:33
d07e40f

Choose a tag to compare

  • 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.bindings to make the code more configurable and easier to maintain.
  • Add support for StrEnum and IntEnum to binders for request handlers' parameters. See #588. Enums can be mapped by key and by value. The class that matches StrEnum make case sensitive checks; override the __missing__ method of your user-defined enums to support case insensitive checks; or define a custom StrEnumConverter class. This feature requires Python >= 3.11.
  • Add support for Literal to 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 input datetime parameters. 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 using python-dateutil for those who desire doing so.
  • Fix erroneous assumption when parsing a request body declared as bytes. When the declared requested input body is bytes, 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 convert functions in custom BoundValue classes 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 list using the default logic.
  • Upgrade pytest-asyncio to 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_handlers dictionary 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 license field in pyproject.toml.

v2.4.0

22 Jun 20:48

Choose a tag to compare

  • 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 custom SessionStore to store information
    where desired. Fix #542. Read the updated documentation on Sessions for more information.
  • Remove charset-normalizer dependency. This library was used only when a
    UnicodeDecodeError exception 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 the Content-Type request header,
    or when the client sends a payload that is not UTF-8 encoded and without
    specifying the charset encoding. Fix #581.
  • Now the framework always returns Bad Request with a useful error message
    in the response payload, in the circumstances described in the point above.
  • Correct bug in the parse_charset function that prevented proper parsing and
    optimal handling of input encodings different than UTF8. Parsing still
    worked in this case because of the automatic fallback to
    charset-normalizer.
  • Correct the output of request.charset when the charset is obtained from the
    'Content-Type' request header.

v2.3.2

17 Jun 20:03
7e9101f

Choose a tag to compare

  • Add built-in features to enable OpenTelemetry logging 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 \n instead of \r\n.