Skip to content

feat(content-type): Add #[Consumes] annotation for per-service content type control #151

Description

@usernane

Problem Statement

WebServicesManager::POST_CONTENT_TYPES is a hardcoded constant that only allows application/x-www-form-urlencoded, multipart/form-data, and application/json for POST/PUT requests. Any other content type (e.g. application/octet-stream) gets rejected with a 415 before the service code runs.

This forces developers to use closure routes instead of proper WebService classes for endpoints that accept raw binary uploads, XML, CSV, or other content types.

Proposed Solution

Add a #[Consumes] annotation that allows a service method to declare which content types it accepts:

#[PostMapping]
#[Consumes(['application/octet-stream'])]
public function streamUpload(): array {
    // raw body is the file — no parameter parsing
}

Behavior:

  • If #[Consumes] is not present, the current three defaults apply (backward compatible).
  • If #[Consumes] is present, only the listed types are accepted for that method.
  • When a non-standard content type is used, parameter filtering/parsing is skipped (the body is raw).

This keeps the safe defaults while allowing opt-in for legitimate use cases.

Alternatives Considered

  1. Global method (WebServicesManager::addSupportedContentType()) — simpler but less precise; opens the type for all services, not just the one that needs it.
  2. Making it fully open (accept any content type) — reduces safety; services expecting JSON would silently receive garbage.
  3. Using closure routes — current workaround, but loses annotation-based routing, OpenAPI generation, and testing via ServiceTestCase.

Breaking Change

No

Additional Context

Use case: StreamingUploader and ResumableUploader from webfiori/file read from php://input with application/octet-stream. Currently these cannot be wrapped in a WebService class.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions