`curl` your landing page
Key takeaways
- Streamline CLI installations with
curl https://your-domain.com | sh
- Try it out:
curl https://mootoday.com | sh
- Serve HTML for browsers, a shell script for
curl
requests
Source code
You can find the source code related to this post in the mootoday/www-mootoday-com
GitHub repository. In particular, look for the handleCurl
function in src/hooks.server.ts
.
CLI distributions
If your project provides a CLI, you have near infinite options to distribute that CLI. Each has its pros and cons and each requires you to maintain and regularly test the various distribution channels you support.
Distribute from your own domain
One alternative to Homebrew, apt-get, NPM, you name it, is to provide an installation shell script on your own domain and let people install it with:
curl https://your-domain.com | sh
To see what this looks like in action, try the following command:
curl https://mootoday.com | sh
So… did you execute the above command 😰? You didn’t, right? If you did, no harm was done since I’m a kind person and as of this writing, my domain hasn’t been hacked.
⛔️ Never, and by that I mean absolutely never ever in your lifetime, should you download a random file with
curl
and blindly pipe it intosh
.
Needless to say there could be major security implications by downloading and running random shell scripts on your computer. See the “Examples” below for a few companies that provide their CLIs through shell scripts. Use your best judgement as to when to trust a company.
If you want to check what a script is about (which is what I do before I execute any curl ... | sh
command):
curl https://mootoday.com | cat
Voilà, this prints the content of that shell script so you can verify its content before you run it.
How does it work?
You may wonder how this works – well given you’ve read this far, you most definitely want to know how it works 🙂.
The key to this solution is what’s called a User-Agent
HTTP request header (MDN docs).
In short, it’s a string that tells the web server what kind of application sent the request. For example, your browser’s User-Agent
is:
false
When someone uses curl https://mootoday.com
, the User-Agent
is something like this:
curl/8.1.2
Knowing that, all we need to do is tell the web server to send either a HTML response when a browser sends a request, or send a shell script response when curl
sends a request.
A SvelteKit hook does the work
In SvelteKit, we can handle that in the src/hooks.server.js|ts
file.
import type { Handle } from '@sveltejs/kit';
import { sequence } from '@sveltejs/kit/hooks';
const handleCurl = (async ({ event, resolve }) => {
if (
event.url.pathname === "/" &&
event.request.headers.get("user-agent")?.startsWith("curl")
) {
const shellScript = import.meta.glob("../static/mootoday.sh", { as: "raw" });
const shellScriptContent = await shellScript["../static/mootoday.sh"]();
return new Response(shellScriptContent, {
status: 200,
});
}
return await resolve(event);
}) satisfies Handle;
export const handle = sequence(handleCurl);
That’s all there is to it.
Example
One example where an actual CLI (as opposed to my demo shell script) is distributed as described in this post is:
curl https://goldsky.com | sh
It’s where I implemented this approach and if you want crypto data live-streamed, Goldsky is how you do it.
👋