Skip to content

Commit

Permalink
fix(C3): minor improvements (#129)
Browse files Browse the repository at this point in the history
  • Loading branch information
uhasker authored Dec 8, 2024
1 parent 7da2526 commit 456b98f
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 66 deletions.
35 changes: 17 additions & 18 deletions src/chapter3/01-ips-ports-and-domains.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ They can also be virtual, i.e. only exist in software.

### Protocols

A **protocol** defines the rules by which computers communicate.
Protocols allow computer to "speak the same language".
A **protocol** defines the rules by which the network interfaces communicate.
Protocols allow computers to "speak the same language".

The internet knows a lot of different protocols—from really common ones like IP, HTTP, HTTPS or DNS to really exotic ones that are only relevant for a select group of specialists.

For example, if you're browsing `http://example.com`, the underlying protocol is HTTP.
Similarly, if your browse `https://www.google.com/`, the underlying protocol is HTTPS.
Similarly, if you browse `https://www.google.com/`, the underlying protocol is HTTPS.

Protocols can also use other protocols.
For example, the HTTP protocol uses the TCP protocol which in turn uses the IP protocol.
Expand All @@ -33,11 +33,11 @@ An **IPv4 address** (or simply **IP** for short) is an identifier that is assign
For example, your wireless network interface might have an IPv4 address that it can use to communicate with other computers on the same wireless network.

Such an address consists of 4 numbers between 0 and 255, separated by dots.
Therefore, example addresses might be `123.56.1.17` or `192.168.178.47`.
Therefore, IP addresses look like `123.56.1.17` or `192.168.178.47`.

Note that instead of saying that a _network interface has a particular IP_, we will often say that _a computer has some IP_.
This is because often we only really care about a particular interface (usually your Ethernet or your wireless interface).
However, it is important to understand that diffent network interfaces will usually have different IP addresses even if they're located on the same machine.
However, it's important to understand that different network interfaces will usually have different IP addresses even if they're located on the same machine.

The **loopback address** `127.0.0.1` is a special IP address which can be used to identify the machine you're currently on.
You can basically use this to talk to your own computer.
Expand All @@ -60,18 +60,18 @@ A public address is basically any address that hasn't been explicitly marked as
For example, `142.251.37.14` is a public address since it's not in one of the private address blocks.

> There are a few other special address blocks like the "link local" block.
> However they won't be important for this book and therefore we'll simply skip over them.
> However, they won't be important for this book and therefore we'll simply skip over them.
### Ports

Usually you want to be able to run multiple networking services on your machine.
Usually, you want to be able to run multiple networking services on your machine.
This poses the problem of _uniquely identifying_ those services.
After all, if the all share the same IP, how can we distinguish them from one another?
After all, if they all share the same IP, how can we distinguish them from one another?

The answer is that we can use **ports**.
A port is simply a number assigned to uniquely identify a connection endpoint on a machine.

Let's say that you want to have a web service and an `ssh` service running on the same machine.
Let's say you want to have a web service and an `ssh` service running on the same machine.

> The `ssh` protocol allows you to remotely log in to a computer and execute commands on it.
Expand All @@ -82,44 +82,43 @@ If a service is assigned some port, programmers often say that the service is **
In our example, the web service would be _listening_ on port `443` and the ssh service would be _listening_ on port `22`.

If you want to specify an IP and a port together, you use the colon `:` notation.
For example, if you have an HTTPS web server running on a machine with the IP `123.56.1.17` and the assigned port `443`, the web server would be reachable at `123.56.1.17:443`.
For example, if you have an HTTPS web server running on a machine with the IP `123.56.1.17` and you have assigned the port `443` to the web server, it would be reachable at `123.56.1.17:443`.

> If we add the protocol (HTTPS), we would get the correct URL for the web server, which would be `https://123.56.1.17:443`.
> We will talk about URLs in a second.
> We will talk about URLs in more detail soon.
Similarly, if you start an HTTP web server locally (i.e. on `127.0.0.1`) on port `80`, you could access it at `127.0.0.1:80`.

> If we add the protocol (HTTP), we would get the correct URL for the web server, which would be `http://127.0.0.1:80`.
> We will talk about URLs in a second.
There is a list of **well-known ports**.
For example, an `http` application typically runs on port `80` while an `https` application typically runs on port `443`.
For example, an HTTP application typically runs on port `80` while an HTTPS application typically runs on port `443`.
This is why you don't need to explicitly tell your browser that `google.com` can be found at port `443`—your web browser will figure this out automatically because `443` is a well-known port.

> During development we will not follow this convention and mostly run our applications on port `3000`.
> This is because you don't need special "root" permissions to run something on port `3000`.
> Typically, ports below `1024` are considered "privileged" and require these special permissions.
> However, when we deploy our final application, it will run on the well-known port `443`.
> However, when we deploy our final application to production, it will run on the well-known port `443`.
### Domains

While IP addresses are great, they are very unwieldy and hard to remember for humans.
Imagine that instead of "just google it" or "go to `google.com`" you would have to tell someone to "go to `142.251.37.14`".
That would suck!

This why the concept of a **domain** was introduced.
This is why the concept of a **domain** was introduced.
A domain is a string that identifies some network resource.
In our neat and tidy web development world, a domain usually has a corresponding IP address.

For example, the domain `google.com` might correspond to the IP address `142.251.37.14`.
That is, you can identify the resource either via `google.com` or via `142.251.37.14`.

The translation of domains to IP adresses is handled by the **Domain Name System** (DNS) protocol.
The translation of domains to IP addresses is handled by the **Domain Name System** (DNS) protocol.
If you type `google.com` into your browser address bar, DNS will translate it to the correct IP under the hood.

> The reality is much more complicated and involves something called DNS records.
> This means that domains can have IPv4 addressess, IPv6 addresses, mail addresses etc.
> Domains can also be forwarded to other domains with so called CNAME records.
> This means that domains can have IPv4 addresses, IPv6 addresses, mail addresses etc.
> Domains can also be forwarded to other domains with so-called CNAME records.
> The picture becomes even more complicated once we go into load balancing.
> Nevertheless, for our purposes the mental model of "there are domains and they correspond to IP addresses" is enough.
Expand Down
54 changes: 28 additions & 26 deletions src/chapter3/02-an-http-primer.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

**Servers** and **clients** are nothing more than regular programs (like the ones you saw in the first chapter).
For example, a server might be a JavaScript program that waits for HTTP requests and sends back responses.
A client might be a browser on your laptop or your phone - it might even be a regular script.
A client might be a browser on your laptop or your phoneit might even be a regular script.

> Often, the term "server" is also used to refer to the actual machine the software is running on.
Expand All @@ -21,9 +21,9 @@ If your code runs on the server, you will have access to the filesystem, but you
This makes sense since the browser is running on your client and the server (mostly) doesn't have access to it.

This also means that we will often need to transmit data from the client to the server (and the other way around).
When writing a web application, the most common way to do so is by using the HTTP procotol.
When writing a web application, the most common way to do so is by using the HTTP protocol.

## Requests and Responses
### Requests and Responses

The **HTTP protocol** is a **request/response protocol**, i.e. HTTP clients send requests to an HTTP server and receive responses in return.

Expand All @@ -41,7 +41,7 @@ Afterwards, the server creates a response and sends it back to the client.

And, finally, the client looks at the response and determines how to update the UI (user interface).

## HTTPS
### HTTPS

We should mention that nowadays developers never use plain HTTP in production.
Instead, they use the **HTTPS protocol**, which is encrypted HTTP.
Expand Down Expand Up @@ -75,7 +75,7 @@ In that file we will create an Express application and then make that applicatio

This is how you can create an Express application and make it listen on port `3000`:

```javascript
```js
const express = require('express');
const app = express();
const PORT = 3000;
Expand All @@ -88,7 +88,7 @@ app.listen(PORT, () => {
This application is not very useful, so let's add a **route** to it.
Add the following code above the call to `listen`:

```javascript
```js
app.get('/', (req, res) => {
res.send('Hello, world!');
});
Expand Down Expand Up @@ -128,7 +128,7 @@ Note that you will need to press <kbd>Ctrl</kbd> + <kbd>C</kbd> in your command
The string `http://localhost:3000/` is a so-called URL.
You have already seen URLs in the previous section.

Navigate to Google and search for "Next.js" - you will notice that the URL in your browser looks like this:
Navigate to Google and search for "Next.js"you will notice that the URL in your browser looks like this:

```
https://www.google.com/search?q=nextjs
Expand All @@ -148,8 +148,8 @@ scheme://host:port/path?key1=value1&key2=value2#fragment

> Note the word _typical_ here.
> HTTP URLs (and especially more general URLs) can become _much more_ complicated, but we will not cover all the little details in this book.
> In fact the complexity of URLs is often a source of subtle bugs and browser crashes.
> For example - at some point Android Chrome would [crash](https://news.ycombinator.com/item?id=28639708) when trying to open `http://../foo`.
> In fact, the complexity of URLs is often a source of subtle bugs and browser crashes.
> For exampleat some point Android Chrome would [crash](https://news.ycombinator.com/item?id=28639708) when trying to open `http://../foo`.
Let's go over the individual component of a typical URL one by one.

Expand All @@ -158,24 +158,24 @@ We will almost exclusively use HTTP or HTTPS in this book.
Therefore, the scheme will almost always be either `http` or `https`.
In the above Google URL the scheme is clearly `https`.

You already learned about the **host** and the **port**—the host identifies the device you wish to connect to and the port is the communication endpoint on that device.
You've already learned about the **host** and the **port**—the host identifies the device you wish to connect to and the port is the communication endpoint on that device.
Note that the host could be a domain (like `www.google.com`) or an IP address (like `142.251.36.238`).
Usually we will work with domains since they're stable and rarely change (unlike IP addresses).
Usually we will work with domains since they're stable and rarely change (unlike some IP addresses).

> At the time of this writing `142.251.36.238` is one of Google's IP addresses.
> This may of course change by the time you are reading this book.
The next part is the **path**.
Assuming it's not empty, the path begins with a forward slash `/` and uniquely identifies the resource we want to query.
In the Google URL the path is `/search`.
In the Google URL, the path is `/search`.

Often, paths will be hierarchical.
In this case the different components of the hierarchy are generally separated by slashes—for example, `/path/to/resource`.
In this case the different components of the hierarchy are generally separated by slashes, e.g. `/path/to/resource`.

The path can be followed by a **query**.
The query begins with a question mark and is followed by key-value pairs.
In the Google URL this is `?q=nextjs`.
Here the query provides information about your search.
In the Google URL, the query is given by `?q=nextjs`.
Here, the query provides information about your search.

If there are multiple key-value pairs, they're separated by ampersands `&`.
For example, a query might look like `?key1=value1&key2=value2`.
Expand All @@ -184,26 +184,28 @@ The query can be followed by a **fragment**.
This is used for navigation by the client and is not sent to the server.
A fragment begins with the `#` character, e.g. `?key1=value1&key2=value2#fragment`.

> For example, if you go to a Wikipedia article and click a heading in the table of contents, you will be navigated to that heading and a fragment will be appended to the URL in your browser address bar.
### GET and POST requests

HTTP knows multiple **request methods**.
HTTP knows many **request methods**.
We primarily care about two request methods for now—namely **GET** and **POST**.

GET requests are generally used to retrieve data.

Recall our route from above:

```javascript
```js
app.get('/', (req, res) => {
res.send('Hello world!');
res.send('Hello, World!');
});
```

This indicates that if a GET request is sent to the path '/', we would like to return 'Hello, world!' to the client.
This indicates that if a GET request is sent to the path `/`, we would like to return `'Hello, World!'` to the client.
The `req` variable represents the **request object** and `res` represents the **response object**.
If we want to send a HTTP response to the client we use the `res.send` method.

POST requests are generally used to send information to the server that tell it to create a new resource or update an existing resource.
POST requests are generally used to send information to instruct the server to create a new resource or update an existing resource.
For example, a login request will generally be a POST request since it tells the server that a user has logged in to the application.
Similarly, if you submit a web form, there will usually be a POST request attached to that, since form submissions carry new information.

Expand All @@ -217,9 +219,9 @@ Note that we need to enable some **middleware** in our script.
Middleware functions are functions that do some additional processing on requests or responses.

Specifically, we will need to use the `express.text()` middleware function to parse incoming request payloads into a string.
Add the following line of code to your script right after the initialization of the `app variable`:
Add the following line of code to your script right after the initialization of the `app` variable:

```javascript
```js
// code
const app = express();
const PORT = 3000;
Expand All @@ -231,16 +233,16 @@ app.use(express.text());

Consider the following route which simply returns the request body back to the client:

```javascript
```js
app.post('/echo', (req, res) => {
res.send(req.body);
});
```

We can send a POST request via `curl`.
We need to specify that we want to send a POST request using the `-X` flag.
In addition we specify the data that we want to send in the _body_ of the POST request using the `-d` flag.
Finally we specify a header called `Content-Type` and set it to `text/plain`.
Additionally, we can specify the data that we want to send in the _body_ of the POST request using the `-d` flag.
Finally, we specify a header called `Content-Type` and set it to `text/plain`.
This indicates that the data we want to send is plain text.

The final command looks like this:
Expand All @@ -252,7 +254,7 @@ curl -X POST -H "Content-Type: text/plain" -d 'test' http://localhost:3000/echo
Generally speaking, GET requests transmit information in the URL, while POST requests transmit information in the request body.

Note that we will rarely send plain text in the request.
Instead we usually use the JSON format that we introduced in the JavaScript chapter.
Instead, we will usually use the JSON format that we've already introduced in the JavaScript chapter.

In order to accept JSON requests, we need to replace the `express.text` middleware with the `express.json` middleware:

Expand Down
Loading

0 comments on commit 456b98f

Please sign in to comment.