Some progress towards bucket allocation endpoint, and defining the protocol better.

This commit is contained in:
Itamar Turner-Trauring 2022-01-12 11:51:56 -05:00
parent c4bb3c21d1
commit f5437d9be7
3 changed files with 40 additions and 9 deletions

View File

@ -382,6 +382,11 @@ the server will respond with ``400 BAD REQUEST``.
If authorization using the secret fails, then a ``401 UNAUTHORIZED`` response should be sent.
Encoding
~~~~~~~~
* ``storage_index`` should be base32 encoded (RFC3548) in URLs.
General
~~~~~~~

View File

@ -34,6 +34,12 @@ from hyperlink import DecodedURL
import treq
from .http_common import swissnum_auth_header, Secrets
from .common import si_b2a
def _encode_si(si): # type: (bytes) -> str
"""Encode the storage index into Unicode string."""
return str(si_b2a(si), "ascii")
class ClientException(Exception):
@ -151,7 +157,7 @@ class StorageClientImmutables(object):
Result fires when creating the storage index succeeded, if creating the
storage index failed the result will fire with an exception.
"""
url = self._client._url("/v1/immutable/" + str(storage_index, "ascii"))
url = self._client._url("/v1/immutable/" + _encode_si(storage_index))
message = dumps(
{"share-numbers": share_numbers, "allocated-size": allocated_size}
)
@ -189,7 +195,7 @@ class StorageClientImmutables(object):
been uploaded.
"""
url = self._client._url(
"/v1/immutable/{}/{}".format(str(storage_index, "ascii"), share_number)
"/v1/immutable/{}/{}".format(_encode_si(storage_index), share_number)
)
response = yield self._client._request(
"POST",
@ -238,7 +244,7 @@ class StorageClientImmutables(object):
https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3777
"""
url = self._client._url(
"/v1/immutable/{}/{}".format(str(storage_index, "ascii"), share_number)
"/v1/immutable/{}/{}".format(_encode_si(storage_index), share_number)
)
response = yield self._client._request(
"GET",

View File

@ -28,6 +28,7 @@ from cbor2 import dumps, loads
from .server import StorageServer
from .http_common import swissnum_auth_header, Secrets
from .common import si_a2b
from .immutable import BucketWriter
from ..util.hashutil import timing_safe_compare
@ -174,6 +175,7 @@ class HTTPServer(object):
)
def allocate_buckets(self, request, authorization, storage_index):
"""Allocate buckets."""
storage_index = si_a2b(storage_index.encode("ascii"))
info = loads(request.content.read())
upload_key = authorization[Secrets.UPLOAD]
@ -191,13 +193,29 @@ class HTTPServer(object):
pass
else:
# New upload.
# TODO self._storage_server.allocate_buckets() with given inputs.
# TODO add results to self._uploads.
pass
already_got, sharenum_to_bucket = self._storage_server.allocate_buckets(
storage_index,
renew_secret=authorization[Secrets.LEASE_RENEW],
cancel_secret=authorization[Secrets.LEASE_CANCEL],
sharenums=info["share-numbers"],
allocated_size=info["allocated-size"],
)
self._uploads[storage_index] = StorageIndexUploads(
shares=sharenum_to_bucket, upload_key=authorization[Secrets.UPLOAD]
)
return self._cbor(
request,
{
"already-have": set(already_got),
"allocated": set(sharenum_to_bucket),
},
)
@_authorized_route(
_app,
{Secrets.UPLOAD}, "/v1/immutable/<string:storage_index>/<int:share_number>", methods=["PATCH"]
{Secrets.UPLOAD},
"/v1/immutable/<string:storage_index>/<int:share_number>",
methods=["PATCH"],
)
def write_share_data(self, request, authorization, storage_index, share_number):
"""Write data to an in-progress immutable upload."""
@ -212,7 +230,10 @@ class HTTPServer(object):
# TODO if it finished writing altogether, 201 CREATED. Otherwise 200 OK.
@_authorized_route(
_app, set(), "/v1/immutable/<string:storage_index>/<int:share_number>", methods=["GET"]
_app,
set(),
"/v1/immutable/<string:storage_index>/<int:share_number>",
methods=["GET"],
)
def read_share_chunk(self, request, authorization, storage_index, share_number):
"""Read a chunk for an already uploaded immutable."""
@ -221,4 +242,3 @@ class HTTPServer(object):
# TODO lookup the share
# TODO if not found, 404
# TODO otherwise, return data from that offset