NAME
Net::Blossom::Server - Server-side support for the Blossom protocol
SYNOPSIS
use Net::Blossom::Server;
my $server = Net::Blossom::Server->new(
storage => $storage,
);
DESCRIPTION
Net::Blossom::Server is the framework-neutral server core for the Blossom protocol. Gateway adapters such as PSGI or PAGI should translate native requests into Net::Blossom::Server::Request objects and translate Net::Blossom::Server::Response objects back to their gateway format.
Server support lives in a separate CPAN distribution so client users do not need server, storage, daemon, or web framework dependencies.
CONSTRUCTOR
new
my $server = Net::Blossom::Server->new(%args);
Required arguments:
storageStorage object that satisfies Net::Blossom::Server::Storage.
Optional arguments:
chunk_sizePositive integer read size used when copying stream bodies. Defaults to
65536.clockCode reference returning the upload timestamp. Defaults to
time.mirror_fetcherOptional code reference or object with
fetch_blob. This is required forPUT /mirror. Mirror fetchers stream origin bytes into a server-provided sink; no default network fetcher is provided.max_upload_bytesOptional positive integer bounding the size of an accepted upload. When set,
PUT /upload,PUT /media, and mirrored origin bodies that exceed it are rejected with413and the partial upload is aborted. Defaults to unset (no limit).max_list_limitPositive integer maximum
GET /list/<pubkey>page size. List requests without alimitquery parameter use this value as the default. Requests with a largerlimitare rejected with400. Defaults to100.
Unknown arguments or invalid values croak.
ACCESSORS
storage
Returns the configured storage object.
chunk_size
Returns the stream copy chunk size.
clock
Returns the clock code reference.
mirror_fetcher
Returns the optional mirror fetcher.
max_upload_bytes
Returns the configured maximum upload size, or undef when uploads are not size-limited.
max_list_limit
Returns the configured maximum list page size.
METHODS
receive_blob
my $result = $server->receive_blob($body, %opts);
Copies a scalar or stream body into storage while computing SHA-256 in the server core. Returns a Net::Blossom::Server::UploadResult.
Options:
typeBlob media type. Defaults to
application/octet-stream.expected_sha256Optional lowercase 64-character SHA-256 hash. When present, the computed hash must match before the upload is committed.
allowed_sha256Optional array reference of lowercase 64-character SHA-256 hashes. When present, the computed hash must match one of these values before the upload is committed. This is used for deferred BUD-11
PUT /mirrorauthorization.content_lengthOptional expected body size. When present, the copied byte count must match before the upload is committed.
uploadedOptional upload timestamp. Defaults to
$server->clock->().pubkeyOptional uploader public key as lowercase 64-character hex. Gateway adapters will normally derive this from BUD-11 authorization.
sha256_mismatch_statusOptional HTTP status code for SHA-256 mismatches. When supplied, mismatches throw Net::Blossom::Server::Error with this status instead of croaking with a plain string.
sha256_mismatch_reasonOptional reason string used with
sha256_mismatch_status.content_length_mismatch_statusOptional HTTP status code for content-length mismatches. When supplied, mismatches throw Net::Blossom::Server::Error with this status instead of croaking with a plain string.
content_length_mismatch_reasonOptional reason string used with
content_length_mismatch_status.
The storage upload is aborted if hashing, length validation, SHA-256 validation, or storage writing fails.
Storage commit results that are raw Net::Blossom::BlobDescriptor objects or descriptor hash references are accepted as newly created uploads for compatibility with early storage implementations. New storage implementations should return a Net::Blossom::Server::UploadResult or a hash reference with descriptor and created.
handle_upload
my $response = $server->handle_upload($request, %opts);
Handles a normalized PUT /upload request and returns a Net::Blossom::Server::Response. The request must be a Net::Blossom::Server::Request with a defined body.
The method passes the request body, content type, content length, optional X-SHA-256, and optional pubkey into receive_blob. When X-SHA-256 is present, a hash mismatch throws a typed 409 error before storage commit. Content-Length mismatches throw a typed 400 error before storage commit. The response body is the blob descriptor encoded as JSON. The response status is 201 when the blob was newly stored and 200 when it already existed.
Options:
pubkeyOptional already-verified uploader public key as lowercase 64-character hex. Authorization verification is deliberately outside this method.
handle_head_upload
my $response = $server->handle_head_upload($request);
Handles a normalized HEAD /upload BUD-06 preflight request. It validates the X-SHA-256, X-Content-Type, and X-Content-Length headers and returns an empty 200 response when the metadata is well-formed. Malformed metadata returns 400; missing X-Content-Length returns 411.
handle_get_blob
my $response = $server->handle_get_blob($request);
Handles a normalized GET /<sha256> request and returns a Net::Blossom::Server::Response. The request path must contain one lowercase 64-character SHA-256 hash segment and may include a file extension.
The method calls $server->storage->get_blob($sha256). It returns 404 when storage returns undef. Otherwise, storage must return a Net::Blossom::Server::BlobResult whose descriptor sha256 matches the request path. The response status is 200, the response body is the blob body, and Content-Type and Content-Length come from the descriptor.
handle_head_blob
my $response = $server->handle_head_blob($request);
Handles a normalized HEAD /<sha256> request and returns the same Content-Type and Content-Length headers as GET /<sha256> without returning the blob body. The request path may include a file extension.
If storage provides an optional head_blob($sha256) method, that method is used and may return either a Net::Blossom::BlobDescriptor or a Net::Blossom::Server::BlobResult. Otherwise get_blob is used and the body is discarded.
handle_media
my $response = $server->handle_media($request, %opts);
Handles a normalized PUT /media request. The current implementation uses the same identity byte path as PUT /upload: it stores the received bytes without media transformation and returns a blob descriptor JSON response with 201 or 200. When X-SHA-256 is present, a hash mismatch throws a typed 409 error before storage commit. Content-Length mismatches throw a typed 400 error before storage commit.
Options:
pubkeyOptional already-verified uploader public key as lowercase 64-character hex.
handle_head_media
my $response = $server->handle_head_media($request);
Handles a normalized HEAD /media BUD-05 preflight request. It validates the X-SHA-256, X-Content-Type, and X-Content-Length headers and returns the same status behavior as handle_head_upload.
handle_mirror
my $response = $server->handle_mirror($request, %opts);
Handles a normalized PUT /mirror request. The request body must be a JSON object with a url field. The URL must use http or https, have a host, must not include userinfo, and must not include a fragment.
The server calls the configured mirror_fetcher with a streaming sink and stores origin bytes as the fetcher writes them. SHA-256 calculation and storage commit remain owned by the server core. A missing mirror_fetcher returns 503. Malformed mirror requests return 400. Origin fetch failures, unusable fetch results, or origin content-length mismatches return 502.
The fetcher may be a code reference called with $url and sink => $sink, or an object called as $fetcher->fetch_blob($url, sink => $sink). It must call $sink->start(%metadata) before writing bytes, then call $sink->write($chunk) for each scalar byte chunk. %metadata may include type and content_length; missing type defaults to application/octet-stream. For empty origin bodies, the fetcher may instead return a metadata hash reference and let the server start the sink. Returning a body value is not supported.
Options:
pubkeyOptional already-verified uploader public key.
authorizationOptional Net::Blossom::Server::AuthorizationResult. When provided, the downloaded blob hash must match one of the authorized
xtag hashes before storage commit, otherwise a typed409error is thrown.
handle_delete_blob
my $response = $server->handle_delete_blob($request, pubkey => $pubkey);
Handles a normalized DELETE /<sha256> request and returns a Net::Blossom::Server::Response. The request path must contain one lowercase 64-character SHA-256 hash segment.
pubkey is required and must be the already-verified owner public key as lowercase 64-character hex. Authorization event verification is deliberately outside this method.
The method calls $server->storage->delete_blob($sha256, pubkey => $pubkey). It returns 204 when storage deletes an owner relationship and 404 when storage returns false.
handle_list_blobs
my $response = $server->handle_list_blobs($request);
Handles a normalized GET /list/<pubkey> request and returns a Net::Blossom::Server::Response. The request path must contain one lowercase 64-character public key segment.
The method reads optional cursor and limit query parameters. cursor must be a lowercase 64-character SHA-256 hash. limit must be a positive integer no larger than max_list_limit. Requests without limit use max_list_limit as the default page size. Storage receives a bounded limit for every list request.
The method calls $server->storage->list_blobs($pubkey, %opts) and returns status 200 with a JSON array of blob descriptors. Storage must return an array reference of Net::Blossom::BlobDescriptor objects.
handle_request
my $response = $server->handle_request($request, %opts);
Dispatches a normalized Net::Blossom::Server::Request and returns a Net::Blossom::Server::Response. This is the framework-neutral routing entry point for future gateway adapters.
Currently implemented routes:
PUT /uploadDelegates to
handle_upload.HEAD /uploadDelegates to
handle_head_upload.PUT /mediaDelegates to
handle_media.HEAD /mediaDelegates to
handle_head_media.PUT /mirrorDelegates to
handle_mirror.GET /<sha256>Delegates to
handle_get_blob.HEAD /<sha256>Delegates to
handle_head_blob.DELETE /<sha256>Delegates to
handle_delete_blob.GET /list/<pubkey>Delegates to
handle_list_blobs.
Unknown paths return 404. Known paths with unsupported methods return 405.
Options:
pubkeyOptional already-verified uploader public key. Passed through to upload, media, mirror, and delete handlers as needed.
authorizationOptional Net::Blossom::Server::AuthorizationResult. Passed through to
handle_mirrorfor deferred hash authorization.
STATUS
The server core is under active development. It implements the protocol handlers documented above and remains framework-neutral.