Goal
The goal for today is to start implementation of the Obnam server HTTP API. If all goes well, after this development session I can run the server, and use authenticated requests to upload chunks, download chunks, delete chunks, and search for chunks based on label.
Plan
I'll use the
axumcrate for the HTTP API. I've played with it a little bit, and it's pretty convenient to use.I will keep the client and server as separate programs. There's no need to have them be the same one. I may later split the
obnamcrate, but for now everything can live in one crate.The server will have its own configuration file. It can default to
~/.config/obnam/server.yamlto be separate from the client one. The server configuration contains, at minimum, the PASETO key pair for signing tokens, or the location where it is.The server admin will be able to create an API token for a client using something like
obnam-server token. For now, the clients are not distinguished except by token. Later on, clients will need their own IDs, I assume, but for now I'll only deal with tokens. When clients get IDs, there will need to an entire subsystem to manage clients, and ideally provide a web application or other way for users to sign up and have accounts. That's going to be a lot of work, and it's the kind of work I'm not currently interested in.Maybe by then someone else will want to contribute that to Obnam?
The HTTP API will be like this:
PUT /chunk?id=ID&label=LABEL- create a new chunk, unless a chunk with that ID already exists
- both
idandlabelare required - body is the blob with chunk content
- requires an
obnam_createclaim
GET /chunk/<ID>- fetch a chunk by id
- response body is the blob with chunk content
- requires an
obnam_getclaim
GET /chunk?label=LABEL- find chunks with a given label
- response is a JSON list of chunk identifiers
- requires an
obnam_findclaim
DELETE /chunk/<ID>- remove a chunk
- requires an
obnam_deleteclaim
The usual HTTP response codes are used, as defined in https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status. There is also https://http.cat/ but I find the textual one more useful.
I will test the server using
curl, but will also change the Obnam client to provide commands for this. Something likeobnam api create --id=ID --label=LABEL FILENAME, but I don't know if I'll have time for that today. It'll be necessary for having a test suite for the server, though.
Notes
First step is to set up scaffolding for the server program. This is straightforward, I can just model it on the client. At first I will only implement the
versioncommand.I'm going to have to figure out what to use for logging in the server. The
env_loggeris fine for many programs, but the server will be multi-threaded and probablytracingwill work better. Might want to use that for the client too, for that matter. But I'll start withenv_loggerfor now.I added the scaffolding, with a
versionsubcommand. As a user I like having both a--versionoption and aversionsubcommand. I likegit-testamentfor more precise version numbers.Next, a server configuration file. Apparently
pasetorsdoesn't supportserdefor the key types it has so I'll need to handle that myself. A little bit of glue code is fine. I'll store the public and secret keys as byte vectors. I'll also useclingwrapto read the configuration file.Setting this scaffolding up for every new program is not as much work as it used to be, before I wrote
clingwrap, but it's still more than I'd like. I'll need to think about how to streamline this more. But not today.One thing I notice right now is that if I want to keep server stuff separate from client stuff, and I do, it gets tricky to put everything into
src/bin/obnam-server.rs, as that grows pretty large. I should split earlier theobnamcrate into a workspace with crates for the client, the server, and shared code. But maybe not right now.My next step will be to add the key pair for token signing key pair to the server configuration file. I made a prototype repository for experimenting with
pasetors, and it looks like I can I used that code almost as-is. However, this becomes a bit messy if I don't split theobnamcrate into a workspace, so I'll actually do that first.I'll have a workspace with members. I've not used workspaces in my own projects before, so I get to learn something. In the Subplot project the workspace has a root package. In the Radicle
heartwoodproject we use a workspace without a root package.It doesn't seem to really matter which approach one uses. Intuitively the lack of a root package seems tidier to me, so I'll go with that.
I'll have crates
obnamandobnam-server. If they share code, I'll addobnamlibor something. I don't want to put crates in acratesdirectory as there's at most three of them. I start by adding theobnamcrate, then extract what I did for the server intoobnam-server.The client and server will have separate version numbers. I specifically do not want them to match. It is an important goal for Obnam that they do not need to match.
As long as I have a single program for each crate, I can just put it
main.rsI guess. I'll do that for the server now, and maybe change the client later.OK, that was fun. Now I'll refactor the server code so that there's a library. Moved the server config there.
Next, add a module for access tokens based on the code I prototyped last time.
Added token signing key pair to server config.
Next I'll need to add commands to the server to generate a key pair and to create a token. But I ran out of time for today, so I'll continue from here next time.
Comments?
If you have feedback on this, please use the following fediverse thread: https://toot.liw.fi/@liw/115994612673569524.