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. 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 General
~~~~~~~ ~~~~~~~

View File

@ -34,6 +34,12 @@ from hyperlink import DecodedURL
import treq import treq
from .http_common import swissnum_auth_header, Secrets 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): class ClientException(Exception):
@ -151,7 +157,7 @@ class StorageClientImmutables(object):
Result fires when creating the storage index succeeded, if creating the Result fires when creating the storage index succeeded, if creating the
storage index failed the result will fire with an exception. 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( message = dumps(
{"share-numbers": share_numbers, "allocated-size": allocated_size} {"share-numbers": share_numbers, "allocated-size": allocated_size}
) )
@ -189,7 +195,7 @@ class StorageClientImmutables(object):
been uploaded. been uploaded.
""" """
url = self._client._url( 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( response = yield self._client._request(
"POST", "POST",
@ -238,7 +244,7 @@ class StorageClientImmutables(object):
https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3777 https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3777
""" """
url = self._client._url( 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( response = yield self._client._request(
"GET", "GET",

View File

@ -28,6 +28,7 @@ from cbor2 import dumps, loads
from .server import StorageServer from .server import StorageServer
from .http_common import swissnum_auth_header, Secrets from .http_common import swissnum_auth_header, Secrets
from .common import si_a2b
from .immutable import BucketWriter from .immutable import BucketWriter
from ..util.hashutil import timing_safe_compare from ..util.hashutil import timing_safe_compare
@ -174,6 +175,7 @@ class HTTPServer(object):
) )
def allocate_buckets(self, request, authorization, storage_index): def allocate_buckets(self, request, authorization, storage_index):
"""Allocate buckets.""" """Allocate buckets."""
storage_index = si_a2b(storage_index.encode("ascii"))
info = loads(request.content.read()) info = loads(request.content.read())
upload_key = authorization[Secrets.UPLOAD] upload_key = authorization[Secrets.UPLOAD]
@ -191,13 +193,29 @@ class HTTPServer(object):
pass pass
else: else:
# New upload. # New upload.
# TODO self._storage_server.allocate_buckets() with given inputs. already_got, sharenum_to_bucket = self._storage_server.allocate_buckets(
# TODO add results to self._uploads. storage_index,
pass 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( @_authorized_route(
_app, _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): def write_share_data(self, request, authorization, storage_index, share_number):
"""Write data to an in-progress immutable upload.""" """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. # TODO if it finished writing altogether, 201 CREATED. Otherwise 200 OK.
@_authorized_route( @_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): def read_share_chunk(self, request, authorization, storage_index, share_number):
"""Read a chunk for an already uploaded immutable.""" """Read a chunk for an already uploaded immutable."""
@ -221,4 +242,3 @@ class HTTPServer(object):
# TODO lookup the share # TODO lookup the share
# TODO if not found, 404 # TODO if not found, 404
# TODO otherwise, return data from that offset # TODO otherwise, return data from that offset