Skip to content

Commit

Permalink
Add proxy middleware (#33)
Browse files Browse the repository at this point in the history
* added proxy middlware

* Make a better fix with env vars and CORS headers

* Update writeup with new .env files

* Uninstall `http-proxy-middleware`

---------

Co-authored-by: Navid Boloorian <[email protected]>
  • Loading branch information
wllmwu and navidboloorian authored Nov 4, 2023
1 parent 2b84e5d commit 9d3ca9f
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 13 deletions.
20 changes: 15 additions & 5 deletions backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,36 @@

import "dotenv/config";
import express, { NextFunction, Request, Response } from "express";
import cors from "cors";
import { isHttpError } from "http-errors";
import taskRoutes from "src/routes/task";

const app = express();

// initializes express to accept json in the request/response body
// initializes Express to accept JSON in the request/response body
app.use(express.json());

// sets the "Access-Control-Allow-Origin" header on all responses to allow
// requests from the frontend, which has a different origin - see the following
// pages for more info:
// https://expressjs.com/en/resources/middleware/cors.html
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
app.use(
cors({
origin: process.env.FRONTEND_ORIGIN,
}),
);

app.use("/api/task", taskRoutes);

/**
* Error handler; all errors thrown by server are handled here.
* Explicit typings required here because TypeScript cannot infer the argument types.
*
* An eslint-disable is being used below because the "next" argument is never used. However,
* it is still required for express to recognize it as an error handler. For this reason, I've
* it is still required for Express to recognize it as an error handler. For this reason, I've
* disabled the eslint error. This should be used sparingly and only in situations where the lint
* error cannot be fixed in another way. Alternatively, the variable name can be prefixed with an
* underscore (i.e. _next). Use underscores for variables that are unused but are still required.
* In this case, eslint-disable is used for educational purposes.
* error cannot be fixed in another way.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
app.use((error: unknown, req: Request, res: Response, next: NextFunction) => {
Expand Down
1 change: 0 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"name": "frontend",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:3001",
"type": "module",
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
Expand Down
19 changes: 13 additions & 6 deletions frontend/src/api/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
*/
type Method = "GET" | "POST" | "PUT";

/**
* The first part of the backend API URL, which we will automatically prepend to
* every request. This means in the rest of our code, we can write "/api/foo"
* instead of "http://localhost:3001/api/foo".
*/
const API_BASE_URL = process.env.REACT_APP_API_BASE_URL;

/**
* A wrapper around the built-in `fetch()` function that abstracts away some of
* the low-level details so we can focus on the important parts of each request.
Expand Down Expand Up @@ -70,21 +77,21 @@ async function assertOk(response: Response): Promise<void> {
}

/**
* Sends a GET request to the provided URL.
* Sends a GET request to the provided API URL.
*
* @param url The URL to request
* @param headers The headers of the request (optional)
* @returns The Response object returned by `fetch()`
*/
export async function get(url: string, headers: Record<string, string> = {}): Promise<Response> {
// GET requests do not have a body
const response = await fetchRequest("GET", url, undefined, headers);
const response = await fetchRequest("GET", API_BASE_URL + url, undefined, headers);
assertOk(response);
return response;
}

/**
* Sends a POST request to the provided URL.
* Sends a POST request to the provided API URL.
*
* @param url The URL to request
* @param body The body of the request, or undefined if there is none
Expand All @@ -96,13 +103,13 @@ export async function post(
body: unknown,
headers: Record<string, string> = {},
): Promise<Response> {
const response = await fetchRequest("POST", url, body, headers);
const response = await fetchRequest("POST", API_BASE_URL + url, body, headers);
assertOk(response);
return response;
}

/**
* Sends a PUT request to the provided URL.
* Sends a PUT request to the provided API URL.
*
* @param url The URL to request
* @param body The body of the request, or undefined if there is none
Expand All @@ -114,7 +121,7 @@ export async function put(
body: unknown,
headers: Record<string, string> = {},
): Promise<Response> {
const response = await fetchRequest("GET", url, body, headers);
const response = await fetchRequest("PUT", API_BASE_URL + url, body, headers);
assertOk(response);
return response;
}
Expand Down
7 changes: 6 additions & 1 deletion writeup/part-0/0-2-Clone.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,15 @@ You should now have a copy of all the starter code in the folder you selected.
We're almost ready to run the project for the first time! Before we can do that, we just need to add some environment variables required by the code.
1. Open the repo in VS Code (File > Open Folder, then select the root folder of the repo). In the `backend` folder, create a new file named `.env`.
2. Paste the following into the .env file:
2. Paste the following into the `.env` file:
```
PORT=3001
MONGODB_URI="mongodb://127.0.0.1:27017/todoList"
FRONTEND_ORIGIN="http://localhost:3000"
```
3. Create another `.env` in the `frontend` folder:
```
REACT_APP_API_BASE_URL="http://localhost:3001"
```
<details>
Expand Down

0 comments on commit 9d3ca9f

Please sign in to comment.