summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2022-04-06 09:51:31 +0300
committerLars Wirzenius <liw@liw.fi>2022-04-06 09:51:31 +0300
commit6defd70a2df0975ee22b09018a9dc709a7933200 (patch)
treef161b7958c3e6975d0bc2dbdef2bf3175e4d6216
parent1c6ae813b00e46d2a8061fa480d1780124af1e64 (diff)
downloadobnam2-6defd70a2df0975ee22b09018a9dc709a7933200.tar.gz
feat! add chunk server API version to HTTP paths
What was /chunks is now /v1/chunks. This is the minimal step to start supporting multiple API versions. Also, /v1/chunks/foo/bar is no longer supported. Sponsored-by: author
-rw-r--r--obnam.md34
-rw-r--r--src/bin/obnam-server.rs8
-rw-r--r--src/client.rs2
-rw-r--r--subplot/server.py8
-rw-r--r--subplot/server.yaml10
5 files changed, 35 insertions, 27 deletions
diff --git a/obnam.md b/obnam.md
index a06717a..a02aacb 100644
--- a/obnam.md
+++ b/obnam.md
@@ -925,11 +925,11 @@ not to the server.
The server has the following API for managing chunks:
-* `POST /chunks` &mdash; store a new chunk (and its metadata) on the
+* `POST /v1/chunks` &mdash; store a new chunk (and its metadata) on the
server, return its randomly chosen identifier
-* `GET /chunks/<ID>` &mdash; retrieve a chunk (and its metadata) from
+* `GET /v1/chunks/<ID>` &mdash; retrieve a chunk (and its metadata) from
the server, given a chunk identifier
-* `GET /chunks?label=xyzzy` &mdash; find chunks on the server whose
+* `GET /v1/chunks?label=xyzzy` &mdash; find chunks on the server whose
metadata has a specific value for a label.
HTTP status codes are used to indicate if a request succeeded or not,
@@ -1092,7 +1092,7 @@ storage of backed up data.
~~~scenario
given a working Obnam system
and a file data.dat containing some random data
-when I POST data.dat to /chunks, with chunk-meta: {"label":"abc"}
+when I POST data.dat to /v1/chunks, with chunk-meta: {"label":"abc"}
then HTTP status code is 201
and content-type is application/json
and the JSON body has a field chunk_id, henceforth ID
@@ -1102,7 +1102,7 @@ and server has 1 chunks
We must be able to retrieve it.
~~~scenario
-when I GET /chunks/<ID>
+when I GET /v1/chunks/<ID>
then HTTP status code is 200
and content-type is application/octet-stream
and chunk-meta is {"label":"abc"}
@@ -1112,7 +1112,7 @@ and the body matches file data.dat
We must also be able to find it based on metadata.
~~~scenario
-when I GET /chunks?label=abc
+when I GET /v1/chunks?label=abc
then HTTP status code is 200
and content-type is application/json
and the JSON body matches {"<ID>":{"label":"abc"}}
@@ -1122,13 +1122,13 @@ Finally, we must be able to delete it. After that, we must not be able
to retrieve it, or find it using metadata.
~~~scenario
-when I DELETE /chunks/<ID>
+when I DELETE /v1/chunks/<ID>
then HTTP status code is 200
-when I GET /chunks/<ID>
+when I GET /v1/chunks/<ID>
then HTTP status code is 404
-when I GET /chunks?label=abc
+when I GET /v1/chunks?label=abc
then HTTP status code is 200
and content-type is application/json
and the JSON body matches {}
@@ -1141,7 +1141,7 @@ not exist.
~~~scenario
given a working Obnam system
-when I try to GET /chunks/any.random.string
+when I try to GET /v1/chunks/any.random.string
then HTTP status code is 404
~~~
@@ -1151,7 +1151,7 @@ We must get an empty result if searching for chunks that don't exist.
~~~scenario
given a working Obnam system
-when I GET /chunks?label=abc
+when I GET /v1/chunks?label=abc
then HTTP status code is 200
and content-type is application/json
and the JSON body matches {}
@@ -1163,7 +1163,7 @@ We must get the right error when deleting a chunk that doesn't exist.
~~~scenario
given a working Obnam system
-when I try to DELETE /chunks/any.random.string
+when I try to DELETE /v1/chunks/any.random.string
then HTTP status code is 404
~~~
@@ -1178,7 +1178,7 @@ First, create a chunk.
~~~scenario
given a working Obnam system
and a file data.dat containing some random data
-when I POST data.dat to /chunks, with chunk-meta: {"label":"abc"}
+when I POST data.dat to /v1/chunks, with chunk-meta: {"label":"abc"}
then HTTP status code is 201
and content-type is application/json
and the JSON body has a field chunk_id, henceforth ID
@@ -1194,7 +1194,7 @@ given a running chunk server
Can we still find it by its metadata?
~~~scenario
-when I GET /chunks?label=abc
+when I GET /v1/chunks?label=abc
then HTTP status code is 200
and content-type is application/json
and the JSON body matches {"<ID>":{"label":"abc"}}
@@ -1203,7 +1203,7 @@ and the JSON body matches {"<ID>":{"label":"abc"}}
Can we still retrieve it by its identifier?
~~~scenario
-when I GET /chunks/<ID>
+when I GET /v1/chunks/<ID>
then HTTP status code is 200
and content-type is application/octet-stream
and chunk-meta is {"label":"abc"}
@@ -1220,14 +1220,14 @@ server more chatty.
~~~scenario
given a working Obnam system
and a file data1.dat containing some random data
-when I POST data1.dat to /chunks, with chunk-meta: {"label":"qwerty"}
+when I POST data1.dat to /v1/chunks, with chunk-meta: {"label":"qwerty"}
then the JSON body has a field chunk_id, henceforth ID
and chunk server's stderr doesn't contain "Obnam server starting up"
and chunk server's stderr doesn't contain "created chunk <ID>"
given a running chunk server with environment {"OBNAM_SERVER_LOG": "info"}
and a file data2.dat containing some random data
-when I POST data2.dat to /chunks, with chunk-meta: {"label":"xyz"}
+when I POST data2.dat to /v1/chunks, with chunk-meta: {"label":"xyz"}
then the JSON body has a field chunk_id, henceforth ID
and chunk server's stderr contains "Obnam server starting up"
and chunk server's stderr contains "created chunk <ID>"
diff --git a/src/bin/obnam-server.rs b/src/bin/obnam-server.rs
index 5be2cee..6cf4122 100644
--- a/src/bin/obnam-server.rs
+++ b/src/bin/obnam-server.rs
@@ -47,27 +47,35 @@ async fn main() -> anyhow::Result<()> {
debug!("Configuration: {:#?}", config);
let create = warp::post()
+ .and(warp::path("v1"))
.and(warp::path("chunks"))
+ .and(warp::path::end())
.and(store.clone())
.and(warp::header("chunk-meta"))
.and(warp::filters::body::bytes())
.and_then(create_chunk);
let fetch = warp::get()
+ .and(warp::path("v1"))
.and(warp::path("chunks"))
.and(warp::path::param())
+ .and(warp::path::end())
.and(store.clone())
.and_then(fetch_chunk);
let search = warp::get()
+ .and(warp::path("v1"))
.and(warp::path("chunks"))
+ .and(warp::path::end())
.and(warp::query::<HashMap<String, String>>())
.and(store.clone())
.and_then(search_chunks);
let delete = warp::delete()
+ .and(warp::path("v1"))
.and(warp::path("chunks"))
.and(warp::path::param())
+ .and(warp::path::end())
.and(store.clone())
.and_then(delete_chunk);
diff --git a/src/client.rs b/src/client.rs
index 5b13cb7..c5d66c1 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -131,7 +131,7 @@ impl BackupClient {
}
fn chunks_url(&self) -> String {
- format!("{}/chunks", self.base_url())
+ format!("{}/v1/chunks", self.base_url())
}
/// Does the server have a chunk?
diff --git a/subplot/server.py b/subplot/server.py
index de63836..1f4506f 100644
--- a/subplot/server.py
+++ b/subplot/server.py
@@ -53,7 +53,7 @@ def stop_chunk_server(ctx, env=None):
def post_file(ctx, filename=None, path=None, header=None, json=None):
- url = f"{ctx['server_url']}/chunks"
+ url = f"{ctx['server_url']}/v1/chunks"
headers = {header: json}
data = open(filename, "rb").read()
_request(ctx, requests.post, url, headers=headers, data=data)
@@ -65,12 +65,12 @@ def get_chunk_via_var(ctx, var=None):
def get_chunk_by_id(ctx, chunk_id=None):
- url = f"{ctx['server_url']}/chunks/{chunk_id}"
+ url = f"{ctx['server_url']}/v1/chunks/{chunk_id}"
_request(ctx, requests.get, url)
def find_chunks_with_label(ctx, sha=None):
- url = f"{ctx['server_url']}/chunks?label={sha}"
+ url = f"{ctx['server_url']}/v1/chunks?label={sha}"
_request(ctx, requests.get, url)
@@ -80,7 +80,7 @@ def delete_chunk_via_var(ctx, var=None):
def delete_chunk_by_id(ctx, chunk_id=None):
- url = f"{ctx['server_url']}/chunks/{chunk_id}"
+ url = f"{ctx['server_url']}/v1/chunks/{chunk_id}"
_request(ctx, requests.delete, url)
diff --git a/subplot/server.yaml b/subplot/server.yaml
index 7b7d461..ac45cac 100644
--- a/subplot/server.yaml
+++ b/subplot/server.yaml
@@ -21,28 +21,28 @@
python:
function: post_file
-- when: "I GET /chunks/<{var}>"
+- when: "I GET /v1/chunks/<{var}>"
impl:
python:
function: get_chunk_via_var
-- when: "I try to GET /chunks/{chunk_id}"
+- when: "I try to GET /v1/chunks/{chunk_id}"
impl:
python:
function: get_chunk_by_id
-- when: "I GET /chunks?label={sha}"
+- when: "I GET /v1/chunks?label={sha}"
regex: false
impl:
python:
function: find_chunks_with_label
-- when: "I DELETE /chunks/<{var}>"
+- when: "I DELETE /v1/chunks/<{var}>"
impl:
python:
function: delete_chunk_via_var
-- when: "I try to DELETE /chunks/{chunk_id}"
+- when: "I try to DELETE /v1/chunks/{chunk_id}"
impl:
python:
function: delete_chunk_by_id