Redirect all
I am working on a Telegram bot, and while I can say that the API is nice to work with, there are a couple of shortcomings. In particular there is limited support for links in messages
as you are essentially limited to https
and tg
schemes. I couldn’t find a list of supported
schemes, official or not.
An obvious solution is sharing https
links than redirect to the actual URI. I could use a url shortening service, since most of them support arbitrary schemes, but that means either
creating the links by hand or registering for the APIs, neither of which I wanted to do.
“But wait”, I thought, “I have web server running nginx, (this very blog) so what about taking advantage of that?”
Turns out that using nginx does actually work, although the final solution is different from what I had in mind initially.
The first idea was to have something very human readable by embedding the uri in the request path,
for example being able to point to ftp://example.com
with an url like https://example.com/ftp/example.com
.
Unfortunately, while this look very nice, in practice doesn’t work well.
First of all, while most scheme use two slashes after the double colon, other require only one or none at all.
For example ftp://example.com
has two, magnet:?xt=urn:sha1:hashoffile&dn=display_name
has none. This means that either we keep track of all the
schemes we want to support, or we have to use something like https://example.com/ftp///example.com
, which is not only ugly, but bug prone, as plenty of
software (and nginx in particular) will consider those three slashes the same as one.
Also, without encoding,some things are just not possible. For example anchors are not sent to the webserver, so an url containing a #
would
need to be escaped to work properly (and not even that, because nginx insists on merging slashes even when encoded).
So I needed something that would always be passed to web server (i.e. not be confused as the hash part of the url) and not altered by nginx; so
the final, working and in retrospect obvious solution is to pass it as a query parameter. https://example.com/fw?ftp://example.com
does the trick.
This can be done with a simple nginx rule:
location ~ /fw {
return 301 $args;
}
This is surprisingly simple not only as an implementation, but also from the user point of view: in pratice it works with most user agents without any kind of encoding.
You can try on my shortener, at least until it gets abused :-), https://shr10.it/fw?https://www.youtube.com/watch?v=dQw4w9WgXcQ should redirect you to the best video on youtube, or you can try https://shr10.it/fw?telnet://freechess.org if you feel like playing chess.