2019-08-25 11:54:33 +02:00
|
|
|
# RushLink
|
2019-08-24 23:14:16 +02:00
|
|
|
|
2019-08-25 11:54:33 +02:00
|
|
|
A URL shortener and (maybe) a pastebin server for our #ru community.
|
|
|
|
|
|
|
|
## Libraries
|
|
|
|
|
|
|
|
Use standard-Go-libraries if the job can be done with those. As of now, these
|
|
|
|
are the exceptions:
|
|
|
|
|
|
|
|
- `github.com/gorilla/mux` provides useful stuff for routing requests.
|
|
|
|
- `github.com/gorilla/sessions` for session management.
|
|
|
|
- `go.etcd.io/bbolt` is our database driver.
|
|
|
|
- `github.com/joomcode/errorx` provides a [`Decorate`] function. This dependency
|
|
|
|
will be dropped when [`errors.Wrap`] is properly supported.
|
|
|
|
|
|
|
|
[`Decorate`]: https://godoc.org/github.com/joomcode/errorx#Decorate
|
|
|
|
[`errors.Wrap`]: https://godoc.org/github.com/pkg/errors#Wrap
|
|
|
|
|
|
|
|
## Database
|
|
|
|
|
|
|
|
We will be using [`go.etcd.io/bbolt`]. This file should be the *only* file
|
|
|
|
apart from our monolithic binary. All settings and keys should go in here.
|
|
|
|
Any read-only data resides in the binary file (possibly compressed).
|
|
|
|
|
|
|
|
[`go.etcd.io/bbolt`]: `go.etcd.io/bbolt`
|
|
|
|
|
|
|
|
## Namespacing
|
|
|
|
|
|
|
|
All shortened URLs exist as a key on the root of the webserver, i.e. `/xd42`.
|
|
|
|
That means that we have to separate every other page with some kind of
|
|
|
|
namespace. Ideas:
|
|
|
|
|
|
|
|
- `/z/` reserved for flat pages.
|
|
|
|
- `/p/` reserved for "pastes".
|
|
|
|
- `/u/` reserved for "users".
|
|
|
|
- `/f/` reserved for "files".
|
|
|
|
- `/z/static/` reserved for "static files".
|
|
|
|
|
|
|
|
## Shorten keys and collisions
|
|
|
|
|
|
|
|
For the first version of the keys, we will use 3 bytes encoded as base64url,
|
|
|
|
as described in [RFC4648, par. 5]. To allow for truncate-resistant upgrading
|
|
|
|
of the URL key format, the first bit is set to `0`. That means the first base64
|
|
|
|
character will always be in `[A-Za-f]`.
|
|
|
|
|
2019-08-25 11:46:30 +02:00
|
|
|
This domain contains `8388608` values. If the service is somewhat used, we will
|
2019-08-25 11:54:33 +02:00
|
|
|
get collisions early when we generate those keys at random. Instead, we will
|
|
|
|
use format-preserving-encryption to construct a counter that visits every value
|
|
|
|
in an unpredictable order. Daan will fix this.
|
|
|
|
|
|
|
|
[RFC4648, par. 5]: https://tools.ietf.org/html/rfc4648#section-5
|
|
|
|
|
|
|
|
## UI design
|
|
|
|
|
|
|
|
As is tradition in a lot of URL-shortener/pastebin-like services, we will put
|
|
|
|
everything in a single `<pre>` tag, and if possible, just serve `text/plain`.
|
|
|
|
A good example is <https://0x0.st>.
|
|
|
|
|
|
|
|
The reason we would use `text/html` instead of `text/plain` is basically
|
|
|
|
form submissions and JavaScript. Our main API should be cURL, but it would be
|
|
|
|
useful if users could also use the website and/or drag-and-drop files and URLs.
|
|
|
|
|
|
|
|
On the other hand, using `text/plain` saves us *so much effort*, because we
|
|
|
|
don't have to do any HTML/CSS/JavaScript. We have native terminal support, etc.
|
|
|
|
|
|
|
|
The best thing would probably to do both, and correctly listen to the `Accept`
|
|
|
|
header that the client sends. We can still wrap the plain-text page in a single
|
|
|
|
`<pre>` to keep it easy for ourselves.
|
|
|
|
|
|
|
|
## Retention
|
|
|
|
|
|
|
|
- If we can, we don't want to have user accounts. We store the sessions
|
|
|
|
forever, and store a user's data in there, without having to collect personal
|
|
|
|
data in any way.
|
|
|
|
- URL-shortening links will be retained for always, unless the submitter
|
|
|
|
revokes it, in which case it will be replaced by a `410 Gone` page*.
|
|
|
|
- The probles of pastes are not solved. This is an unsolved problem*.
|
|
|
|
|
|
|
|
* In any case, we going to comply with all European laws and reasonable
|
|
|
|
requests for deletion.
|
|
|
|
|
|
|
|
## Privacy
|
|
|
|
|
|
|
|
We will try as hard as possible to not store any data about our users, and will
|
|
|
|
only provide any data when we have the legal obligation to do so.
|