[Websersver]miniWebserver-(6)

๐Ÿ‘‰๐Ÿป ์ฃผ์š”๋ณ€๊ฒฝ ์‚ฌํ•ญ / Major changes

โœ”๏ธ ์ฝ”๋“œ์–‘์ด ๋งŽ์•„์ ธ์„œ ๋ฐ”๋€ ๋ถ€๋ถ„๋งŒ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
Since the amount of code has increased, I will only explain the parts that have changed.

โœ”๏ธ ์ปดํŒŒ์ผ์„ cmake๋กœ ๋ณ€๊ฒฝ
Change compilation to cmake

— g++ ๋กœ ์ปดํŒŒ์ผ ํ•˜๋Š” ๋ฐฉ์‹์—์„œ cmake๋ฅผ ํ†ตํ•ด์„œ ์ปดํŒŒ์ผ ํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.
I changed the compilation method from using g++ to using cmake.

— ์ปดํŒŒ์ผ ํ•ด์•ผํ•˜๋Š” ํŒŒ์ผ์˜ ์–‘์ด ๋งŽ๊ณ  ์™ธ๋ถ€๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค๋ฉด cmake๊ฐ€ ๋” ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.
If you have a large amount of files to compile and need to use external libraries, CMake is more efficient.

— cmake๋ฅผ ๋จผ์ € ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.(MacOS)

brew install cmake

— CMakeLists.txt ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  ์•„๋ž˜์˜ ๋‚ด์šฉ์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
Create a CMakeLists.txt file and write the following content.

# cmake์ตœ์†Œ๋ฒ„์ „์ง€์ • / Specify minimum CMake version
cmake_minimum_required(VERSION 3.10)

# ํ”„๋กœ์ ํŠธ ์ด๋ฆ„๊ณผ ๋ฒ„์ „ ์„ค์ • / Set project name and version
project(mini_webserver_6 VERSION 1.0)

# C++ ํ‘œ์ค€ ๋ฒ„์ „ ์ง€์ •(c++20) / C++ Standard Version Specification (C++20)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# ์‹คํ–‰ ํŒŒ์ผ ์ด๋ฆ„, ์†Œ์Šค ํŒŒ์ผ / Executable file name, source file
add_executable(main
    Main.cpp
    Router.cpp
    Server.cpp
)

โœ”๏ธ ํ—ค๋”์™€ ๋ฐ”๋”” ๋ฆฌํ„ด ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Added header and body return functionality

— server.cpp์—์„œ ์ฒ˜๋ฆฌํ•˜๋˜ ํ—ค๋”๋ฅผ main.cpp์—์„œ body์™€ header๋ฅผ ๊ฐ™์ด ๋„˜๊ฒจ ์ค๋‹ˆ๋‹ค.
The header that was handled in server.cpp is passed to main.cpp along with the body.

— main.cpp

    my_server.set_handler([&](const std::string& req) {

        // ๋ผ์šฐํ„ฐ๋กœ๋ถ€ํ„ฐ ๋งˆ์ž„ ํƒ€์ž…๊ณผ ๋ณธ๋ฌธ์„ ๋ฐ›์Œ
        // Receive MIME type and body from router
        auto [mime, body] = my_router.router(req);

        // HTTP ์‘๋‹ต ํ—ค๋” ์ƒ์„ฑ
        // Generate HTTP response headers
        std::string response = "HTTP/1.1 200 OK\r\n";
        response += "Content-Type: " + mime + "\r\n";
        response += "Content-Length: " + std::to_string(body.size()) + "\r\n";
        response += "Connection: close\r\n";
        response += "\r\n"; // ํ—ค๋”์™€ ๋ณธ๋ฌธ ๊ตฌ๋ถ„์ž / Header and body separator

        // ๋ณธ๋ฌธ ์ถ”๊ฐ€ / Add body
        response += body;

        // ์ตœ์ข… ์‘๋‹ต ๋ฐ˜ํ™˜ / Return final response
        return response;
    });

— server.cpp


void Server::handle_client(int client_socket) {

 // ... ์ค‘๋žต / Omitted ...

        // HTTP ํฌ๋งท ์‘๋‹ต
        // std::string response = "HTTP/1.1 200 OK\r\n"
        //                        "Content-Type: text/html; charset=utf-8\r\n"
        //                        "Content-Length: " + std::to_string(html_content.size()) + "\r\n"
        //                        "\r\n" + html_content;
        //
        // main.cpp์—์„œ ๋„˜์–ด์˜จ ํ—ค๋” ์ ์šฉโ—๏ธ
        // Apply header passed from main.cpp
        std::string response = html_content;

// ... ์ค‘๋žต / Omitted ...

}

โœ”๏ธ ์ •์ ํŒŒ์ผ ์„œ๋น™ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Added static file serving feature

— public๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์— html ํŒŒ์ผ์„ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
You can use HTML files inside the public directory.

— Router.cpp

std::pair<std::string, std::string> Router::router(const std::string& request) {

// ... ์ค‘๋žต / omitted ...

    std::string doc_root = "../public";
    std::string full_path = doc_root + path;

    // ๊ฒฝ๋กœ๊ฐ€ / ์ด๋ฉด index.html๋กœ ๋งคํ•‘
    // If the path is /, map to index.html

    if (path == "/") {
        full_path = doc_root + "/index.html";
    }else if(path == "/test1"){
        full_path = doc_root + "/test1.html";
    }else if(path == "/test2"){
        full_path = doc_root + "/test2.html";
    }else{
        full_path = doc_root + "/index.html";
    }
    if (!std::filesystem::exists(full_path)) {
        return {"text/html", "<h1 style='color:red;'>404 Not Found</h1>"};
    }
// ... ์ค‘๋žต / omitted ...

    // ํŒŒ์ผ ํ™•์žฅ์ž์— ๋”ฐ๋ฅธ ๋งˆ์ž„ํƒ€์ž… ์ง€์ •
    // Specify MIME type based on file extension
    std::string mime_type = "text/html; charset=UTF-8";
    if (full_path.ends_with(".css")) mime_type = "text/css";
    else if (full_path.ends_with(".js")) mime_type = "application/javascript";
    else if (full_path.ends_with(".json")) mime_type = "application/json";
    else if (full_path.ends_with(".png")) mime_type = "image/png";
    else if (full_path.ends_with(".jpg")) mime_type = "image/jpg";

}

โœ”๏ธ ๋นŒ๋“œ / build

MacBookAir build % cd ..  
MacBookAir mini_webserver_6 % cd build
MacBookAir build % cmake ..
-- Configuring done (0.1s)
-- Generating done (0.0s)
-- Build files have been written to: /Users/.../mini_webserver_6/build
MacBookAir build % make
[ 25%] Building CXX object CMakeFiles/main.dir/Main.cpp.o
[ 50%] Building CXX object CMakeFiles/main.dir/Router.cpp.o
[ 75%] Building CXX object CMakeFiles/main.dir/Server.cpp.o
[100%] Linking CXX executable main
[100%] Built target main
MacBookAir build % 

โœ”๏ธ ์‹คํ–‰ / Run

MacBookAir build % ./maiin

โœ”๏ธ ๋ธŒ๋ผ์šฐ์ € ์ ‘์† / Access Browser

http://localhost:5080

Leave a Reply