mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-04 09:15:58 +02:00
Merge pull request #294 from the-programmers-hangout/style-format-codebase
style: format codebase with Prettier
This commit is contained in:
@@ -66,18 +66,18 @@ const weather = await getWeatherAsync("Los Angeles").catch((error) => {
|
|||||||
console.log(weather);
|
console.log(weather);
|
||||||
```
|
```
|
||||||
|
|
||||||
In Node.js >v8.0.0 you can make use of the built-in `util` package which exposes a
|
In Node.js >v8.0.0 you can make use of the built-in `util` package which exposes a
|
||||||
[promisify](https://nodejs.org/api/util.html#util_util_promisify_original) method. This method helps us convert our original function to a promise-based function so that it returns the callback.
|
[promisify](https://nodejs.org/api/util.html#util_util_promisify_original) method. This method helps us convert our original function to a promise-based function so that it returns the callback.
|
||||||
|
|
||||||
Using our example from earlier, we can write it as:
|
Using our example from earlier, we can write it as:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const util = require("util")
|
const util = require("util");
|
||||||
|
|
||||||
const getWeatherAsync = util.promisify(getWeather)
|
const getWeatherAsync = util.promisify(getWeather);
|
||||||
|
|
||||||
const weather = await getWeatherAync("Los Angeles").catch(console.log)
|
const weather = await getWeatherAync("Los Angeles").catch(console.log);
|
||||||
console.log(weather)
|
console.log(weather);
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** the `promisify` method adds a extra argument to the arguments you passed in. In this case we are calling the custom function with a single parameter of type `String`, which means the original function should also accept `(String, Function)`, `Function` being the callback `(error, result)`.
|
**Note:** the `promisify` method adds a extra argument to the arguments you passed in. In this case we are calling the custom function with a single parameter of type `String`, which means the original function should also accept `(String, Function)`, `Function` being the callback `(error, result)`.
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ title: "Chapter 1: Getting setup"
|
|||||||
|
|
||||||
## Getting setup.
|
## Getting setup.
|
||||||
|
|
||||||
One of the first steps to any project is having a nice clear workspace to get started.
|
One of the first steps to any project is having a nice clear workspace to get started.
|
||||||
We can do the same with programming projects by creating an empty directory for our project to be developed in.
|
We can do the same with programming projects by creating an empty directory for our project to be developed in.
|
||||||
|
|
||||||
You should pick a suitable name for this project, you
|
You should pick a suitable name for this project, you
|
||||||
can pick a word or phrase yourself or use a [project name generator](http://codenames.herokuapp.com/).
|
can pick a word or phrase yourself or use a [project name generator](http://codenames.herokuapp.com/).
|
||||||
Try to make sure that there is no space in your project name as this will cause issues later.
|
Try to make sure that there is no space in your project name as this will cause issues later.
|
||||||
|
|
||||||
@@ -18,14 +18,14 @@ If you are using a build tool that sets up the environment for you now would be
|
|||||||
|
|
||||||
Feel free to add the Hello World of your language to test that everything is setup correctly.
|
Feel free to add the Hello World of your language to test that everything is setup correctly.
|
||||||
|
|
||||||
One of the key steps in this project will be to track progress and changes as you develop.
|
One of the key steps in this project will be to track progress and changes as you develop.
|
||||||
For this we are going to be using `git`. If you do not know git,
|
For this we are going to be using `git`. If you do not know git,
|
||||||
don't worry there will be links to [tutorials](https://www.atlassian.com/git/tutorials)
|
don't worry there will be links to [tutorials](https://www.atlassian.com/git/tutorials)
|
||||||
and [guides](https://rogerdudler.github.io/git-guide/).
|
and [guides](https://rogerdudler.github.io/git-guide/).
|
||||||
|
|
||||||
Setup the git repository and push it to a remote host like Github or Gitlab or BitBucket.
|
Setup the git repository and push it to a remote host like Github or Gitlab or BitBucket.
|
||||||
|
|
||||||
Consider adding a `.gitignore` file to stop from committing unimportant files.
|
Consider adding a `.gitignore` file to stop from committing unimportant files.
|
||||||
Here is a [guide](https://help.github.com/en/github/using-git/ignoring-files)
|
Here is a [guide](https://help.github.com/en/github/using-git/ignoring-files)
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
@@ -39,4 +39,4 @@ Here is a [guide](https://help.github.com/en/github/using-git/ignoring-files)
|
|||||||
|
|
||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Create a `.gitignore` file and add that to the repository.
|
- Create a `.gitignore` file and add that to the repository.
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ title: "Chapter 2: So what are we building?"
|
|||||||
The actual final end goal is going to remain a mystery for the time being, but what I can tell you is that we are going
|
The actual final end goal is going to remain a mystery for the time being, but what I can tell you is that we are going
|
||||||
to be building a server!
|
to be building a server!
|
||||||
|
|
||||||
What is a server? It's a program that accepts incoming connections, reads and writes to that connection and closing
|
What is a server? It's a program that accepts incoming connections, reads and writes to that connection and closing
|
||||||
it eventually.
|
it eventually.
|
||||||
|
|
||||||
You will hear the term socket used a lot in this project. Sockets are a way of connecting two devices on a network together.
|
You will hear the term socket used a lot in this project. Sockets are a way of connecting two devices on a network together.
|
||||||
@@ -21,7 +21,7 @@ on windows it's [Winsock](https://www.wikiwand.com/en/Winsock).
|
|||||||
|
|
||||||
This project will mostly be using berkeley sockets but if you want to use windows APIs feel free.
|
This project will mostly be using berkeley sockets but if you want to use windows APIs feel free.
|
||||||
|
|
||||||
In general there is a flow for sockets. On the client you follow a flow like this;
|
In general there is a flow for sockets. On the client you follow a flow like this;
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
+---------+
|
+---------+
|
||||||
@@ -52,15 +52,15 @@ On the server the flow is slightly more involved.
|
|||||||
| | | |
|
| | | |
|
||||||
+------------+ +----------+
|
+------------+ +----------+
|
||||||
```
|
```
|
||||||
|
|
||||||
When a server starts up and creates a socket, it binds that socket to an interface and a port.
|
When a server starts up and creates a socket, it binds that socket to an interface and a port.
|
||||||
The server will then set the socket to listening for connections,
|
The server will then set the socket to listening for connections,
|
||||||
when a connection comes in it needs to accept that connection.
|
when a connection comes in it needs to accept that connection.
|
||||||
Once a connection has been accepted it can receive and send to the socket the same as the client and eventually close it.
|
Once a connection has been accepted it can receive and send to the socket the same as the client and eventually close it.
|
||||||
|
|
||||||
This overview is brushing over a few details and you are encouraged to do your own research
|
This overview is brushing over a few details and you are encouraged to do your own research
|
||||||
|
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
- Read up on sockets.
|
- Read up on sockets.
|
||||||
- Find the documentation on your languages bindings for sockets.
|
- Find the documentation on your languages bindings for sockets.
|
||||||
|
|||||||
@@ -14,31 +14,32 @@ chapters in the project
|
|||||||
|
|
||||||
The first step is to create a socket in your language.
|
The first step is to create a socket in your language.
|
||||||
|
|
||||||
Different languages will expect you to set it up in different ways, you should check the documentation for your given
|
Different languages will expect you to set it up in different ways, you should check the documentation for your given
|
||||||
network bindings, something like this.
|
network bindings, something like this.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var socket = new Socket();
|
var socket = new Socket();
|
||||||
```
|
```
|
||||||
|
|
||||||
Once we have that socket we can then bind it to an interface.
|
Once we have that socket we can then bind it to an interface.
|
||||||
The interface is what IP network / device it is going to listen on, the port is the port it will bind to.
|
The interface is what IP network / device it is going to listen on, the port is the port it will bind to.
|
||||||
|
|
||||||
Whenever you see a connection like `127.0.0.1:6789` the IP address comes first, then `:` then the port number.
|
Whenever you see a connection like `127.0.0.1:6789` the IP address comes first, then `:` then the port number.
|
||||||
|
|
||||||
In the pseudo code this would be the required code to bind the socket. You can pick any port number for this, I chose `6789`
|
In the pseudo code this would be the required code to bind the socket. You can pick any port number for this, I chose `6789`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
socket.bind("127.0.0.1", 6789);
|
socket.bind("127.0.0.1", 6789);
|
||||||
```
|
```
|
||||||
|
|
||||||
Now that the socket is bound, we can put it into listening mode. Listening mode implies that people will be connecting
|
Now that the socket is bound, we can put it into listening mode. Listening mode implies that people will be connecting
|
||||||
to this socket. The parameter is *usually* the backlog of connections you want to allow.
|
to this socket. The parameter is _usually_ the backlog of connections you want to allow.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
socket.listen(1);
|
socket.listen(1);
|
||||||
```
|
```
|
||||||
|
|
||||||
Once we have set the socket up in listen mode we can finally accept an incoming connection.
|
Once we have set the socket up in listen mode we can finally accept an incoming connection.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var conn = socket.accept();
|
var conn = socket.accept();
|
||||||
@@ -59,19 +60,21 @@ stdin.read(); // to stop the program just exiting.
|
|||||||
|
|
||||||
If you are using windows you can use [Putty](https://www.ssh.com/ssh/putty/putty-manuals/0.68/Chapter3.html#using-rawprot) to create a raw connection.
|
If you are using windows you can use [Putty](https://www.ssh.com/ssh/putty/putty-manuals/0.68/Chapter3.html#using-rawprot) to create a raw connection.
|
||||||
|
|
||||||
On linux you can use `netcat` or `nc` to make network connections,
|
On linux you can use `netcat` or `nc` to make network connections,
|
||||||
you can see if your server is listening properly by running a command like this
|
you can see if your server is listening properly by running a command like this
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
nc -v -v localhost <port>
|
nc -v -v localhost <port>
|
||||||
```
|
```
|
||||||
|
|
||||||
where `<port>` is the port number you picked earlier on.
|
where `<port>` is the port number you picked earlier on.
|
||||||
|
|
||||||
|
If it works you should see some output like
|
||||||
|
|
||||||
If it works you should see some output like
|
|
||||||
```sh
|
```sh
|
||||||
localhost [127.0.0.1] 6789 (radg) open
|
localhost [127.0.0.1] 6789 (radg) open
|
||||||
```
|
```
|
||||||
|
|
||||||
If something has gone wrong then you will get a different message.
|
If something has gone wrong then you will get a different message.
|
||||||
|
|
||||||
When you have completed the goals for this chapter you will have created a socket, bound it, listened for connections and accepted a connection.
|
When you have completed the goals for this chapter you will have created a socket, bound it, listened for connections and accepted a connection.
|
||||||
@@ -86,4 +89,4 @@ You should try experimenting with connecting twice and seeing what happens. This
|
|||||||
|
|
||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Allow for a backlog of connections.
|
- Allow for a backlog of connections.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ title: "Chapter 4: Writing to the socket"
|
|||||||
|
|
||||||
## Chapter 4: Writing to the socket.
|
## Chapter 4: Writing to the socket.
|
||||||
|
|
||||||
We have a server, but it doesn't really do anything. That isn't very useful really.
|
We have a server, but it doesn't really do anything. That isn't very useful really.
|
||||||
|
|
||||||
In this chapter we will take it a step further and actually write a message to the connection.
|
In this chapter we will take it a step further and actually write a message to the connection.
|
||||||
|
|
||||||
@@ -29,12 +29,12 @@ conn.send("Hello Joe!\n");
|
|||||||
conn.close();
|
conn.close();
|
||||||
```
|
```
|
||||||
|
|
||||||
When testing this with netcat we should see that when someone connects it prints out `Hello Joe!` in the terminal,
|
When testing this with netcat we should see that when someone connects it prints out `Hello Joe!` in the terminal,
|
||||||
then closes the connection.
|
then closes the connection.
|
||||||
|
|
||||||
For the time being we are going to stick to hard coded responses, but you can change that message to whatever you want.
|
For the time being we are going to stick to hard coded responses, but you can change that message to whatever you want.
|
||||||
|
|
||||||
You can always send a message to a client that is *not* closed.
|
You can always send a message to a client that is _not_ closed.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
conn.send("hi ");
|
conn.send("hi ");
|
||||||
@@ -44,7 +44,7 @@ conn.send("slim shady\n");
|
|||||||
conn.close();
|
conn.close();
|
||||||
```
|
```
|
||||||
|
|
||||||
This code will send `hi my name is slim shady` to anyone that connects.
|
This code will send `hi my name is slim shady` to anyone that connects.
|
||||||
Notice it doesn't have to be all in one single send method
|
Notice it doesn't have to be all in one single send method
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
@@ -53,4 +53,4 @@ Notice it doesn't have to be all in one single send method
|
|||||||
|
|
||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Send a message to the client every X seconds.
|
- Send a message to the client every X seconds.
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ title: "Chapter 4: Reading from the socket"
|
|||||||
|
|
||||||
## Chapter 4: Reading from the socket.
|
## Chapter 4: Reading from the socket.
|
||||||
|
|
||||||
It's a good start, we have a server that can accept connections. It will write a message to the client.
|
It's a good start, we have a server that can accept connections. It will write a message to the client.
|
||||||
|
|
||||||
But we aren't reading anything from the client. This will all change now.
|
But we aren't reading anything from the client. This will all change now.
|
||||||
|
|
||||||
Most network bindings will have a `recv` method. This method allows you to receive some bytes from the client.
|
Most network bindings will have a `recv` method. This method allows you to receive some bytes from the client.
|
||||||
There might be higher level abstractions like `recv_line` or `recv_all` or something like that but we are gonna focus
|
There might be higher level abstractions like `recv_line` or `recv_all` or something like that but we are gonna focus
|
||||||
on the simplest version `recv`. The basic version of recv takes a number, and tries to read that many bytes from the
|
on the simplest version `recv`. The basic version of recv takes a number, and tries to read that many bytes from the
|
||||||
connected client. It will read as many as it can then return what it read.
|
connected client. It will read as many as it can then return what it read.
|
||||||
|
|
||||||
Given our code from previous chapters.
|
Given our code from previous chapters.
|
||||||
|
|
||||||
@@ -26,6 +26,7 @@ client.send("You said: \n");
|
|||||||
client.send(reply);
|
client.send(reply);
|
||||||
client.close();
|
client.close();
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that you can also test your server with netcat, use netcat as a client and whatever you write in the terminal will be sent to the server.
|
Note that you can also test your server with netcat, use netcat as a client and whatever you write in the terminal will be sent to the server.
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
@@ -36,4 +37,4 @@ Note that you can also test your server with netcat, use netcat as a client and
|
|||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Find a method that allows you to read lines OR parse the bytes into lines yourself.
|
- Find a method that allows you to read lines OR parse the bytes into lines yourself.
|
||||||
- Accept multiple lines.
|
- Accept multiple lines.
|
||||||
|
|||||||
@@ -6,37 +6,46 @@ title: "Chapter 6: What is a protocol?"
|
|||||||
---
|
---
|
||||||
|
|
||||||
## Chapter 6: What is a protocol?
|
## Chapter 6: What is a protocol?
|
||||||
|
|
||||||
How do we humans communicate? Through a mutually agreed convention of a language and conventions.
|
How do we humans communicate? Through a mutually agreed convention of a language and conventions.
|
||||||
Similarly, How do we make clients and servers talk to each other?
|
Similarly, How do we make clients and servers talk to each other?
|
||||||
They need some sort of agreed way to ask for things and respond with replies or errors. This mutually agreed set of rules is commonly known as a protocol.
|
They need some sort of agreed way to ask for things and respond with replies or errors. This mutually agreed set of rules is commonly known as a protocol.
|
||||||
|
|
||||||
In this chapter, we are going to create a really simple protocol for getting and storing strings, a *dictionary*.
|
In this chapter, we are going to create a really simple protocol for getting and storing strings, a _dictionary_.
|
||||||
With our hypothetical protocol your server will store the definition to a series of words.
|
With our hypothetical protocol your server will store the definition to a series of words.
|
||||||
You can do this nice and simply with a map-like data structure or something more complex, your choice.
|
You can do this nice and simply with a map-like data structure or something more complex, your choice.
|
||||||
|
|
||||||
In a client-server architecture, genrally a client initiates communication by making a request to the server. In our case, the client will make a request to *get* a definition from the dictionary server.
|
In a client-server architecture, genrally a client initiates communication by making a request to the server. In our case, the client will make a request to _get_ a definition from the dictionary server.
|
||||||
|
|
||||||
|
To _get_ a definition, the client will send this:
|
||||||
|
|
||||||
To *get* a definition, the client will send this:
|
|
||||||
```txt
|
```txt
|
||||||
GET someword
|
GET someword
|
||||||
```
|
```
|
||||||
|
|
||||||
All lines in this protocol will be terminated with `\n`
|
All lines in this protocol will be terminated with `\n`
|
||||||
|
|
||||||
Your server will then look that word up and reply with the value stored against it.
|
Your server will then look that word up and reply with the value stored against it.
|
||||||
The server will need to reply with a sensible error message if the word does not exist.
|
The server will need to reply with a sensible error message if the word does not exist.
|
||||||
|
|
||||||
For now the reply will be either
|
For now the reply will be either
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
ANSWER the description
|
ANSWER the description
|
||||||
```
|
```
|
||||||
or
|
|
||||||
|
or
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
ERROR can't find someword
|
ERROR can't find someword
|
||||||
```
|
```
|
||||||
|
|
||||||
We have created a simple reading protocol. This protocol can be extended by adding new requests of the form:
|
We have created a simple reading protocol. This protocol can be extended by adding new requests of the form:
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
VERB args go here
|
VERB args go here
|
||||||
```
|
```
|
||||||
|
|
||||||
I encourage you to experiment and add other verb based commands.
|
I encourage you to experiment and add other verb based commands.
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
@@ -48,4 +57,4 @@ I encourage you to experiment and add other verb based commands.
|
|||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Allow clients to `SET word definition*` at runtime. Where definition might be multiple words ending in `\n`
|
- Allow clients to `SET word definition*` at runtime. Where definition might be multiple words ending in `\n`
|
||||||
- Add other commands like `CLEAR` to clear all definitions or `ALL` to get all words currently defined.
|
- Add other commands like `CLEAR` to clear all definitions or `ALL` to get all words currently defined.
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ title: "Chapter 7: Testing"
|
|||||||
---
|
---
|
||||||
|
|
||||||
## Chapter 7: Testing.
|
## Chapter 7: Testing.
|
||||||
Im assuming most of the testing has been done by hand up to this point but this isn't really
|
|
||||||
scalable as a long term solution. This is where unit testing comes in, all projects should have tests that cover
|
|
||||||
at least the bare minimum of cases that are expected. This project is no different.
|
|
||||||
|
|
||||||
Pretty much all languages have some sort of unit test functionality, to make connections and assert things.
|
Im assuming most of the testing has been done by hand up to this point but this isn't really
|
||||||
We will need to write a bit of code to be able to facilitate the unit testing. You will now need to create a
|
scalable as a long term solution. This is where unit testing comes in, all projects should have tests that cover
|
||||||
|
at least the bare minimum of cases that are expected. This project is no different.
|
||||||
|
|
||||||
|
Pretty much all languages have some sort of unit test functionality, to make connections and assert things.
|
||||||
|
We will need to write a bit of code to be able to facilitate the unit testing. You will now need to create a
|
||||||
tcp client that can connect and you can send and receive lines via, this will help with testing the project as
|
tcp client that can connect and you can send and receive lines via, this will help with testing the project as
|
||||||
a whole.
|
a whole.
|
||||||
|
|
||||||
@@ -23,16 +24,16 @@ fun test_get_definition() {
|
|||||||
assert(line == "ANSWER something interesting here\n");
|
assert(line == "ANSWER something interesting here\n");
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The idea here is to try and test all the functionality of your program and use the above tests to identify what may be going wrong.
|
The idea here is to try and test all the functionality of your program and use the above tests to identify what may be going wrong.
|
||||||
|
|
||||||
Coverage is a reasonably good metric for establishing if your code is well tested. Coverage is identifying what lines
|
Coverage is a reasonably good metric for establishing if your code is well tested. Coverage is identifying what lines
|
||||||
are covered by unit tests and what lines are not.
|
are covered by unit tests and what lines are not.
|
||||||
|
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
- Unit test any verbs defined in the previous chapter.
|
- Unit test any verbs defined in the previous chapter.
|
||||||
|
|
||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Reach a 90% test coverage.
|
- Reach a 90% test coverage.
|
||||||
|
|||||||
@@ -7,16 +7,16 @@ title: "Chapter 8: Multiple connections at once"
|
|||||||
|
|
||||||
## Chapter 8: Multiple connections at once.
|
## Chapter 8: Multiple connections at once.
|
||||||
|
|
||||||
Up until now we have only had one server, one client.
|
Up until now we have only had one server, one client.
|
||||||
|
|
||||||
If you try to run the server from earlier and connect to it twice you will get one of two things happen. Either the client
|
If you try to run the server from earlier and connect to it twice you will get one of two things happen. Either the client
|
||||||
fails to connect because the server is busy and refuses the connection, or the connection will hang waiting in the backlog
|
fails to connect because the server is busy and refuses the connection, or the connection will hang waiting in the backlog
|
||||||
to be accepted.
|
to be accepted.
|
||||||
|
|
||||||
Now we are going to move to support multiple connections at the same time.
|
Now we are going to move to support multiple connections at the same time.
|
||||||
|
|
||||||
There are a number of ways to do this; threads, processes, actors, async/await, promises, callbacks, select, iocp. The list can
|
There are a number of ways to do this; threads, processes, actors, async/await, promises, callbacks, select, iocp. The list can
|
||||||
go on for hours. Each language will have different bindings and ways of doing these things, you will need to do some research as to
|
go on for hours. Each language will have different bindings and ways of doing these things, you will need to do some research as to
|
||||||
what the best option is for you.
|
what the best option is for you.
|
||||||
|
|
||||||
Both epoll and select are common in most languages a few other suggestions include.
|
Both epoll and select are common in most languages a few other suggestions include.
|
||||||
@@ -34,4 +34,4 @@ Both epoll and select are common in most languages a few other suggestions inclu
|
|||||||
|
|
||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- See how many connections you can have concurrently using something like [wrk](https://github.com/wg/wrk)
|
- See how many connections you can have concurrently using something like [wrk](https://github.com/wg/wrk)
|
||||||
|
|||||||
@@ -7,15 +7,15 @@ title: "Chapter 9: Documentation and clean code"
|
|||||||
|
|
||||||
## Chapter 9: Documentation and clean code.
|
## Chapter 9: Documentation and clean code.
|
||||||
|
|
||||||
Wew this is the chapter nobody wants to talk about.
|
Wew this is the chapter nobody wants to talk about.
|
||||||
|
|
||||||
A good project is one that is readable and understandable. To be readable code should have some sort of consistency
|
A good project is one that is readable and understandable. To be readable code should have some sort of consistency
|
||||||
and formatting, this helps with navigation and generally makes working on the code easier. The second is understandable,
|
and formatting, this helps with navigation and generally makes working on the code easier. The second is understandable,
|
||||||
this comes in two flavours, concise code with clear meaning and documented code with clear explanation.
|
this comes in two flavours, concise code with clear meaning and documented code with clear explanation.
|
||||||
|
|
||||||
Most languages offer some sort of docstring processing, or have support for external tools like doxygen.
|
Most languages offer some sort of docstring processing, or have support for external tools like doxygen.
|
||||||
|
|
||||||
You should take advantage of this and document your code so far, try to explain and design choices and tell the reader
|
You should take advantage of this and document your code so far, try to explain and design choices and tell the reader
|
||||||
what each method does BUT do not go over the top. Nobody wants 500 lines of documentation explaining that `x = 1`.
|
what each method does BUT do not go over the top. Nobody wants 500 lines of documentation explaining that `x = 1`.
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
@@ -24,4 +24,4 @@ what each method does BUT do not go over the top. Nobody wants 500 lines of docu
|
|||||||
|
|
||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Write a readme.md in your repo
|
- Write a readme.md in your repo
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ title: "Chapter 10: Methods and resources"
|
|||||||
## Chapter 10: Methods and resources.
|
## Chapter 10: Methods and resources.
|
||||||
|
|
||||||
If you haven't guessed by now, we are writing a HTTP server. Not against the entire specification (though you can if you want)
|
If you haven't guessed by now, we are writing a HTTP server. Not against the entire specification (though you can if you want)
|
||||||
just against a limited subset that *should* work with a browser if you have done it correctly.
|
just against a limited subset that _should_ work with a browser if you have done it correctly.
|
||||||
|
|
||||||
HTTP is a line delimited protocol. The idea being that a client will request content from a server and the server will
|
HTTP is a line delimited protocol. The idea being that a client will request content from a server and the server will
|
||||||
deliver it.
|
deliver it.
|
||||||
Each time one side delivers a line to the other it should be delimited by `\r` and `\n` which is carriage ret and line feed.
|
Each time one side delivers a line to the other it should be delimited by `\r` and `\n` which is carriage ret and line feed.
|
||||||
|
|
||||||
The start of a HTTP request is as follows.
|
The start of a HTTP request is as follows.
|
||||||
@@ -25,8 +25,8 @@ The start of a HTTP request is as follows.
|
|||||||
The methods are `OPTIONS` or `GET` or `HEAD` or `POST` or `PUT` or `DELETE` or `TRACE` or `CONNECT`
|
The methods are `OPTIONS` or `GET` or `HEAD` or `POST` or `PUT` or `DELETE` or `TRACE` or `CONNECT`
|
||||||
Some of these you might have experienced before, others are a bit more unusual.
|
Some of these you might have experienced before, others are a bit more unusual.
|
||||||
|
|
||||||
`GET` is the simplest with "GET me this resource". Get is also considered idempotent which means the act of doing it again
|
`GET` is the simplest with "GET me this resource". Get is also considered idempotent which means the act of doing it again
|
||||||
should have identical results, cause *no* side effects, it can also be cached.
|
should have identical results, cause _no_ side effects, it can also be cached.
|
||||||
|
|
||||||
`PUT` is "PUT something at this resource". This method is also considered idempotent and is usually used to create or update a resource.
|
`PUT` is "PUT something at this resource". This method is also considered idempotent and is usually used to create or update a resource.
|
||||||
|
|
||||||
@@ -40,12 +40,11 @@ should have identical results, cause *no* side effects, it can also be cached.
|
|||||||
|
|
||||||
`TRACE` and `CONNECT` we are going to ignore these two as they are not commonly used anymore and wont be of much use to us.
|
`TRACE` and `CONNECT` we are going to ignore these two as they are not commonly used anymore and wont be of much use to us.
|
||||||
|
|
||||||
|
|
||||||
### Resource
|
### Resource
|
||||||
|
|
||||||
A resource is just something identified by a URL. An example of a resource could be `/index.html` or `/api/person`
|
A resource is just something identified by a URL. An example of a resource could be `/index.html` or `/api/person`
|
||||||
These are both resources, it's down to the server to decide what these resources mean. In a web application they might
|
These are both resources, it's down to the server to decide what these resources mean. In a web application they might
|
||||||
correspond to a controller, or as a file on disk.
|
correspond to a controller, or as a file on disk.
|
||||||
|
|
||||||
### Version
|
### Version
|
||||||
|
|
||||||
@@ -54,8 +53,8 @@ The version tells the server what http version the client is using and can suppo
|
|||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
- Process an incoming request (you can use curl, wget, your browser to send requests)
|
- Process an incoming request (you can use curl, wget, your browser to send requests)
|
||||||
- Read the first line and break it into a method, a resource and the version and then close the connection.
|
- Read the first line and break it into a method, a resource and the version and then close the connection.
|
||||||
|
|
||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Log when a request is invalid (unknown method)
|
- Log when a request is invalid (unknown method)
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ title: "Chapter 11: Headers and bodies"
|
|||||||
|
|
||||||
## Chapter 11: Headers and bodies.
|
## Chapter 11: Headers and bodies.
|
||||||
|
|
||||||
We are almost there, we can almost complete an entire request. But before we can finish a request, we need to
|
We are almost there, we can almost complete an entire request. But before we can finish a request, we need to
|
||||||
read the last few parts of an entire request.
|
read the last few parts of an entire request.
|
||||||
|
|
||||||
We have already read the `GET /resource HTTP/1.0\r\n` line parsed.
|
We have already read the `GET /resource HTTP/1.0\r\n` line parsed.
|
||||||
|
|
||||||
The next line following this will be a header line.
|
The next line following this will be a header line.
|
||||||
Headers are just key value pairs that repeat until you read an empty `\r\n` line.
|
Headers are just key value pairs that repeat until you read an empty `\r\n` line.
|
||||||
You split on the `:` and treat the left hand side as the key, and the right hand side as the value.
|
You split on the `:` and treat the left hand side as the key, and the right hand side as the value.
|
||||||
|
|
||||||
|
|
||||||
This is an example request from curl.
|
This is an example request from curl.
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
GET / HTTP/1.1
|
GET / HTTP/1.1
|
||||||
Host: localhost:9995
|
Host: localhost:9995
|
||||||
@@ -28,19 +28,19 @@ Accept: */*
|
|||||||
|
|
||||||
This breaks down into the following information.
|
This breaks down into the following information.
|
||||||
|
|
||||||
* Method: GET
|
- Method: GET
|
||||||
* Resource: /
|
- Resource: /
|
||||||
* Headers
|
- Headers
|
||||||
* Host: localhost:9995
|
- Host: localhost:9995
|
||||||
* User-Agent: curl/7.67.0
|
- User-Agent: curl/7.67.0
|
||||||
* Accept: */*
|
- Accept: _/_
|
||||||
|
|
||||||
That's all the information contained in this request.
|
That's all the information contained in this request.
|
||||||
|
|
||||||
There are hundreds of different headers and browsers / clients will often define their own.
|
There are hundreds of different headers and browsers / clients will often define their own.
|
||||||
For a list of common headers look [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)
|
For a list of common headers look [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)
|
||||||
|
|
||||||
Some client requests will send a body. This will be included after the header block.
|
Some client requests will send a body. This will be included after the header block.
|
||||||
For now this is not important.
|
For now this is not important.
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
@@ -49,4 +49,4 @@ For now this is not important.
|
|||||||
|
|
||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Handle malformed headers.
|
- Handle malformed headers.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ title: "Chapter 11: Replying"
|
|||||||
|
|
||||||
Servers have a number of responses they can make to a request. These range from "OK" to "Not Found" a list can be found [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
|
Servers have a number of responses they can make to a request. These range from "OK" to "Not Found" a list can be found [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
|
||||||
|
|
||||||
The ones we will focus on in this chapter is
|
The ones we will focus on in this chapter is
|
||||||
|
|
||||||
- 200 - OK
|
- 200 - OK
|
||||||
- 400 - Bad Request
|
- 400 - Bad Request
|
||||||
@@ -27,11 +27,11 @@ Accept: */*
|
|||||||
|
|
||||||
Lets start by replying to the request given above.
|
Lets start by replying to the request given above.
|
||||||
|
|
||||||
For this we need to have a directory for our web hosting files to live in. Lets call this `./www`.
|
For this we need to have a directory for our web hosting files to live in. Lets call this `./www`.
|
||||||
Create the directory and add a test file in it called `test.txt` this file should contain some text of your choice.
|
Create the directory and add a test file in it called `test.txt` this file should contain some text of your choice.
|
||||||
|
|
||||||
Now the request that came in asked for the `test.txt` file we are hosting.
|
Now the request that came in asked for the `test.txt` file we are hosting.
|
||||||
So to answer the request we must first check we have that resource, in this case we do.
|
So to answer the request we must first check we have that resource, in this case we do.
|
||||||
So we are going to reply with the most common HTTP response. OK.
|
So we are going to reply with the most common HTTP response. OK.
|
||||||
|
|
||||||
The first line of the response looks like this. We include the version we support, the status number, and the human readable
|
The first line of the response looks like this. We include the version we support, the status number, and the human readable
|
||||||
@@ -41,12 +41,12 @@ description of that status number.
|
|||||||
HTTP/1.0 200 OK
|
HTTP/1.0 200 OK
|
||||||
```
|
```
|
||||||
|
|
||||||
Once we have sent that line we can send any headers we want to send.
|
Once we have sent that line we can send any headers we want to send.
|
||||||
There are no mandatory headers but there are some suggested ones we will cover later.
|
There are no mandatory headers but there are some suggested ones we will cover later.
|
||||||
|
|
||||||
Then we send an empty `\r\n` to indicate we are done sending the headers. Now we can send the body.
|
Then we send an empty `\r\n` to indicate we are done sending the headers. Now we can send the body.
|
||||||
|
|
||||||
We read the `test.txt` file in and we write that as the body.
|
We read the `test.txt` file in and we write that as the body.
|
||||||
Once we are done sending we can simply close the connection to indicate we are done sending the body.
|
Once we are done sending we can simply close the connection to indicate we are done sending the body.
|
||||||
|
|
||||||
The entire response might look something like this
|
The entire response might look something like this
|
||||||
@@ -54,17 +54,16 @@ The entire response might look something like this
|
|||||||
```txt
|
```txt
|
||||||
HTTP/1.0 200 OK
|
HTTP/1.0 200 OK
|
||||||
|
|
||||||
Etiam bibendum sapien ut est posuere pretium. Vestibulum a justo at sapien pharetra sagittis in eget lacus.
|
Etiam bibendum sapien ut est posuere pretium. Vestibulum a justo at sapien pharetra sagittis in eget lacus.
|
||||||
Sed ullamcorper quam sed nulla molestie interdum. Vestibulum hendrerit, est vel tristique
|
Sed ullamcorper quam sed nulla molestie interdum. Vestibulum hendrerit, est vel tristique
|
||||||
luctus, urna nibh pulvinar ligula, vel scelerisque nisi orci ac mauris. Nam tempor, orci nec rutrum sodales,
|
luctus, urna nibh pulvinar ligula, vel scelerisque nisi orci ac mauris. Nam tempor, orci nec rutrum sodales,
|
||||||
nulla diam imperdiet enim, id pellentesque leo nibh et urna. Vivamus non tortor dapibus, efficitur ex sed,
|
nulla diam imperdiet enim, id pellentesque leo nibh et urna. Vivamus non tortor dapibus, efficitur ex sed,
|
||||||
blandit odio. Vivamus volutpat, nunc sed pulvinar pellentesque, ipsum ante vestibulum sem, vitae malesuada
|
blandit odio. Vivamus volutpat, nunc sed pulvinar pellentesque, ipsum ante vestibulum sem, vitae malesuada
|
||||||
dui odio ut erat.
|
dui odio ut erat.
|
||||||
```
|
```
|
||||||
|
|
||||||
Boom. Done.
|
Boom. Done.
|
||||||
|
|
||||||
|
|
||||||
There are other replies we might send though, for example lets say someone requests `missing.txt` and we don't have that.
|
There are other replies we might send though, for example lets say someone requests `missing.txt` and we don't have that.
|
||||||
We need to inform the client it doesn't exist. We do this by sending a 404. It's mostly the same as the previous but we change
|
We need to inform the client it doesn't exist. We do this by sending a 404. It's mostly the same as the previous but we change
|
||||||
the number and message to something different
|
the number and message to something different
|
||||||
@@ -75,16 +74,17 @@ HTTP/1.0 404 Not Found
|
|||||||
Sorry we don't have that file!
|
Sorry we don't have that file!
|
||||||
```
|
```
|
||||||
|
|
||||||
The final response is a generic response when the client sends you something that doesn't make sense.
|
The final response is a generic response when the client sends you something that doesn't make sense.
|
||||||
|
|
||||||
Imagine the client sent
|
Imagine the client sent
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
GasdasET /test.txt
|
GasdasET /test.txt
|
||||||
!!!!!!
|
!!!!!!
|
||||||
WHAT/1.1
|
WHAT/1.1
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
That doesn't look like a valid request so we should tell them that by sending a Bad Request response.
|
That doesn't look like a valid request so we should tell them that by sending a Bad Request response.
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
@@ -116,4 +116,4 @@ This is an example of the `Server` header, there are other common headers as lis
|
|||||||
|
|
||||||
- Implement the `Content-Length` header
|
- Implement the `Content-Length` header
|
||||||
- Implement the `Server` header
|
- Implement the `Server` header
|
||||||
- Implement the `Content-Type` header
|
- Implement the `Content-Type` header
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ title: "Chapter 12: Config"
|
|||||||
|
|
||||||
## Chapter 12: Config.
|
## Chapter 12: Config.
|
||||||
|
|
||||||
For the time being we have been hard coding all the various values like the port and the web directory,
|
For the time being we have been hard coding all the various values like the port and the web directory,
|
||||||
it's about time we made this configurable.
|
it's about time we made this configurable.
|
||||||
|
|
||||||
Lets create a config file that we can set the port and the host in. Lets say this config file is called `config`
|
Lets create a config file that we can set the port and the host in. Lets say this config file is called `config`
|
||||||
and can contain any format you want. YAML, JSON, INI, Plain text; whatever suits you and your language.
|
and can contain any format you want. YAML, JSON, INI, Plain text; whatever suits you and your language.
|
||||||
|
|
||||||
For these examples we will use YAML but they are all similar
|
For these examples we will use YAML but they are all similar
|
||||||
|
|
||||||
@@ -23,11 +23,11 @@ web_directory: ./www
|
|||||||
|
|
||||||
Lets update the program to read the values from config and use those.
|
Lets update the program to read the values from config and use those.
|
||||||
|
|
||||||
The whole point of making it configurable is the person deploying this in the future doesn't want to edit code or
|
The whole point of making it configurable is the person deploying this in the future doesn't want to edit code or
|
||||||
change values in your program to get it to work to their usecase. So by providing a way to configure your application
|
change values in your program to get it to work to their usecase. So by providing a way to configure your application
|
||||||
it makes it more portable and usable in different situations.
|
it makes it more portable and usable in different situations.
|
||||||
|
|
||||||
This should be quite an easy chapter but it's a reasonably important one.
|
This should be quite an easy chapter but it's a reasonably important one.
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
@@ -36,4 +36,4 @@ This should be quite an easy chapter but it's a reasonably important one.
|
|||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Provide sane defaults if the values are missing
|
- Provide sane defaults if the values are missing
|
||||||
- Add your own config values.
|
- Add your own config values.
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ GET /../config.yaml HTTP/1.0
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This request is a relative path. So your server accepts the path. Goes up one directory from the `www` directory.
|
This request is a relative path. So your server accepts the path. Goes up one directory from the `www` directory.
|
||||||
Reads your *config* and sends it to the attacker.
|
Reads your _config_ and sends it to the attacker.
|
||||||
|
|
||||||
This is real bad. Imagine if your config had database passwords in it?
|
This is real bad. Imagine if your config had database passwords in it?
|
||||||
Imagine if someone requested `../../../../etc/passwd` and your server replied with it!
|
Imagine if someone requested `../../../../etc/passwd` and your server replied with it!
|
||||||
@@ -30,14 +30,14 @@ You need to find a way to isolate the `www` directory we created so nobody can r
|
|||||||
- You could manually work out if `..` will take you above the `www` directory.
|
- You could manually work out if `..` will take you above the `www` directory.
|
||||||
- You could make the http server run as a different user and only give that user permission to read `www` directory.
|
- You could make the http server run as a different user and only give that user permission to read `www` directory.
|
||||||
|
|
||||||
This is just one of many possible attacks against your web server.
|
This is just one of many possible attacks against your web server.
|
||||||
|
|
||||||
You should look through guides for your language of choice and find ways to harden your application.
|
You should look through guides for your language of choice and find ways to harden your application.
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
- Solve the ability to read files outside of your `www` directory.
|
- Solve the ability to read files outside of your `www` directory.
|
||||||
|
|
||||||
## Bonus goals
|
## Bonus goals
|
||||||
|
|
||||||
- Audit your code for other issues.
|
- Audit your code for other issues.
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ Any questions about the project, goals, or queries can be handled in the event c
|
|||||||
|
|
||||||
You can use any language that the server currently has a channel for.
|
You can use any language that the server currently has a channel for.
|
||||||
|
|
||||||
This project will expect you to have basic understanding of the language you are using and have a few extra tools
|
This project will expect you to have basic understanding of the language you are using and have a few extra tools
|
||||||
installed like; `git`, `netcat` (linux), `putty` (windows)
|
installed like; `git`, `netcat` (linux), `putty` (windows)
|
||||||
|
|
||||||
This project will guide you in the direction of what you need to do but it leaves individual learning up to you.
|
This project will guide you in the direction of what you need to do but it leaves individual learning up to you.
|
||||||
Feel free to ask for help, search topics online, look for tutorials for any of the concepts presented.
|
Feel free to ask for help, search topics online, look for tutorials for any of the concepts presented.
|
||||||
|
|
||||||
The idea is to guide you along but not give you all the answers. There will be pseudo code in some of the chapters in
|
The idea is to guide you along but not give you all the answers. There will be pseudo code in some of the chapters in
|
||||||
this project it's down to you to achieve the functionality in your language of choice.
|
this project it's down to you to achieve the functionality in your language of choice.
|
||||||
The pseudo code isn't representative of a final project and is there to convey specific ideas you need to achieve
|
The pseudo code isn't representative of a final project and is there to convey specific ideas you need to achieve
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
- Put in the work yourself. Don't copy and paste, the only person you are cheating is yourself.
|
- Put in the work yourself. Don't copy and paste, the only person you are cheating is yourself.
|
||||||
- If you are helping don't spoon-feed. It's about the journey not the destination.
|
- If you are helping don't spoon-feed. It's about the journey not the destination.
|
||||||
|
|||||||
Reference in New Issue
Block a user