CodeCraftersで「HTTPサーバー」を作ってみたくなったのでやっていきます。
CodeCraftersの各webページ
CodeCraftersの主要ページは以下のような構成になっているようです。
- 製品紹介
- サービス本体
- ドキュメント
- サービス稼働状況
- リポジトリ
GitHubアカウントと連携
CodeCraftersを利用するにはGitHubアカウントでログインする必要があるので、その対応を行っていきます。
まずは、製品紹介ページにアクセスします。
画面右上の「Try now」をクリックします。
「Challenges」の画面に切り替わります。
画面右上の「Sign in with GitHub」をクリックします。
権限を確認して問題なければ「Authorize codecrafters-io」をクリックします。
いくつかアンケートが表示されるので適宜答えましょう。
私は「PHPerKaigi 2023」のげんえいさんの登壇で知ったので、「How did you hear about CodeCrafters?」の質問には「Friend」、「Conference」と回答しました。
「Introduction」のステップで利用言語やアンケートに回答
アンケートに回答すると「Challenges」の画面に戻ってくるので、「Build your own HTTP server」を選択して、「Start Building」をクリックします。
「Introduction」の画面に遷移し、どの言語を利用したいか選択肢が表示されます。
PHPで解くつもりだったのですが、未実装のようなので今回は「Java」を選択しました。
「Javaなんもわからん」なので「Beginner」を選択しました。
仕事で週に数回程度は触っているので「Few times a week」を選択しました。
今回は不要なので「I'll pass」を選択しました。すると、画面下段に「Continue →」のボタンが表示されます。
「Introduction」の質問にすべて回答すると画面上段に「Completed」と表示され、「View next step →」のボタンが表示されます。
画面左側のメニューの「Introduction」に✅が表示されます。
画面上段の「View next step →」もしくは画面下段の「Continue →」をクリックします。
「Repository Setup」のステップでリポジトリのcloneとpushを実行
「Repository Setup」の画面に遷移し、ここから以降の作業で必要となるGitリポジトリのURLが表示されます。
「Step 1」としてリポジトリをcloneするように指示されていますので、表示されているコマンドを実行します。
$ git clone https://git.codecrafters.io/XXXXXXXXXXXXXXXX codecrafters-http-server-java && cd codecrafters-http-server-java
Cloning into 'codecrafters-http-server-java'...
remote: Enumerating objects: 12, done.
remote: Counting objects: 100% (12/12), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 12 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (12/12), 2.78 KiB | 712.00 KiB/s, done.
「Step 2」では --allow-empty
を使って空コミットを行うように指示されていますので、表示されているコマンドを実行します。
$ git commit --allow-empty -m 'test' && git push origin master
[master 8367fc1] test
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 172 bytes | 172.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
remote: ------------------------------------------------------------------------
remote:
remote:
remote: ___ _ ___ __ _
remote: / __\ ___ __| | ___ / __\_ __ __ _ / _|| |_ ___ _ __ ___
remote: / / / _ \ / _` | / _ \ / / | '__|/ _` || |_ | __|/ _ \| '__|/ __|
remote: / /___| (_) || (_| || __// /___| | | (_| || _|| |_| __/| | \__
remote: \____/ \___/ \__,_| \___|\____/|_| \__,_||_| \__|\___||_| |___/
remote:
remote:
remote: Welcome to CodeCrafters! Your commit was received successfully.
remote:
remote: ------------------------------------------------------------------------
remote:
remote: Running tests on your codebase. Streaming logs...
remote:
remote: [compile] [INFO] Scanning for projects...
remote: [compile] [INFO]
remote: [compile] [INFO] ----------------< io.codecrafters:build-your-own-http >-----------------
remote: [compile] [INFO] Building build-your-own-http 1.0
remote: [compile] [INFO] from pom.xml
remote: [compile] [INFO] --------------------------------[ jar ]---------------------------------
remote: [compile] [INFO]
remote: [compile] [INFO] --- resources:3.3.1:resources (default-resources) @ build-your-own-http ---
remote: [compile] [INFO] skip non existing resourceDirectory /app/src/main/resources
remote: [compile] [INFO]
remote: [compile] [INFO] --- compiler:3.11.0:compile (default-compile) @ build-your-own-http ---
remote: [compile] [INFO] Changes detected - recompiling the module! :source
remote: [compile] [INFO] Compiling 1 source file with javac [debug target 21] to target/classes
remote: [compile] [INFO]
remote: [compile] [INFO] --- resources:3.3.1:testResources (default-testResources) @ build-your-own-http ---
remote: [compile] [INFO] skip non existing resourceDirectory /app/src/test/resources
remote: [compile] [INFO]
remote: [compile] [INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ build-your-own-http ---
remote: [compile] [INFO] No sources to compile
remote: [compile] [INFO]
remote: [compile] [INFO] --- surefire:3.1.2:test (default-test) @ build-your-own-http ---
remote: [compile] [INFO] No tests to run.
remote: [compile] [INFO]
remote: [compile] [INFO] --- jar:3.3.0:jar (default-jar) @ build-your-own-http ---
remote: [compile] [INFO] Building jar: /app/target/build-your-own-http-1.0.jar
remote: [compile] [INFO]
remote: [compile] [INFO] --- assembly:3.6.0:single (make-assembly) @ build-your-own-http ---
remote: [compile] [INFO] Building jar: /tmp/codecrafters-http-target/java_http.jar
remote: [compile] [WARNING] Configuration option 'appendAssemblyId' is set to false.
remote: [compile] Instead of attaching the assembly file: /tmp/codecrafters-http-target/java_http.jar, it will become the file for main project artifact.
remote: [compile] NOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic!
remote: [compile] [WARNING] Replacing pre-existing project main-artifact file: /app/target/build-your-own-http-1.0.jar
remote: [compile] with assembly file: /tmp/codecrafters-http-target/java_http.jar
remote: [compile] [INFO] ------------------------------------------------------------------------
remote: [compile] [INFO] BUILD SUCCESS
remote: [compile] [INFO] ------------------------------------------------------------------------
remote: [compile] [INFO] Total time: 2.197 s
remote: [compile] [INFO] Finished at: 2024-02-24T08:16:50Z
remote: [compile] [INFO] ------------------------------------------------------------------------
remote: [compile] Compilation successful.
remote:
remote: [stage-1] Running tests for Stage #1: Bind to a port
remote: [stage-1] Connecting to localhost:4221 using TCP
remote: [your_program] Logs from your program will appear here!
remote: [stage-1] Looks like your program has terminated. A HTTP server is expected to be a long-running process.
remote: [stage-1] Test failed (try setting 'debug: true' in your codecrafters.yml to see more details)
remote:
remote: View stage instructions: https://app.codecrafters.io/courses/http-server.
remote:
To https://git.codecrafters.io/XXXXXXXXXXXXXXXX
c4bb38d..8367fc1 master -> master
pushが成功すると「Listening for a git push...」というメッセージが「🎉 Git push received! The first stage is now activated.」に切り替わり、画面下段に「Continue →」のボタンが表示されます。
「Repository Setup」のすべてのステップの対応が完了すると画面上段に「Completed」と表示され、「View next stage →」のボタンが表示されます。
画面左側のメニューの「Repository Setup」に✅が表示されます。
画面上段の「View next stage →」もしくは画面下段の「Continue →」をクリックします。
「Bind to a port」のタスク
「Bind to a port」の画面に遷移するので、「Your Task」を参照します。
※テストの失敗については先程のpush実行時のログにも表示されていましたが、画面上にも表示されています。
このステージで行うべきタスクの内容は以下のとおりです。
- 4221番ポートでTCPサーバーを起動すること。
「How to pass this stage」の「Step 1」にヒントというか答えが書いてあります。
ヒントのとおりプログラムを修正して、「Step 2」の指示のとおりpushを実行します。
$ git add .
$ git commit -m "pass 1st stage"
[master 8489766] pass 1st stage
1 file changed, 12 insertions(+), 12 deletions(-)
$ git push origin master
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 483 bytes | 483.00 KiB/s, done.
Total 6 (delta 2), reused 0 (delta 0), pack-reused 0
remote: ------------------------------------------------------------------------
remote:
remote:
remote: ___ _ ___ __ _
remote: / __\ ___ __| | ___ / __\_ __ __ _ / _|| |_ ___ _ __ ___
remote: / / / _ \ / _` | / _ \ / / | '__|/ _` || |_ | __|/ _ \| '__|/ __|
remote: / /___| (_) || (_| || __// /___| | | (_| || _|| |_| __/| | \__
remote: \____/ \___/ \__,_| \___|\____/|_| \__,_||_| \__|\___||_| |___/
remote:
remote:
remote: Welcome to CodeCrafters! Your commit was received successfully.
remote:
remote: ------------------------------------------------------------------------
remote:
remote: Running tests on your codebase. Streaming logs...
remote:
remote: [compile] [INFO] Scanning for projects...
remote: [compile] [INFO]
remote: [compile] [INFO] ----------------< io.codecrafters:build-your-own-http >-----------------
remote: [compile] [INFO] Building build-your-own-http 1.0
remote: [compile] [INFO] from pom.xml
remote: [compile] [INFO] --------------------------------[ jar ]---------------------------------
remote: [compile] [INFO]
remote: [compile] [INFO] --- resources:3.3.1:resources (default-resources) @ build-your-own-http ---
remote: [compile] [INFO] skip non existing resourceDirectory /app/src/main/resources
remote: [compile] [INFO]
remote: [compile] [INFO] --- compiler:3.11.0:compile (default-compile) @ build-your-own-http ---
remote: [compile] [INFO] Changes detected - recompiling the module! :source
remote: [compile] [INFO] Compiling 1 source file with javac [debug target 21] to target/classes
remote: [compile] [INFO]
remote: [compile] [INFO] --- resources:3.3.1:testResources (default-testResources) @ build-your-own-http ---
remote: [compile] [INFO] skip non existing resourceDirectory /app/src/test/resources
remote: [compile] [INFO]
remote: [compile] [INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ build-your-own-http ---
remote: [compile] [INFO] No sources to compile
remote: [compile] [INFO]
remote: [compile] [INFO] --- surefire:3.1.2:test (default-test) @ build-your-own-http ---
remote: [compile] [INFO] No tests to run.
remote: [compile] [INFO]
remote: [compile] [INFO] --- jar:3.3.0:jar (default-jar) @ build-your-own-http ---
remote: [compile] [INFO] Building jar: /app/target/build-your-own-http-1.0.jar
remote: [compile] [INFO]
remote: [compile] [INFO] --- assembly:3.6.0:single (make-assembly) @ build-your-own-http ---
remote: [compile] [INFO] Building jar: /tmp/codecrafters-http-target/java_http.jar
remote: [compile] [WARNING] Configuration option 'appendAssemblyId' is set to false.
remote: [compile] Instead of attaching the assembly file: /tmp/codecrafters-http-target/java_http.jar, it will become the file for main project artifact.
remote: [compile] NOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic!
remote: [compile] [WARNING] Replacing pre-existing project main-artifact file: /app/target/build-your-own-http-1.0.jar
remote: [compile] with assembly file: /tmp/codecrafters-http-target/java_http.jar
remote: [compile] [INFO] ------------------------------------------------------------------------
remote: [compile] [INFO] BUILD SUCCESS
remote: [compile] [INFO] ------------------------------------------------------------------------
remote: [compile] [INFO] Total time: 2.186 s
remote: [compile] [INFO] Finished at: 2024-02-24T08:46:44Z
remote: [compile] [INFO] ------------------------------------------------------------------------
remote: [compile] Compilation successful.
remote:
remote: [stage-1] Running tests for Stage #1: Bind to a port
remote: [stage-1] Connecting to localhost:4221 using TCP
remote: [your_program] Logs from your program will appear here!
remote: [stage-1] Success! Closing connection
remote: [stage-1] Test passed.
remote: [your_program] accepted new connection
remote:
remote: All tests ran successfully. Congrats!
remote:
remote: View instructions for the next stage: https://app.codecrafters.io/courses/http-server
remote:
To https://git.codecrafters.io/XXXXXXXXXXXXXXXX
8367fc1..8489766 master -> master
pushを実行すると、以下のようなメッセージからビルドとテストが実行されていることがわかります。
つまり、各ステージで提示されているタスク内容を元にプログラムの修正を行い、テストをパスすることで次のステージに進める仕組みのようです。
remote: [compile] [INFO] Building build-your-own-http 1.0
・
・
remote: [compile] [INFO] BUILD SUCCESS
・
・
remote: [compile] Compilation successful.
remote: [stage-1] Running tests for Stage #1: Bind to a port
remote: [stage-1] Connecting to localhost:4221 using TCP
・
・
remote: [stage-1] Test passed.
・
・
remote: All tests ran successfully. Congrats!
テストをパスすると「Your Task」の欄に「Completed」と表示され、「View Next Stage →」のボタンが表示されます。
「Bind to a port」のすべてのステップの対応が完了すると画面上段に「Completed」と表示され、「View next stage →」のボタンが表示されます。
画面左側のメニューの「Bind to a port」に✅が表示されます。
画面上段もしくは「Your Task」の欄の「View Next Stage →」をクリックします。
「Respond with 200」のタスク
「Respond with 200」の画面に遷移するので、「Your Task」を参照します。
このステージで行うべきタスクの内容は以下のとおりです。
- TCP接続を受け付けます。
- TCP接続の受信内容を読み取ります。(読み取った内容の解析は後のステージで行います)
- HTTPレスポンスとして以下を返します。
- ステータスライン(
HTTP/1.1 200 OK\r\n\r\n
)
- ステータスライン(
- 受信した他の内容は無視して構いません。(「Parse headers」というステージが控えているので、あとでこのあたりは対応することになると思われます)
解き方がわからなければ「Code Examples」のタブを参考にしましょう。
プログラムを修正して、「Step 2」の指示のとおりpushを実行します。
$ git add .
$ git commit -m "pass 2nd stage"
[master cbaf07a] pass 2nd stage
1 file changed, 14 insertions(+), 4 deletions(-)
$ git push origin master
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 674 bytes | 674.00 KiB/s, done.
Total 6 (delta 2), reused 0 (delta 0), pack-reused 0
remote: ------------------------------------------------------------------------
remote:
remote:
remote: ___ _ ___ __ _
remote: / __\ ___ __| | ___ / __\_ __ __ _ / _|| |_ ___ _ __ ___
remote: / / / _ \ / _` | / _ \ / / | '__|/ _` || |_ | __|/ _ \| '__|/ __|
remote: / /___| (_) || (_| || __// /___| | | (_| || _|| |_| __/| | \__
remote: \____/ \___/ \__,_| \___|\____/|_| \__,_||_| \__|\___||_| |___/
remote:
remote:
remote: Welcome to CodeCrafters! Your commit was received successfully.
remote:
remote: ------------------------------------------------------------------------
remote:
remote: Running tests on your codebase. Streaming logs...
remote:
remote: [compile] [INFO] Scanning for projects...
remote: [compile] [INFO]
remote: [compile] [INFO] ----------------< io.codecrafters:build-your-own-http >-----------------
remote: [compile] [INFO] Building build-your-own-http 1.0
remote: [compile] [INFO] from pom.xml
remote: [compile] [INFO] --------------------------------[ jar ]---------------------------------
remote: [compile] [INFO]
remote: [compile] [INFO] --- resources:3.3.1:resources (default-resources) @ build-your-own-http ---
remote: [compile] [INFO] skip non existing resourceDirectory /app/src/main/resources
remote: [compile] [INFO]
remote: [compile] [INFO] --- compiler:3.11.0:compile (default-compile) @ build-your-own-http ---
remote: [compile] [INFO] Changes detected - recompiling the module! :source
remote: [compile] [INFO] Compiling 1 source file with javac [debug target 21] to target/classes
remote: [compile] [INFO]
remote: [compile] [INFO] --- resources:3.3.1:testResources (default-testResources) @ build-your-own-http ---
remote: [compile] [INFO] skip non existing resourceDirectory /app/src/test/resources
remote: [compile] [INFO]
remote: [compile] [INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ build-your-own-http ---
remote: [compile] [INFO] No sources to compile
remote: [compile] [INFO]
remote: [compile] [INFO] --- surefire:3.1.2:test (default-test) @ build-your-own-http ---
remote: [compile] [INFO] No tests to run.
remote: [compile] [INFO]
remote: [compile] [INFO] --- jar:3.3.0:jar (default-jar) @ build-your-own-http ---
remote: [compile] [INFO] Building jar: /app/target/build-your-own-http-1.0.jar
remote: [compile] [INFO]
remote: [compile] [INFO] --- assembly:3.6.0:single (make-assembly) @ build-your-own-http ---
remote: [compile] [INFO] Building jar: /tmp/codecrafters-http-target/java_http.jar
remote: [compile] [WARNING] Configuration option 'appendAssemblyId' is set to false.
remote: [compile] Instead of attaching the assembly file: /tmp/codecrafters-http-target/java_http.jar, it will become the file for main project artifact.
remote: [compile] NOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic!
remote: [compile] [WARNING] Replacing pre-existing project main-artifact file: /app/target/build-your-own-http-1.0.jar
remote: [compile] with assembly file: /tmp/codecrafters-http-target/java_http.jar
remote: [compile] [INFO] ------------------------------------------------------------------------
remote: [compile] [INFO] BUILD SUCCESS
remote: [compile] [INFO] ------------------------------------------------------------------------
remote: [compile] [INFO] Total time: 2.214 s
remote: [compile] [INFO] Finished at: 2024-02-24T10:13:50Z
remote: [compile] [INFO] ------------------------------------------------------------------------
remote: [compile] Compilation successful.
remote:
remote: [stage-1] Running tests for Stage #1: Bind to a port
remote: [stage-1] Connecting to localhost:4221 using TCP
remote: [your_program] Logs from your program will appear here!
remote: [stage-1] Success! Closing connection
remote: [stage-1] Test passed.
remote:
remote: [stage-2] Running tests for Stage #2: Respond with 200
remote: [stage-2] You can use the following curl command to test this locally
remote: [stage-2] $ curl -v -X GET http://localhost:4221/
remote: [stage-2] Sending request (status line): GET / HTTP/1.1
remote: [your_program] Logs from your program will appear here!
remote: [stage-2] Test passed.
remote:
remote: All tests ran successfully. Congrats!
remote:
remote: View instructions for the next stage: https://app.codecrafters.io/courses/http-server
remote:
To https://git.codecrafters.io/XXXXXXXXXXXXXXXX
8489766..cbaf07a master -> master
テストをパスすると「Your Task」の欄に「Completed」と表示され、「View Next Stage →」のボタンが表示されます。
「Respond with 200」のすべてのステップの対応が完了すると画面上段に「Completed」と表示され、「View next stage →」のボタンが表示されます。
画面左側のメニューの「Respond with 200」に✅が表示されます。
画面上段もしくは「Your Task」の欄の「View Next Stage →」をクリックします。
「Respond with 404」のタスク
「Respond with 404」の画面に遷移します。ここで、「This stage requires a CodeCrafters Membership.」と表示され、有料会員になることが求められます。
ということで、ここから以降はそこそこの料金を支払う必要があるようです。
せっかくなので、「Respond with 404」以降のタスクの内容だけでも確認しましょう。
「Respond with 404」の「Your Task」を参照します。
このステージで行うべきタスクの内容は以下のとおりです。
- HTTPリクエストのリクエストライン(例:
GET /index.html HTTP/1.1
)からパス部分を抽出します。 - 条件に合致する場合、HTTPレスポンスとして以下を返します。
- HTTPメソッドが
GET
の場合- パスが
/
の場合HTTP/1.1 200 OK
- パスが
/
以外の場合HTTP/1.1 404 Not Found
- パスが
- HTTPメソッドが
-
Host: localhost:4221
とUser-Agent: curl/7.64.1
はリクエストヘッダーです。(今回のステージでは利用しません)
「Respond with content」のタスク
「Respond with content」の「Your Task」を参照します。
このステージで行うべきタスクの内容は以下のとおりです。
- ここまでのステージではHTTPレスポンスとしてステータスラインのみを返していましたが、このステージではbodyも返します。
- HTTPリクエストのリクエストライン(例:
GET /echo/abc HTTP/1.1
)からパス部分を抽出します。 - 条件に合致する場合、HTTPレスポンスとして以下を返します。
- HTTPメソッドが
GET
の場合- パスが
/echo/<ランダムな文字列>
の場合、/echo/
以降の<ランダムな文字列>
の部分をbodyとして返します。HTTP/1.1 200 OK Content-Type: text/plain Content-Length: <ランダムな文字列>に応じたサイズ <ランダムな文字列>
- パスが
- HTTPメソッドが
「Parse headers」のタスク
「Parse headers」の「Your Task」を参照します。
このステージで行うべきタスクの内容は以下のとおりです。
- HTTPリクエストのリクエストライン(例:
GET /user-agent HTTP/1.1
)からパス部分を抽出します。 - 条件に合致する場合、HTTPレスポンスとして以下を返します。
- HTTPメソッドが
GET
の場合- パスが
/user-agent
の場合- リクエストヘッダーに
User-Agent
を含む場合、User-Agent
の値をbodyとして返します。HTTP/1.1 200 OK Content-Type: text/plain Content-Length: <User-Agent>の値に応じたサイズ <User-Agent>の値
- リクエストヘッダーに
- パスが
- HTTPメソッドが
「Concurrent connections」のタスク
「Concurrent connections」の「Your Task」を参照します。
このステージで行うべきタスクの内容は以下のとおりです。
- ここまでのステージでは、1つの接続(HTTPリクエスト)に対してのみ、HTTPレスポンスを返すように実装してきました。
- このステージでは複数同時接続を考慮し、HTTPリクエストが複数来てもそれぞれにHTTPレスポンスを返すように実装します。
「Get a file」のタスク
「Get a file」の「Your Task」を参照します。
このステージで行うべきタスクの内容は以下のとおりです。
- テストでは、「
./your_server.sh --directory <ディレクトリ名>
」のようにプログラムを実行します。 - HTTPリクエストのリクエストライン(例:
GET /files/ファイル名 HTTP/1.1
)からパス部分を抽出します。 - 条件に合致する場合、HTTPレスポンスとして以下を返します。
- HTTPメソッドが
GET
の場合- パスが
/files/<ファイル名>
の場合- 対象ファイルが
--directory <ディレクトリ名>
で指定されたディレクトリ内に存在する場合HTTP/1.1 200 OK Content-Type: application/octet-stream Content-Length: 対象ファイルのサイズ 対象ファイルの内容
- 対象ファイルが
--directory <ディレクトリ名>
で指定されたディレクトリ内に存在しない場合HTTP/1.1 404 Not Found
- 対象ファイルが
- パスが
- HTTPメソッドが
「Post a file」のタスク
「Post a file」の「Your Task」を参照します。
このステージで行うべきタスクの内容は以下のとおりです。
- テストでは、「
./your_server.sh --directory <ディレクトリ名>
」のようにプログラムを実行します。 - HTTPリクエストのリクエストライン(例:
POST /files/ファイル名 HTTP/1.1
)からパス部分を抽出します。 - 条件に合致する場合、HTTPレスポンスとして以下を返します。
- HTTPメソッドが
POST
の場合- パスが
/files/<ファイル名>
の場合- 対象ファイルを
--directory <ディレクトリ名>
で指定されたディレクトリ内に保存する。 - ファイルの保存に成功したら以下を返す。
HTTP/1.1 201 Created Content-Type: application/octet-stream Content-Length: 保存したファイルのサイズ 保存したファイルの内容
- 対象ファイルを
- パスが
- HTTPメソッドが
CodeCraftersをやってみた感想
有料版の壁の件を把握していなかったので、やる前の「HTTPサーバー作るぞ」という気持ちを打ち砕かれて、終盤はちょっと残念な感じになってしまいましたが、最後にCodeCraftersをやってみた感想を少しだけ。
今回は「Build your own HTTP server」を触ってみましたが、普段仕事で利用しているHTTPサーバーなどの仕組みを知るきっかけとしては、CodeCraftersはとても良い教材だと思いました。
もちろん、「Build your own HTTP server」の各ステージをクリアしただけでは、「HTTPサーバー完全に理解した」という域に達することにはなりませんが、こういった複雑で難しそうなアプリケーションも小さな機能の集合体なので、少しずつ理解を深めていくきっかけになるのではないでしょうか。
ということで、CodeCraftersには様々な言語とアプリケーションを学べるように準備されていますので、ぜひチャレンジしてみてください。