Skip to content

Commit

Permalink
Use Cloudinary for images so that content can be uploaded to teclado.ocm
Browse files Browse the repository at this point in the history
  • Loading branch information
jslvtr committed Jul 12, 2023
1 parent 6736b77 commit bb89653
Show file tree
Hide file tree
Showing 14 changed files with 41 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ Start by [downloading Insomnia REST Client](https://insomnia.rest/).

Once you've opened it, create a Project. I would call it "REST APIs with Flask and Python".

![Creating the Project for this course](assets/creating-project.png)
![Creating the Project for this course](https://res.cloudinary.com/teclado/image/upload/v1689180715/courses/rest-apis-flask-python/creating-project_qsyxlg.png)

Then, create a new Request Collection. Call it "Stores REST API".

![Creating the Stores REST API Request Collection](assets/making-request-collection.png)
![Creating the Stores REST API Request Collection](https://res.cloudinary.com/teclado/image/upload/v1689180710/courses/rest-apis-flask-python/making-request-collection_lcthlv.png)

In the Request Collection, we can now add requests! Each request has a few parts:

Expand All @@ -46,19 +46,19 @@ Let's create our first request, `GET /store`.

Make a new request using the Insomnia interface. First, use the dropdown to start:

![How to make a request using the Insomnia interface](assets/making-request.png)
![How to make a request using the Insomnia interface](https://res.cloudinary.com/teclado/image/upload/v1689180711/courses/rest-apis-flask-python/making-request_hmiptl.png)

Then enter the request name. Leave the method as `GET`:

![Enter the request name and method](assets/set-request-name-and-method.png)
![Enter the request name and method](https://res.cloudinary.com/teclado/image/upload/v1689180712/courses/rest-apis-flask-python/set-request-name-and-method_bc6smy.png)

Once you're done, you will see your request in the collection:

![The request is shown in the collection](assets/before-setting-url.png)
![The request is shown in the collection](https://res.cloudinary.com/teclado/image/upload/v1689180711/courses/rest-apis-flask-python/before-setting-url_qjxvyr.png)

Next up, enter the URL for your request. Here we will be requesting the `/store` endpoint. Remember to include your Base URL as well:

![Entering the full URL for the request in Insomnia](assets/url-set.png)
![Entering the full URL for the request in Insomnia](https://res.cloudinary.com/teclado/image/upload/v1689180714/courses/rest-apis-flask-python/url-set_fgp9s9.png)

Once you're done, make sure that your Flask app is running! If it isn't, remember to activate your virtual environment first and then run the app:

Expand All @@ -75,6 +75,6 @@ If you get an error, read it carefully and make sure that no other Flask app is

Once your Flask app is running, you can hit "Send" on the Insomnia client, and you should see the JSON come back from your API!

![Making a request to our API using Insomnia](assets/after-pressing-send.png)
![Making a request to our API using Insomnia](https://res.cloudinary.com/teclado/image/upload/v1689180712/courses/rest-apis-flask-python/after-pressing-send_okjkjq.png)

If that worked and you can see your JSON, you're good to go! You've made your first API request. Now we can continue developing our REST API, remembering to always create new Requests in Insomnia and test our code as we go along!
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ I'm sure you have heard of the term "Virtual Machine". A virtual machine is an e

This diagram shows what happens in that case:

![Virtual Machine Diagram stack](./assets/vm.drawio.png)
![Virtual Machine Diagram stack](https://res.cloudinary.com/teclado/image/upload/v1689180716/courses/rest-apis-flask-python/vm.drawio_nlrxmx.png)

When you run a Virtual Machine, you can configure what hardware it has access to (e.g. 50% of the host's RAM, 2 CPU cores, etc).

Expand All @@ -18,7 +18,7 @@ Containers have their own storage and networking, but because they don't have to

This diagram shows how Linux containers run in a Linux host:

![Docker Diagram stack](./assets/docker-linux.drawio.png)
![Docker Diagram stack](https://res.cloudinary.com/teclado/image/upload/v1689180716/courses/rest-apis-flask-python/docker-linux.drawio_ebvff5.png)

Looks similar, but the `docker -> container` section is much more efficient than running a VM because it **uses the host's kernel** instead of running its own.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,6 @@ docker run -dp 5001:5000 rest-apis-flask-python

Try making requests using the URL `127.0.0.1:5000` with Insomnia REST Client or Postman, and you should see it working well!

![Insomnia REST Client successfully made a request to the API running in Docker](assets/running-app-docker.png)
![Insomnia REST Client successfully made a request to the API running in Docker](https://res.cloudinary.com/teclado/image/upload/v1689180719/courses/rest-apis-flask-python/running-app-docker_mkosjm.png)

[^1]: [Docker `EXPOSE` command (Official Documentation)](https://docs.docker.com/engine/reference/builder/#expose)
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,4 @@ Using this kind of volume mapping only makes sense _during development_. When yo

Just to recap, here are the two ways we've seen to run your Docker container:

![Diagram showing two ways of running a Docker container from a built image, with and without volume mapping](./assets/build-with-without-volume.png)
![Diagram showing two ways of running a Docker container from a built image, with and without volume mapping](https://res.cloudinary.com/teclado/image/upload/v1689180724/courses/rest-apis-flask-python/build-with-without-volume_a7mig8.png)
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ This means that tags will have:

Here's a diagram to illustrate what this looks like:

![ER database model showing relationships](./assets/db_model.drawio.png)
![ER database model showing relationships](https://res.cloudinary.com/teclado/image/upload/v1689180742/courses/rest-apis-flask-python/db_model.drawio_ilgupm.png)

## New API endpoints to be added

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/08_flask_jwt_extended/03_how_is_jwt_used/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Here is a diagram of the interaction between client and API to generate an acces

<div style={{maxWidth: '600px'}}>

![Diagram showing the flow between client and server to generate an access token](./assets/access-token-flow.drawio.png)
![Diagram showing the flow between client and server to generate an access token](https://res.cloudinary.com/teclado/image/upload/v1689180750/courses/rest-apis-flask-python/access-token-flow.drawio_gdr9oo.png)

</div>

Expand Down Expand Up @@ -56,7 +56,7 @@ Here is a rather long diagram depicting what happens:

<div style={{maxWidth: '600px'}}>

![Diagram showing flow of data when user wants to load their information but aren't logged in](./assets/my-info-flow.drawio.png)
![Diagram showing flow of data when user wants to load their information but aren't logged in](https://res.cloudinary.com/teclado/image/upload/v1689180750/courses/rest-apis-flask-python/my-info-flow.drawio_pzfjh7.png)

</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,40 @@ Up until now, we've been able to log in, get an access token, and then use that

Instead of passing the JWT in every request, you can access the `Headers` section and follow these steps. In the `Authorization` field, type `Bearer` add a space and then press `CTRL + SPACE` to get a contextual menu. Navigate to the `Response -> Body Attribute` field and select it, as shown in the screenshot below:

![Contextual menu with Generator Tag options](./assets/bearer_token.png)
![Contextual menu with Generator Tag options](https://res.cloudinary.com/teclado/image/upload/v1689180763/courses/rest-apis-flask-python/bearer_token_qk2jqi.png)

After you've selected it, you'll see an error that looks like this:

![Response error in the Authorization field](./assets/error.png)
![Response error in the Authorization field](https://res.cloudinary.com/teclado/image/upload/v1689180763/courses/rest-apis-flask-python/error_darkak.png)

If you click on the error, you'll see a modal window:

![Modal window with empty fields](./assets/modal.png)
![Modal window with empty fields](https://res.cloudinary.com/teclado/image/upload/v1689180763/courses/rest-apis-flask-python/modal_xutepw.png)

Inside of this window, you will first need to select a request that you want to get the data from. Click on `Select item` inside the `Request` field and choose the `POST /login` endpoint. After you've done that, go to the `Filter` field. In this field, we are telling Insomnia which part of the response we want to get from it. The prompt is started with the dollar sign `$` and then we can use the dot to access the attributes of the response. If we only type `$` or `$.`, we'll get a list of all the attributes of the response:

![Attributes recieved from request using a dollar sign](./assets/attributes.png)
![Attributes recieved from request using a dollar sign](https://res.cloudinary.com/teclado/image/upload/v1689180763/courses/rest-apis-flask-python/attributes_kxngsi.png)

In our case, we want to get the `access_token` attribute from the response, so we type `$.access_token`. If there was something else inside the `access_token` that you wanted to access like some value for example, you could do `$.access_token.value` and so on. After you've added the filter, you can set the `Trigger Behavior`. For example, you can set it to `When expired` and set time to 300 seconds. This means that the token will be refreshed every 5 minutes. The filled out window should look like this:

![Filled out modal window with attributes recieved from request using a dollar sign followed by .access_token](./assets/filled_out.png)
![Filled out modal window with attributes recieved from request using a dollar sign followed by .access_token](https://res.cloudinary.com/teclado/image/upload/v1689180763/courses/rest-apis-flask-python/filled_out_muzo2u.png)

You can now press `Done` and you'll see that the error is gone and that the `Authorization` field is filled out with the `Bearer` token:

![Filled out Authorization field with Bearer token](./assets/token.png)
![Filled out Authorization field with Bearer token](https://res.cloudinary.com/teclado/image/upload/v1689180763/courses/rest-apis-flask-python/token_txc8sb.png)

Since we use multiple protected endpoints, we would need to use the same method to get the `access_token` for every request. To tackle this problem, we can use [environment variables](https://support.insomnia.rest/article/13-environment-variables), as we did before for the `url` variable.

To do this, you need to create a new environment variable. Click on the `No Environment` button in the top left corner of the Insomnia window and then click on the `Manage Environments` button, you will see a base environment that looks like this:

![Base environment with url environment variable only](./assets/base_environment.png)
![Base environment with url environment variable only](https://res.cloudinary.com/teclado/image/upload/v1689180763/courses/rest-apis-flask-python/base_environment_cfyrab.png)

Add a new environment variable called `access_token`, and for its value you should follow the same process from above. As a quick reminder, you should press `CTRL + SPACE` to get the contextual menu and then select the `Response -> Body Attribute` field. Click on the error that will show up and fill out the modal window as we've done before. Make sure to wrap the `Response -> Body Attribute` with quotation marks, as shown in the screenshot. When the variable is created, your environment should look like this:

![Base environment with added access_token variable](./assets/environment.png)
![Base environment with added access_token variable](https://res.cloudinary.com/teclado/image/upload/v1689180763/courses/rest-apis-flask-python/environment_n8jfm9.png)

You will now be able to use this environment variable in all of the endpoints by simply writing `{{access_token}}` in the field that you want to use it in. Coming back to the first example, you can use the access token in the `Authorization` field by writing `Bearer {{access_token}}` and this will be the result:

![Bearer with access_token environment variable](./assets/result.png)
![Bearer with access_token environment variable](https://res.cloudinary.com/teclado/image/upload/v1689180763/courses/rest-apis-flask-python/result_krbno3.png)

If you try and make the request, you will see that it works just like before, without needing to copy and paste the access token.
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ Then you'll [connect your GitHub account](https://render.com/docs/github) if you

Select the repository that you created during this course:

![Render.com screenshot showing how to search for and select a repository to connect to from GitHub](./assets/render-github-connect.png)
![Render.com screenshot showing how to search for and select a repository to connect to from GitHub](https://res.cloudinary.com/teclado/image/upload/v1689180776/courses/rest-apis-flask-python/render-github-connect_jp6mip.png)

Then, give it a name and make sure the configuration is as follows:

![Render.com screenshot showing the web service configuration](./assets/render-service-config.png)
![Render.com screenshot showing the web service configuration](https://res.cloudinary.com/teclado/image/upload/v1689180776/courses/rest-apis-flask-python/render-service-config_poweeb.png)

- Make sure "Docker" is selected.
- Select a server location close to you. I'm near Frankfurt, but if you are in the US or Asia you might want to choose a different one so it's faster to connect to.
Expand All @@ -32,19 +32,19 @@ For now, hit "Create Web Service" and wait for it to deploy your code from GitHu

If you navigate to your Dashboard and then click through to your newly created service, you'll be able to see the service details. If it isn't already deploying, click on the "Manual Deploy" button on the top right to initiate a deploy of the latest commit:

![](./assets/deploy-latest-commit.png)
![](https://res.cloudinary.com/teclado/image/upload/v1689180775/courses/rest-apis-flask-python/deploy-latest-commit_k9as13.png)

Then you should start seeing logs appear detailing the deployment process!

![](./assets/render-deploy-screen.png)
![](https://res.cloudinary.com/teclado/image/upload/v1689180776/courses/rest-apis-flask-python/render-deploy-screen_lfx1uh.png)

While on the free plan, deployments are a bit slow. It has to build your image and run it! Give it a few minutes, until the deployment succeeds. You should see this:

![](./assets/render-deploy-finished.png)
![](https://res.cloudinary.com/teclado/image/upload/v1689180776/courses/rest-apis-flask-python/render-deploy-finished_lyiftz.png)

Now, you can access your service URL and try it out using Insomnia or Postman!

![](./assets/insomnia-test-prod.png)
![](https://res.cloudinary.com/teclado/image/upload/v1689180778/courses/rest-apis-flask-python/insomnia-test-prod_dlfe1d.png)

:::warning
Free services in Render.com shut down after inactivity for a few minutes. If you don't use your service for a few minutes, it will shut down and it will need to restart, which can take a minute! This is one of the limitations of their free plan.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ That's why I recommend using ElephantSQL for your free PostgreSQL needs. When yo

To get a free ElephantSQL PostgreSQL database, just go to their site, sign up, and then create a database in a region close to your Render.com server. Make sure to select the free tier.

![ElephantSQL screenshot showing plan configuration of Tiny Turtle (free) and name](./assets/select-plan-and-name-elephantsql.png)
![ElephantSQL screenshot showing plan configuration of Tiny Turtle (free) and name](https://res.cloudinary.com/teclado/image/upload/v1689180780/courses/rest-apis-flask-python/select-plan-and-name-elephantsql_sx3v2e.png)

Once you've got this, you should be able to see the Database URL:

![ElephantSQL screenshot showing that a copy icon beside the Database URL can be clicked to copy it](./assets/copy-elephantsql-url.png)
![ElephantSQL screenshot showing that a copy icon beside the Database URL can be clicked to copy it](https://res.cloudinary.com/teclado/image/upload/v1689180780/courses/rest-apis-flask-python/copy-elephantsql-url_ydr90k.png)

Copy this, as you'll need it in the next lecture!
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,11 @@ Now that our Flask app is using environment variables, all we have to do is add

To add environment variables in Render.com, go to the service settings and then on the left you'll see "Environment":

![Render.com screenshot showing the button to add a environment variables](./assets/render-add-env-var.png)
![Render.com screenshot showing the button to add a environment variables](https://res.cloudinary.com/teclado/image/upload/v1689180783/courses/rest-apis-flask-python/render-add-env-var_lodpee.png)

Click on "Add Environment Variable", and there put `DATABASE_URL` as the key, and your ElephantSQL Database URL as the value:

![Render.com screenshot showing DATABASE_URL added with a pixelated value](./assets/render-database-url-env-var.png)
![Render.com screenshot showing DATABASE_URL added with a pixelated value](https://res.cloudinary.com/teclado/image/upload/v1689180784/courses/rest-apis-flask-python/render-database-url-env-var_wrxgjl.png)

:::warning
Again, make sure to use `postgresql://...` here.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ You will get an email to confirm. Click the button that you see in that email to

Next up, grab your API key. You can find it by clicking on this button (my domain and API key are blurred in this screenshot):

![Click the 'Select' button to reveal your Mailgun API key](./assets/mailgun-api-key.png)
![Click the 'Select' button to reveal your Mailgun API key](https://res.cloudinary.com/teclado/image/upload/v1689180789/courses/rest-apis-flask-python/mailgun-api-key_mc8bjz.png)

## Sending emails with Mailgun

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ctslug: what-is-a-task-queue

A queue is a data structure to which you can add and remove data, but a key aspect of it is that when you want to remove a piece of data from it, the piece of data removed is the first piece of data that was added.

![New elements are added at the end, called pushing, and removed from the start, called popping, of a queue](./assets/queues.drawio.png)
![New elements are added at the end, called pushing, and removed from the start, called popping, of a queue](https://res.cloudinary.com/teclado/image/upload/v1689180793/courses/rest-apis-flask-python/queues.drawio_yqgtvg.png)

This is identical to how people queuing works. The first person to arrive at the queue (i.e. the first in line), is the first person removed from the queue when they reach the ticket counter.

Expand All @@ -32,6 +32,6 @@ Later on if we want, we can upgrade to one of the paid plans.

To be able to add tasks to the queue from your dev environment, make sure to [allow external connections](https://render.com/docs/redis#connecting-to-your-redis-from-outside-render) in your Redis database configuration.

![Screenshot showing 0.0.0.0/0 as an allowed IP address when connecting to our Render Redis database](./assets/render-redis-allowing-outside.png)
![Screenshot showing 0.0.0.0/0 as an allowed IP address when connecting to our Render Redis database](https://res.cloudinary.com/teclado/image/upload/v1689180794/courses/rest-apis-flask-python/render-redis-allowing-outside_tkxsls.png)

You should get a Redis URL that looks like this: `rediss://red-ct8aen0hkl10:[email protected]:6379`. Save it, for we'll need it in the next lecture!
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ Now remember to restart your app _and_ your background worker, then try to regis

You should get the HTML email delivered!

![HTML email with button to go to the API documentation](./assets/html-email.png)
![HTML email with button to go to the API documentation](https://res.cloudinary.com/teclado/image/upload/v1689180798/courses/rest-apis-flask-python/html-email_dyxasi.png)

:::info Spam or junk?
If your emails are going to spam, it's likely because you're using the sandbox domain. When you use an actual domain, you have to go through various [domain verification steps](https://help.mailgun.com/hc/en-us/articles/360011702394-Why-Do-My-Emails-Go-to-Spam-) which reduce the likelihood of your emails ending up in spam.
Expand Down
Loading

1 comment on commit bb89653

@vercel
Copy link

@vercel vercel bot commented on bb89653 Jul 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.