Authentication from cli tools can be a bit of a bear, and I have to look it up every time. This is my reference guide for future me to remember how to easily do it.
I set up a fastapi server running on port 8000, it uses a basic auth with
waylonwalker as the username and asdf as the password. The server follows
along with what comes out of the docs. I have it setup to take basic auth,
form username and password, or a bearer token for authentication.
curl #
The og of command line url tools.
# basic auth
curl -u 'waylonwalker:asdf' -X POST localhost:8000/token
# basic auth with password prompt
curl -u 'waylonwalker' -X POST localhost:8000/token
# token
curl -H 'Authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ3YXlsb253YWxrZXIiLCJleHAiOjE3MDI5NTI2MDJ9.GeYNt7DNal6LTiPoavJnqypaMt4vYeriXdq5lqu1ILg' -X POST localhost:8000/token
wget #
My go to if I want the result to go into a file.
# basic auth
wget -q -O - --auth-no-challenge --http-user=waylonwalker --http-password=asdf --post-data '' localhost:8000/token
# token
wget -q -O - --header="Authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ3YXlsb253YWxrZXIiLCJleHAiOjE3MDI5NTI2MDJ9.GeYNt7DNal6LTiPoavJnqypaMt4vYeriXdq5lqu1ILg" -O - --post-data '' localhost:8000/token
httpx #
An http client written in python, primarilty used with the python api, but has a nice cli.
# install
python3 -m pip install httpx
# basic auth
httpx -m POST --auth waylonwalker asdf http://localhost:8000/token
# basic auth with password prompt
httpx -m POST --auth waylonwalker - http://localhost:8000/token
# token
httpx -m POST --headers="Authorization" "bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ3YXlsb253YWxrZXIiLCJleHAiOjE3MDI5NTI2MDJ9.GeYNt7DNal6LTiPoavJnqypaMt4vYeriXdq5lqu1ILg" http://localhost:8000/token
httpie #
A modern http client written in python.
# install
python3 -m pip install httpie
# basic auth
http POST localhost:8000/token -a waylonwalker:asdf
# basic auth with password prompt
http POST localhost:8000/token -a waylonwalker
# token
http POST localhost:8000/token -A bearer -a eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ3YXlsb253YWxrZXIiLCJleHAiOjE3MDI5NTI2MDJ9.GeYNt7DNal6LTiPoavJnqypaMt4vYeriXdq5lqu1ILg
httpie with plugin #
# install
python3 -m pip install httpie-credential-store
# usage
http POST localhost:8000/token -A creds
httpie prompt #
http-prompt comes from the httpie org, and has an interactive cli interface
into apis. You can even specify a spec file to autocomplete on api methods.
http-prompt localhost:8000 --auth waylonwalker:asdf --spec openapi.json
I am working on fokais.com’s signup page, and I want to hide the form input during an htmx request. I was seeing some issues where I was able to prevent spamming the submit button, but was still able to get one extra hit on it.
It also felt like nothing was happening while sending the email to the user for verification. Now I get the form to disappear and a spinner to show during the request.
html">HTML #
Let’s start off with the form. It uses htmx to submit a post request to the
post_request route. Note that there is a spinner in the post_request with the
htmx-indicator class.
The intent is to hide the spinner until the request is running, and hide all of the form input during the request.
<form
id="signup-form"
hx-swap-oob="outerHTML"
class="m-4 mx-auto mb-6 flex w-80 flex-col rounded-lg b p-4 shadow-xlc shadow-cyan-500/10"
method="POST"
action="{{ url_for('post_signup') }}"
hx-post="{{ url_for('post_signup') }}"
>
<!--markata-attribution-->
<input
class="mx-8 mt-6 mb-4 border border-black bg-zinc-900 p-1 text-center focus:bg-zinc-800"
<!--markata-attribution-->
type="text"
<!--markata-attribution-->
value="{{ full_name }}"
<!--markata-attribution-->
name="full_name"
<!--markata-attribution-->
placeholder="Full Name"
/>
<!--markata-attribution-->
{% if full_name_error %}
<!--markata-attribution-->
<label class="-mt-6 mb-6 mx-8 text-red-500 p-1 text-center">
<!--markata-attribution-->
{{ full_name_error }}
<!--markata-attribution-->
</label>
<!--markata-attribution-->
{% endif %}
<!--markata-attribution-->
<input
class="mx-8 mb-4 border border-black bg-zinc-900 p-1 text-center focus:bg-zinc-800"
<!--markata-attribution-->
type="text"
<!--markata-attribution-->
value="{{ username }}"
<!--markata-attribution-->
name="username"
<!--markata-attribution-->
placeholder="username"
/>
<!--markata-attribution-->
{% if username_error %}
<!--markata-attribution-->
<label class="-mt-6 mb-6 mx-8 text-red-500 p-1 text-center">
<!--markata-attribution-->
{{ username_error }}
<!--markata-attribution-->
</label>
<!--markata-attribution-->
{% endif %}
<!--markata-attribution-->
<input
class="mx-8 mb-4 border border-black bg-zinc-900 p-1 text-center focus:bg-zinc-800"
<!--markata-attribution-->
type="email"
<!--markata-attribution-->
name="email"
<!--markata-attribution-->
value="{{ email }}"
<!--markata-attribution-->
placeholder="email"
/>
<!--markata-attribution-->
{% if email_error %}
<!--markata-attribution-->
<label class="-mt-6 mb-6 mx-8 text-red-500 p-1 text-center">
<!--markata-attribution-->
{{ email_error }}
<!--markata-attribution-->
</label>
<!--markata-attribution-->
{% endif %}
<!--markata-attribution-->
<input
class="mx-auto w-32 mb-4 border border-black bg-purple-900 p-1 text-center focus:bg-zinc-800"
<!--markata-attribution-->
type="submit"
<!--markata-attribution-->
value="sign up"
/>
<!--markata-attribution-->
<div role="status" class="mx-auto htmx-indicator">
<!--markata-attribution-->
<svg
<!--markata-attribution-->
class="mx-auto animate-spin h-5 w-5 text-white"
<!--markata-attribution-->
xmlns="https://www.w3.org/2000/svg"
<!--markata-attribution-->
fill="none"
<!--markata-attribution-->
viewBox="0 0 24 24"
>
<!--markata-attribution-->
<circle
<!--markata-attribution-->
class="opacity-25"
<!--markata-attribution-->
cx="12"
<!--markata-attribution-->
cy="12"
<!--markata-attribution-->
r="10"
<!--markata-attribution-->
stroke="currentColor"
<!--markata-attribution-->
stroke-width="4"
></circle>
<!--markata-attribution-->
<path
<!--markata-attribution-->
class="opacity-75"
<!--markata-attribution-->
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
<!--markata-attribution-->
</svg>
<!--markata-attribution-->
<p>Signing up...</p>
<!--markata-attribution-->
</div>
<!--markata-attribution-->
</form>
Yes this is styled using tailwindcss.
https://waylonwalker.com/still-loving-tailwind/
CSS #
Let’s take a look at how we achieve switching between only spinner an only form inputs using css.
.htmx-indicator {
@apply hidden;
opacity: 0;
transition: opacity 500ms ease-in;
}
.htmx-request button,
.htmx-request input[type="submit"],
.htmx-request input,
.htmx-request label {
@apply hidden;
}
.htmx-request .htmx-indicator {
opacity: 1;
@apply block;
}
.htmx-request.htmx-indicator {
opacity: 1;
@apply block;
}
Final Result #
Here is the final result of me signing up for a new account in fokais.