-
Notifications
You must be signed in to change notification settings - Fork 69
A request journey
This document's goal is to help you understand the inner workings of the codebase by explaining what happens when a request is sent to https://c0d3.com.
Please start with the c0d3.com
request, it is the most complete and has the most details. All subsequent request journeys are short high level descriptions
What happens when you type https://c0d3.com
into your browser url bar and hit enter?
- When you type https://c0d3.com/ (notice how
www
is not in the url) in your browser and hit enter, DNS resolution will resolve to our Digital Ocean application server, the same one that hosts our curriculum's demo apps. The request will be sent there- Our application server's caprover application has an nginx redirection (if you login to caprover, the redirection application is called redirect-to-www) to send back a
301
HTTP response code for https://www.c0d3.com.
- Our application server's caprover application has an nginx redirection (if you login to caprover, the redirection application is called redirect-to-www) to send back a
- Browser sends a request to https://www.c0d3.com (notice the
www
in the url). DNS resolution for this url will resolve to a server owned by Vercel, and the request will be sent to the vercel instance that hosts our application.- Take a look at our nextjs config. If a route is defined there, nextJS will immediately respond with those rules first.
- For our example, vercel will send back HTML and assets from their CDN, which contains our landing page. Keep in mind, this page is static, which means during deployment the page is built and put into their CDN for faster response times.
- When browser receives the index page, the first code that runs is
_app.tsx
. This file is a container for every page.- Sentry (used for our error monitoring) Posthog (used for our front end analytics), and Apollo (used for sending GraphQL requests) are initialized.
- Since the index page is served by CDN and is client side rendered,
_app.tsx
will be running on the browser so it is run on the client side. This is important because if you track down the Apollo setup helper function,useApollo
, you will see that it needs to account for server side generated (SSG), server side rendered (SSR), as well as client side rendered pages (which is the case for our current example).- Pages that have
getServerSideProps
function defined are server side rendered, so_app.tsx
would run on the server side.
- Pages that have
- After running
_app.tsx
, the browser renders the index page component. The first thing it does is to try to predict user login status by checking localstorage.- This is done to have a faster loading page. Alternatives were to send request to check for login status (slow), or server side render (then we can't use cdn)
- If user is not logged in, the landing page is rendered.
- Let's assume the user is logged in, in that case the curriculum page is rendered. Keep in mind we are using client side routing so this page change does not result the browser to send a new request to
/curriculum
.-
/curriculum
page has a getStaticProps, which means the page is getting server side generated (SSG) by vercel and then uploaded to their CDN every five minutes. More info with NextJS documentation.- We choose to do this because lesson content and challenges do not change often so it did not make sense for every user to send a request to fetch an additional request to get lesson and challenge descriptions on every page load. Instead, we build this page once every 5 minutes and push to the CDN so every user will get the lesson and challenge data along with the page.
- Since
_app.tsx
already ran when loading the index page, it does not run again.
-
- As the curriculum page loads, a graphql request is sent to the server by calling
useGetSessionQuery
.- The
useGetSessionQuery
is autogenerated by graphql code generator by runningyarn generate
.- The reason why we use code generator is because it is tedious to write out our graphql front end queries and then write out the types (for typescript) for it. Codegen will take our queries and autogenerate hooks and typescript types.
- This query request is sent to the server.
- The
- When server receives the graphql query at
/api/graphql
, which is handled by/pages/api/graphql.ts
- The request object goes through a few middlewares, which gives you logging functions like
req.warn
and user info withreq.user
- The request object goes through a few middlewares, which gives you logging functions like
- The request continues to the session query resolver, which queries our database using prisma and returns the data to the browser.
- We use prisma for our database queries so we don't have to write SQL and typescript types manually. For example, if we were to get the stars using SQL, it would look something like
SELECT * FROM USERS WHERE .... INNER JOIN ...
, which is complicated! Prisma allows us to query our database easily using JavaScript syntax and then generates optimized SQL for us along with types for typescript.
- We use prisma for our database queries so we don't have to write SQL and typescript types manually. For example, if we were to get the stars using SQL, it would look something like
- The browser continues to render the curriculum page and renders
LessonCard
components for each lesson. For each card, if the user has passed a lesson a request would be sent to retrieve the submissions for the lesson. - The request goes to
/api/graphql
(mentioned above) and makes its way to submissions resolver, where Prisma is used to query the submissions for the given lesson.
Done! Page is now completely loaded!
- User clicks sign in on the client side
- The request eventually arrives at the graphql resolver, which either throws an error or sets the
session
cookie and returns the user information. - When the client side receives the response, it sets the corresponding errors if there are errors. If not, the
localStorage
is updated and user redirected to/curriculum
.
- User clicks sign up on the client side
- A request eventually arrives at the graphql resolver, which either throws an error or returns the user information.
- When the client side receives the response, it sets the corresponding errors if there are errors. If not, the user shown the signup success component.
- The signup success component prompts user to set their password.
- When the user types their password and hits submit, a request goes to graphql resolver, which would either throw error or sets the user cookie and returns a success message.
- Once successful, user is shown a success message with a button to continue to the curriculum page.
Keep in mind the CLI is in a different repo!
What happens when you type c0d3 login
into the terminal to login?
- You are prompted for your c0d3 credentials.
- A graphql request is sent to www.c0d3.com/api/graphql with a login mutation.
- The request goes through the middlewares first and then arrives at the login mutation.
- In the login mutation, if the user does not have a cliToken, one would be generated for the user and stored in the database.
- When cli receives the response, the token is written into
~/.c0d3/credentials.json
What happens when you type c0d3 submit
into the terminal to submit your code?
- The CLI gets the token that is generated by the
c0d3 login
command, gets thediff
between the current branch andmaster
branch, prompts forlesson and challenge
, and prompts for confirmation. - The CLI sends a submission graphql request to www.c0d3.com/api/graphql with a create submission mutation.
- The request goes through the middlewares first and then arrives at the createSubmission mutation.
- In the
createSubmission
mutation resolver, a new submission will be created, if there's a previous submission, its status will be updated to Overwritten.
- In the
This resolver deals with adding and removing alerts for every user. Alerts have two different categories which are info and urgent which can only be added and removed by an admin here.
-
addAlert
deals with adding an alert so that when an alert is added, users can see that alert on their dashboard. -
removeAlert
deals with removing an alert so users won't be able to see it on the dashboard anymore.
This resolver handles with changing admin rights for users with changeAdminRights
This resolver handles with the login, signout, and signup of a user.
-
login
- Handles with logging in a user and updating the session. -
logout
- Handles with logging out a user and destroying the session object. -
signup
- Handles with signing up a user/creating a user with prisma. -
isTokenValid
- Checks if CLI token is valid. Created because of issue highlighted here.
This resolver handles creating and updating a challenge on the admin page
-
createChallenge
- Creates a new challenge for a lesson. -
updateChallenge
- Updates an existing challenge for a lesson.
This resolver handles creating and updating a lesson on the admin page
-
createLesson
- Creates a new lesson with its respective content. -
updateLesson
- Updates an existing lesson and its content.
This resolver deals with requesting and changing a user's password on the forgot password page
-
reqPwReset
- Handles sending an email to a user requesting a password change. -
changePw
- Handles with changing a user's password and updating it.
This resolver handles the action of giving a star to a user. When a star is given, a message is also sent to the according Discord channel, notifying who gave a star and who had received a star.
-
setStar
- handles giving a star to a user and sending a message to the correct discord channel.
This resolver handles retrieving user information to be displayed on the profile page
-
userInfo
- returns user information such as username, stars received and given, etc.