mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-31 16:36:20 +00:00
Reorganize into shared file.
This commit is contained in:
parent
9c20ac8e7b
commit
90a25d0109
@ -24,7 +24,7 @@ from base64 import b64encode
|
|||||||
import attr
|
import attr
|
||||||
|
|
||||||
# TODO Make sure to import Python version?
|
# TODO Make sure to import Python version?
|
||||||
from cbor2 import loads
|
from cbor2 import loads, dumps
|
||||||
|
|
||||||
|
|
||||||
from twisted.web.http_headers import Headers
|
from twisted.web.http_headers import Headers
|
||||||
@ -32,6 +32,8 @@ from twisted.internet.defer import inlineCallbacks, returnValue, fail, Deferred
|
|||||||
from hyperlink import DecodedURL
|
from hyperlink import DecodedURL
|
||||||
import treq
|
import treq
|
||||||
|
|
||||||
|
from .http_common import swissnum_auth_header, Secrets
|
||||||
|
|
||||||
|
|
||||||
class ClientException(Exception):
|
class ClientException(Exception):
|
||||||
"""An unexpected error."""
|
"""An unexpected error."""
|
||||||
@ -44,11 +46,6 @@ def _decode_cbor(response):
|
|||||||
return fail(ClientException(response.code, response.phrase))
|
return fail(ClientException(response.code, response.phrase))
|
||||||
|
|
||||||
|
|
||||||
def swissnum_auth_header(swissnum): # type: (bytes) -> bytes
|
|
||||||
"""Return value for ``Authentication`` header."""
|
|
||||||
return b"Tahoe-LAFS " + b64encode(swissnum).strip()
|
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
class ImmutableCreateResult(object):
|
class ImmutableCreateResult(object):
|
||||||
"""Result of creating a storage index for an immutable."""
|
"""Result of creating a storage index for an immutable."""
|
||||||
@ -57,12 +54,75 @@ class ImmutableCreateResult(object):
|
|||||||
allocated = attr.ib(type=Set[int])
|
allocated = attr.ib(type=Set[int])
|
||||||
|
|
||||||
|
|
||||||
|
class StorageClient(object):
|
||||||
|
"""
|
||||||
|
HTTP client that talks to the HTTP storage server.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, url, swissnum, treq=treq
|
||||||
|
): # type: (DecodedURL, bytes, Union[treq,StubTreq]) -> None
|
||||||
|
self._base_url = url
|
||||||
|
self._swissnum = swissnum
|
||||||
|
self._treq = treq
|
||||||
|
|
||||||
|
def _url(self, path):
|
||||||
|
"""Get a URL relative to the base URL."""
|
||||||
|
return self._base_url.click(path)
|
||||||
|
|
||||||
|
def _get_headers(self): # type: () -> Headers
|
||||||
|
"""Return the basic headers to be used by default."""
|
||||||
|
headers = Headers()
|
||||||
|
headers.addRawHeader(
|
||||||
|
"Authorization",
|
||||||
|
swissnum_auth_header(self._swissnum),
|
||||||
|
)
|
||||||
|
return headers
|
||||||
|
|
||||||
|
def _request(
|
||||||
|
self,
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
lease_renewal_secret=None,
|
||||||
|
lease_cancel_secret=None,
|
||||||
|
upload_secret=None,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Like ``treq.request()``, but with optional secrets that get translated
|
||||||
|
into corresponding HTTP headers.
|
||||||
|
"""
|
||||||
|
headers = self._get_headers()
|
||||||
|
for secret, value in [
|
||||||
|
(Secrets.LEASE_RENEW, lease_renewal_secret),
|
||||||
|
(Secrets.LEASE_CANCEL, lease_cancel_secret),
|
||||||
|
(Secrets.UPLOAD, upload_secret),
|
||||||
|
]:
|
||||||
|
if value is None:
|
||||||
|
continue
|
||||||
|
headers.addRawHeader(
|
||||||
|
"X-Tahoe-Authorization",
|
||||||
|
b"%s %s" % (secret.value.encode("ascii"), b64encode(value).strip()),
|
||||||
|
)
|
||||||
|
return self._treq.request(method, url, headers=headers, **kwargs)
|
||||||
|
|
||||||
|
@inlineCallbacks
|
||||||
|
def get_version(self):
|
||||||
|
"""
|
||||||
|
Return the version metadata for the server.
|
||||||
|
"""
|
||||||
|
url = self._url("/v1/version")
|
||||||
|
response = yield self._request("GET", url, {})
|
||||||
|
decoded_response = yield _decode_cbor(response)
|
||||||
|
returnValue(decoded_response)
|
||||||
|
|
||||||
|
|
||||||
class StorageClientImmutables(object):
|
class StorageClientImmutables(object):
|
||||||
"""
|
"""
|
||||||
APIs for interacting with immutables.
|
APIs for interacting with immutables.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, client): # type: (StorageClient) -> None
|
def __init__(self, client: StorageClient):# # type: (StorageClient) -> None
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
||||||
@inlineCallbacks
|
@inlineCallbacks
|
||||||
@ -87,6 +147,11 @@ 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"))
|
||||||
|
message = dumps(
|
||||||
|
{"share-numbers": share_numbers, "allocated-size": allocated_size}
|
||||||
|
)
|
||||||
|
self._client._request("POST", )
|
||||||
|
|
||||||
@inlineCallbacks
|
@inlineCallbacks
|
||||||
def write_share_chunk(
|
def write_share_chunk(
|
||||||
@ -121,48 +186,3 @@ class StorageClientImmutables(object):
|
|||||||
the HTTP protocol will be simplified, see
|
the HTTP protocol will be simplified, see
|
||||||
https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3777
|
https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3777
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class StorageClient(object):
|
|
||||||
"""
|
|
||||||
HTTP client that talks to the HTTP storage server.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self, url, swissnum, treq=treq
|
|
||||||
): # type: (DecodedURL, bytes, Union[treq,StubTreq]) -> None
|
|
||||||
self._base_url = url
|
|
||||||
self._swissnum = swissnum
|
|
||||||
self._treq = treq
|
|
||||||
|
|
||||||
def _get_headers(self): # type: () -> Headers
|
|
||||||
"""Return the basic headers to be used by default."""
|
|
||||||
headers = Headers()
|
|
||||||
headers.addRawHeader(
|
|
||||||
"Authorization",
|
|
||||||
swissnum_auth_header(self._swissnum),
|
|
||||||
)
|
|
||||||
return headers
|
|
||||||
|
|
||||||
def _request(self, method, url, secrets, **kwargs):
|
|
||||||
"""
|
|
||||||
Like ``treq.request()``, but additional argument of secrets mapping
|
|
||||||
``http_server.Secret`` to the bytes value of the secret.
|
|
||||||
"""
|
|
||||||
headers = self._get_headers()
|
|
||||||
for key, value in secrets.items():
|
|
||||||
headers.addRawHeader(
|
|
||||||
"X-Tahoe-Authorization",
|
|
||||||
b"%s %s" % (key.value.encode("ascii"), b64encode(value).strip()),
|
|
||||||
)
|
|
||||||
return self._treq.request(method, url, headers=headers, **kwargs)
|
|
||||||
|
|
||||||
@inlineCallbacks
|
|
||||||
def get_version(self):
|
|
||||||
"""
|
|
||||||
Return the version metadata for the server.
|
|
||||||
"""
|
|
||||||
url = self._base_url.click("/v1/version")
|
|
||||||
response = yield self._request("GET", url, {})
|
|
||||||
decoded_response = yield _decode_cbor(response)
|
|
||||||
returnValue(decoded_response)
|
|
||||||
|
25
src/allmydata/storage/http_common.py
Normal file
25
src/allmydata/storage/http_common.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
"""
|
||||||
|
Common HTTP infrastructure for the storge server.
|
||||||
|
"""
|
||||||
|
from future.utils import PY2
|
||||||
|
|
||||||
|
if PY2:
|
||||||
|
# fmt: off
|
||||||
|
from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401
|
||||||
|
# fmt: on
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
from base64 import b64encode
|
||||||
|
|
||||||
|
|
||||||
|
def swissnum_auth_header(swissnum): # type: (bytes) -> bytes
|
||||||
|
"""Return value for ``Authentication`` header."""
|
||||||
|
return b"Tahoe-LAFS " + b64encode(swissnum).strip()
|
||||||
|
|
||||||
|
|
||||||
|
class Secrets(Enum):
|
||||||
|
"""Different kinds of secrets the client may send."""
|
||||||
|
|
||||||
|
LEASE_RENEW = "lease-renew-secret"
|
||||||
|
LEASE_CANCEL = "lease-cancel-secret"
|
||||||
|
UPLOAD = "upload-secret"
|
@ -17,7 +17,6 @@ else:
|
|||||||
from typing import Dict, List, Set
|
from typing import Dict, List, Set
|
||||||
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from enum import Enum
|
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
|
|
||||||
from klein import Klein
|
from klein import Klein
|
||||||
@ -28,19 +27,11 @@ import attr
|
|||||||
from cbor2 import dumps, loads
|
from cbor2 import dumps, loads
|
||||||
|
|
||||||
from .server import StorageServer
|
from .server import StorageServer
|
||||||
from .http_client import swissnum_auth_header
|
from .http_common import swissnum_auth_header, Secrets
|
||||||
from .immutable import BucketWriter
|
from .immutable import BucketWriter
|
||||||
from ..util.hashutil import timing_safe_compare
|
from ..util.hashutil import timing_safe_compare
|
||||||
|
|
||||||
|
|
||||||
class Secrets(Enum):
|
|
||||||
"""Different kinds of secrets the client may send."""
|
|
||||||
|
|
||||||
LEASE_RENEW = "lease-renew-secret"
|
|
||||||
LEASE_CANCEL = "lease-cancel-secret"
|
|
||||||
UPLOAD = "upload-secret"
|
|
||||||
|
|
||||||
|
|
||||||
class ClientSecretsException(Exception):
|
class ClientSecretsException(Exception):
|
||||||
"""The client did not send the appropriate secrets."""
|
"""The client did not send the appropriate secrets."""
|
||||||
|
|
||||||
@ -201,3 +192,4 @@ class HTTPServer(object):
|
|||||||
# New upload.
|
# New upload.
|
||||||
# TODO self._storage_server.allocate_buckets() with given inputs.
|
# TODO self._storage_server.allocate_buckets() with given inputs.
|
||||||
# TODO add results to self._uploads.
|
# TODO add results to self._uploads.
|
||||||
|
pass
|
||||||
|
Loading…
x
Reference in New Issue
Block a user