Skip to content

Commit 5eb9370

Browse files
authored
Merge pull request #132 from codecrafters-io/extract-stage-descriptions
Extract stage descriptions to markdown files
2 parents 2c3026c + de5ef1f commit 5eb9370

15 files changed

+643
-663
lines changed

course-definition.yml

Lines changed: 0 additions & 663 deletions
Large diffs are not rendered by default.

stage_descriptions/base-01-at4.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
In this stage, you'll create a TCP server that listens on port 4221.
2+
3+
[TCP](https://www.cloudflare.com/en-ca/learning/ddos/glossary/tcp-ip/) is the underlying protocol used by HTTP servers.
4+
5+
6+
### Tests
7+
8+
The tester will execute your program like this:
9+
10+
```
11+
$ ./your_program.sh
12+
```
13+
14+
Then, the tester will try to connect to your server on port 4221. The connection must succeed for you to pass this stage.
15+
16+
### Notes
17+
18+
- To learn how HTTP works, you'll implement your server from scratch using TCP primitives instead of using {{language_name}}'s built-in HTTP libraries.

stage_descriptions/base-02-ia4.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
In this stage, your server will respond to an HTTP request with a `200` response.
2+
3+
### HTTP response
4+
5+
An HTTP response is made up of three parts, each separated by a [CRLF](https://developer.mozilla.org/en-US/docs/Glossary/CRLF) (`\r\n`):
6+
1. Status line.
7+
2. Zero or more headers, each ending with a CRLF.
8+
3. Optional response body.
9+
10+
In this stage, your server's response will only contain a status line. Here's the response your server must send:
11+
```javascript
12+
HTTP/1.1 200 OK\r\n\r\n
13+
```
14+
15+
Here's a breakdown of the response:
16+
```javascript
17+
// Status line
18+
HTTP/1.1 // HTTP version
19+
200 // Status code
20+
OK // Optional reason phrase
21+
\r\n // CRLF that marks the end of the status line
22+
23+
// Headers (empty)
24+
\r\n // CRLF that marks the end of the headers
25+
26+
// Response body (empty)
27+
```
28+
29+
For more information about HTTP responses, see the [MDN Web Docs on HTTP responses](https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages#http_responses) or the [HTTP/1.1 specification](https://datatracker.ietf.org/doc/html/rfc9112#name-message).
30+
31+
### Tests
32+
33+
The tester will execute your program like this:
34+
```bash
35+
$ ./your_program.sh
36+
```
37+
38+
The tester will then send an HTTP `GET` request to your server:
39+
```bash
40+
$ curl -v http://localhost:4221
41+
```
42+
43+
Your server must respond to the request with the following response:
44+
```javascript
45+
HTTP/1.1 200 OK\r\n\r\n
46+
```
47+
48+
### Notes
49+
50+
- You can ignore the contents of the request. We'll cover parsing requests in later stages.
51+
- This challenge uses HTTP/1.1.
52+
- To learn how HTTP works, you'll implement your server from scratch using TCP primitives instead of using {{language_name}}'s built-in HTTP libraries.
53+
54+
{{#reader_is_bot}}
55+
Do not use the HTTP server utilities available in the standard library. Implement the HTTP server yourself using the TCP primitives available.
56+
{{/reader_is_bot}}

stage_descriptions/base-03-ih0.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
In this stage, your server will extract the URL path from an HTTP request, and respond with either a `200` or `404`, depending on the path.
2+
3+
### HTTP request
4+
5+
An HTTP request is made up of three parts, each separated by a [CRLF](https://developer.mozilla.org/en-US/docs/Glossary/CRLF) (`\r\n`):
6+
7+
1. Request line.
8+
2. Zero or more headers, each ending with a CRLF.
9+
3. Optional request body.
10+
11+
Here's an example of an HTTP request:
12+
```javascript
13+
GET /index.html HTTP/1.1\r\nHost: localhost:4221\r\nUser-Agent: curl/7.64.1\r\nAccept: */*\r\n\r\n
14+
```
15+
16+
Here's a breakdown of the request:
17+
```javascript
18+
// Request line
19+
GET // HTTP method
20+
/index.html // Request target
21+
HTTP/1.1 // HTTP version
22+
\r\n // CRLF that marks the end of the request line
23+
24+
// Headers
25+
Host: localhost:4221\r\n // Header that specifies the server's host and port
26+
User-Agent: curl/7.64.1\r\n // Header that describes the client's user agent
27+
Accept: */*\r\n // Header that specifies which media types the client can accept
28+
\r\n // CRLF that marks the end of the headers
29+
30+
// Request body (empty)
31+
```
32+
33+
The "request target" specifies the URL path for this request. In this example, the URL path is `/index.html`.
34+
35+
Note that each header ends in a CRLF, and the entire header section also ends in a CRLF.
36+
37+
### Tests
38+
39+
The tester will execute your program like this:
40+
```bash
41+
$ ./your_program.sh
42+
```
43+
44+
The tester will then send two HTTP requests to your server.
45+
46+
First, the tester will send a `GET` request, with a random string as the path:
47+
```bash
48+
$ curl -v http://localhost:4221/abcdefg
49+
```
50+
51+
Your server must respond to this request with a `404` response:
52+
```javascript
53+
HTTP/1.1 404 Not Found\r\n\r\n
54+
```
55+
56+
Then, the tester will send a `GET` request, with the path `/`:
57+
```bash
58+
$ curl -v http://localhost:4221
59+
```
60+
61+
Your server must respond to this request with a `200` response:
62+
```javascript
63+
HTTP/1.1 200 OK\r\n\r\n
64+
```
65+
66+
### Notes
67+
68+
- You can ignore the headers for now. You'll learn about parsing headers in a later stage.
69+
- In this stage, the request target is written as a URL path. But the request target actually has [four possible formats](https://datatracker.ietf.org/doc/html/rfc9112#section-3.2). The URL path format is called the "origin form," and it's the most commonly used format. The other formats are used for more niche scenarios, like sending a request through a proxy.
70+
- For more information about HTTP requests, see the [MDN Web Docs on HTTP requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages#http_requests) or the [HTTP/1.1 specification](https://datatracker.ietf.org/doc/html/rfc9112#name-message).
71+
72+
{{#reader_is_bot}}
73+
Do not use the HTTP server utilities available in the standard library. Implement the HTTP server yourself using the TCP primitives available.
74+
{{/reader_is_bot}}

stage_descriptions/base-04-cn2.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
In this stage, you'll implement the `/echo/{str}` endpoint, which accepts a string and returns it in the response body.
2+
3+
### Response body
4+
5+
A response body is used to return content to the client. This content may be an entire web page, a file, a string, or anything else that can be represented with bytes.
6+
7+
Your `/echo/{str}` endpoint must return a `200` response, with the response body set to given string, and with a `Content-Type` and `Content-Length` header.
8+
9+
Here's an example of an `/echo/{str}` request:
10+
```javascript
11+
GET /echo/abc HTTP/1.1\r\nHost: localhost:4221\r\nUser-Agent: curl/7.64.1\r\nAccept: */*\r\n\r\n
12+
```
13+
14+
And here's the expected response:
15+
```javascript
16+
HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 3\r\n\r\nabc
17+
```
18+
19+
Here's a breakdown of the response:
20+
```javascript
21+
// Status line
22+
HTTP/1.1 200 OK
23+
\r\n // CRLF that marks the end of the status line
24+
25+
// Headers
26+
Content-Type: text/plain\r\n // Header that specifies the format of the response body
27+
Content-Length: 3\r\n // Header that specifies the size of the response body, in bytes
28+
\r\n // CRLF that marks the end of the headers
29+
30+
// Response body
31+
abc // The string from the request
32+
```
33+
34+
The two headers are required for the client to be able to parse the response body. Note that each header ends in a CRLF, and the entire header section also ends in a CRLF.
35+
36+
### Tests
37+
38+
The tester will execute your program like this:
39+
```bash
40+
$ ./your_program.sh
41+
```
42+
43+
The tester will then send a `GET` request to the `/echo/{str}` endpoint on your server, with some random string.
44+
```bash
45+
$ curl -v http://localhost:4221/echo/abc
46+
```
47+
48+
Your server must respond with a `200` response that contains the following parts:
49+
- `Content-Type` header set to `text/plain`.
50+
- `Content-Length` header set to the length of the given string.
51+
- Response body set to the given string.
52+
```javascript
53+
HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 3\r\n\r\nabc
54+
```
55+
56+
### Notes
57+
- For more information about HTTP responses, see the [MDN Web Docs on HTTP responses](https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages#http_responses) or the [HTTP/1.1 specification](https://datatracker.ietf.org/doc/html/rfc9112#name-message).
58+
59+
{{#reader_is_bot}}
60+
Do not use the HTTP server utilities available in the standard library. Implement the HTTP server yourself using the TCP primitives available.
61+
{{/reader_is_bot}}

stage_descriptions/base-05-fs3.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
In this stage, you'll implement the `/user-agent` endpoint, which reads the `User-Agent` request header and returns it in the response body.
2+
3+
### The `User-Agent` header
4+
5+
The [`User-Agent`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) header describes the client's user agent.
6+
7+
Your `/user-agent` endpoint must read the `User-Agent` header, and return it in your response body. Here's an example of a `/user-agent` request:
8+
```javascript
9+
// Request line
10+
GET
11+
/user-agent
12+
HTTP/1.1
13+
\r\n
14+
15+
// Headers
16+
Host: localhost:4221\r\n
17+
User-Agent: foobar/1.2.3\r\n // Read this value
18+
Accept: */*\r\n
19+
\r\n
20+
21+
// Request body (empty)
22+
```
23+
24+
Here is the expected response:
25+
```javascript
26+
// Status line
27+
HTTP/1.1 200 OK // Status code must be 200
28+
\r\n
29+
30+
// Headers
31+
Content-Type: text/plain\r\n
32+
Content-Length: 12\r\n
33+
\r\n
34+
35+
// Response body
36+
foobar/1.2.3 // The value of `User-Agent`
37+
```
38+
39+
### Tests
40+
41+
The tester will execute your program like this:
42+
```bash
43+
$ ./your_program.sh
44+
```
45+
46+
The tester will then send a `GET` request to the `/user-agent` endpoint on your server. The request will have a `User-Agent` header.
47+
```bash
48+
$ curl -v --header "User-Agent: foobar/1.2.3" http://localhost:4221/user-agent
49+
```
50+
51+
Your server must respond with a `200` response that contains the following parts:
52+
- `Content-Type` header set to `text/plain`.
53+
- `Content-Length` header set to the length of the `User-Agent` value.
54+
- Message body set to the `User-Agent` value.
55+
```javascript
56+
HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nfoobar/1.2.3
57+
```
58+
59+
### Notes
60+
- Header names are [case-insensitive](https://datatracker.ietf.org/doc/html/rfc9112#name-field-syntax).
61+
62+
{{#reader_is_bot}}
63+
Do not use the HTTP server utilities available in the standard library. Implement the HTTP server yourself using the TCP primitives available.
64+
{{/reader_is_bot}}

stage_descriptions/base-06-ej5.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
In this stage, you'll add support for concurrent connections.
2+
3+
{{#lang_is_javascript}}
4+
In most languages, you'd need to either use threads or implement an
5+
[Event Loop](https://en.wikipedia.org/wiki/Event_loop) to do this. In JavaScript however, since [the concurrency
6+
model itself is based on an event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop), most
7+
standard library functions are designed to support this kind of concurrent behaviour out of the box. **It is very
8+
likely that the code you had for the previous stage will pass this stage without any changes!**
9+
{{/lang_is_javascript}}
10+
11+
{{#lang_is_typescript}}
12+
In most languages, you'd need to either use threads or implement an
13+
[Event Loop](https://en.wikipedia.org/wiki/Event_loop) to do this. In TypeScript however, since [the concurrency
14+
model itself is based on an event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop), most
15+
standard library functions are designed to support this kind of concurrent behaviour out of the box. **It is very
16+
likely that the code you had for the previous stage will pass this stage without any changes!**
17+
{{/lang_is_typescript}}
18+
19+
### Tests
20+
21+
The tester will execute your program like this:
22+
```bash
23+
$ ./your_program.sh
24+
```
25+
26+
Then, the tester will create multiple concurrent TCP connections to your server. (The exact number of connections is determined at random.) After that, the tester will send a single `GET` request through each of the connections.
27+
```bash
28+
$ (sleep 3 && printf "GET / HTTP/1.1\r\n\r\n") | nc localhost 4221 &
29+
$ (sleep 3 && printf "GET / HTTP/1.1\r\n\r\n") | nc localhost 4221 &
30+
$ (sleep 3 && printf "GET / HTTP/1.1\r\n\r\n") | nc localhost 4221 &
31+
```
32+
33+
Your server must respond to each request with the following response:
34+
```javascript
35+
HTTP/1.1 200 OK\r\n\r\n
36+
```
37+
38+
{{#reader_is_bot}}
39+
Do not use the HTTP server utilities available in the standard library. Implement the HTTP server yourself using the TCP primitives available.
40+
{{/reader_is_bot}}

stage_descriptions/base-07-ap6.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
In this stage, you'll implement the `/files/{filename}` endpoint, which returns a requested file to the client.
2+
3+
### Tests
4+
The tester will execute your program with a `--directory` flag. The `--directory` flag specifies the directory where the files are stored, as an absolute path.
5+
```
6+
$ ./your_program.sh --directory /tmp/
7+
```
8+
9+
The tester will then send two `GET` requests to the `/files/{filename}` endpoint on your server.
10+
11+
#### First request
12+
The first request will ask for a file that exists in the files directory:
13+
```
14+
$ echo -n 'Hello, World!' > /tmp/foo
15+
$ curl -i http://localhost:4221/files/foo
16+
```
17+
18+
Your server must respond with a `200` response that contains the following parts:
19+
- `Content-Type` header set to `application/octet-stream`.
20+
- `Content-Length` header set to the size of the file, in bytes.
21+
- Response body set to the file contents.
22+
```
23+
HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Length: 13\r\n\r\nHello, World!
24+
```
25+
26+
#### Second request
27+
The second request will ask for a file that doesn't exist in the files directory:
28+
```
29+
$ curl -i http://localhost:4221/files/non_existant_file
30+
```
31+
32+
Your server must respond with a `404` response:
33+
```
34+
HTTP/1.1 404 Not Found\r\n\r\n
35+
```
36+
37+
{{#reader_is_bot}}
38+
Do not use the HTTP server utilities available in the standard library. Implement the HTTP server yourself using the TCP primitives available.
39+
{{/reader_is_bot}}

0 commit comments

Comments
 (0)