Fix embarrasing typo in app name & add docs for CLI
Add file-based store
Fix tests 😬
A slightly over-engineered URL shortener written in Go.
This project uses go mod
, so you'll have to make sure you've got EXPORT GO111MODULE=ON
defined in your shell or ~/.bashrc
.
make install
shortener
is the central domain. Most of the other packages rely on either the shortener
interface or URL
/ ShortCode
types. I tried to make this vaguely hexagonal (in other words, these central business rules don't rely on any other packages & connect to other packages via interfaces).
app
contains a concrete implementation of the shortener
interface. It connects to the hasher
and stores
interfaces.
stores
are where the persistance layer lives. As there's a stores
interface, you can easily create new layers and actually create a useful database backend. I've only implemented an in-memory cache as it was easiest to get working.
hasher
contains a way to generate random codes from the input URL. At the moment, it just hashes the string, but if you wanted you coudl change the algorithm. I was thinking you may also want to change the interface to allow a store
to be passed in... so that you could check whether the url already exists in the database if you were to use a different algorithm.
There are currently two main ways to run the app:
web
package)cli
package')
These both use the same shortener
interface, so there is no duplication of buisness logic. Almost all of the code in the web
and cli
packages just deals with the specifics of their interfaces (eg. accessing data and returning error messages or results).$ make run
$ # In another terminal:
$ curl -X POST -H "Content-Type: application/json" \
-d '{"URL": "https://example.com/foo"}' \
localhost:8080/shorten
# => {"success":true,"error":"","redirectURL":"localhost:8080/Ti0-MV4cifgD"}
$ curl localhost:8080/Ti0-MV4cifgD
# => <a href="https://example.com/foo">Moved Permanently</a>.
go install
$ url-shortener-golang -shorten https://example.com/yolo
# => Successfully shortened https://example.com/yolo to LpnX-1cqUSsL
$ url-shortener-golang -retrieve LpnX-1cqUSsL
# =>Successfully retrieved https://example.com/yolo from LpnX-1cqUSsL
# => ***OPENS BROWSER & OPENS https://example.com/yolo***
We've got a pretty minimal makefile
$ go run main.go -help
shortener
interface; I reckon that cli
and web
should rely on shortener.Shortener
rather than app.URLShortener
(the actual interface, rather than just an implementation of it).
Having said that, I'm unconvinced that we actually do need an interface here. If we're trying to keep things simple (as we should be), perhaps I should just remove the pointless shortener.Shortener
interface alltogether as we're unlikely to make different implementations of the interface. Something to think about.shortener
/ app
distinction is perhaps a bit vague. Maybe I should totally remove the shortener
interface and just move URL
/ ShortCode
to a generic models
package??Store
one).hasher
is a good name. Maybe tokenisation
would be better?➜ url-shortener-golang -help
Usage of ./url-shortener:
-redirect
should we redirect you? (default true)
-retrieve string
submit a code to retrieve URL from
-server
start server
-shorten string
submit a URL To shorten & store