0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rustを使ってサーバーを構築する!

Posted at

nodejsでもやったから次はRustどと思いました
環境:
OS: MacOS
editor: vscode

同じWiFiにつながってないと他のパソコンや端末からアクセスできません!

デレクトリ

.
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
└── static
    └── index.html

3 directories, 4 files

コード

cargo new server
cargo.toml
[package]
name = "Server"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
warp = "0.3"
tokio = { version = "1", features = ["full"] }

main.rs
use warp::Filter;
use std::{sync::{Arc, Mutex}, time::Duration};
use tokio::time::interval;

#[tokio::main]
async fn main() {
    // isSelectedの状態を保持する
    let is_running = Arc::new(Mutex::new(false));
    
    // HTMLファイルを読み込む
    let html = std::fs::read_to_string("static/index.html").expect("HTMLファイルが見つかりません");

    // GETリクエスト用のフィルター
    let get_route = warp::path::end()
        .map(move || warp::reply::html(html.clone()));

    // POSTリクエスト用のフィルター
    let post_route = warp::path("toggle")
        .and(warp::post())
        .and(warp::body::json())
        .map({
            let is_running = Arc::clone(&is_running);
            move |body: std::collections::HashMap<String, bool>| {
                let is_selected = body.get("isSelected").copied().unwrap_or(false);
                let mut running = is_running.lock().unwrap();
                
                if is_selected && !*running {
                    *running = true;
                    println!("処理を開始します...");
                    tokio::spawn({
                        let is_running = Arc::clone(&is_running);
                        async move {
                            let mut interval = interval(Duration::from_secs(1));
                            while *is_running.lock().unwrap() {
                                interval.tick().await;
                                println!("処理中...");
                            }
                        }
                    });
                } else if !is_selected && *running {
                    *running = false;
                    println!("処理を停止します...");
                }

                warp::reply::json(&"State received")
            }
        });

    // ルートを結合
    let routes = get_route.or(post_route);
    
    let addr = ([127, 0, 0, 1], 8000); // ここで addr を定義
    println!("Server running on http://{}", format!("{}:{}", addr.0.iter().map(|b| b.to_string()).collect::<Vec<_>>().join("."), addr.1));
    // サーバーを起動
    warp::serve(routes).run(([127, 0, 0, 1], 8000)).await;
    
}

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>遠隔操作ボタン</title>
    <style>
        body {
            background-color: #1a1a1a;
            color: #fff;
            font-family: 'Arial', sans-serif;
            overflow: hidden;
        }

        .center {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            position: relative;
        }

        .toggle-btn {
            background-color: #007bff;
            color: #fff;
            padding: 15px 30px;
            border: none;
            border-radius: 10px;
            cursor: pointer;
            font-size: 1.5em;
            position: relative;
            outline: none;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);
            transition: transform 0.3s;
            z-index: 1;
        }

        .selected {
            background-color: #26ff00;
            animation: glow 1s infinite alternate;
        }

        @keyframes glow {
            from {
                box-shadow: 0 0 20px rgba(47, 255, 0, 0.5);
            }
            to {
                box-shadow: 0 0 40px rgb(94, 255, 0);
            }
        }

        .error-message {
            color: rgb(115, 255, 0);
            font-weight: bold;
            position: absolute;
            top: 0; /* ボタンの上に表示 */
            left: 50%;
            transform: translateX(-50%);
            display: none; /* 初期は非表示 */
            z-index: 2;
        }
        .server-message {
            color: blue;
            font-weight: bold;
            position: absolute;
            top: 0; /* ボタンの上に表示 */
            left: 50%;
            transform: translateX(-50%);
            display: none; /* 初期は非表示 */
            z-index: 2;
        }

        .server_err {
            background-color: rgb(251, 59, 59);
            color: #fff;
            padding: 15px 30px;
            border: none;
            border-radius: 10px;
            /*cursor: pointer;*/
            font-size: 1.5em;
            position: relative;
            outline: none;
            /*box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);*/
            transition: transform 0.3s;
            z-index: 1;
        }
        .server_sf {
            background-color: rgb(78, 99, 255);
            color: #fff;
            padding: 15px 30px;
            border: none;
            border-radius: 10px;
            /*cursor: pointer;*/
            font-size: 1.5em;
            position: relative;
            outline: none;
            /*box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);*/
            transition: transform 0.3s;
            z-index: 1;
        }
    </style>
</head>
<body>
    <div class="center">
        <div class="server_sf" id="serverMessage">安全</div>
        <div class="server_err" id="errorMessage">エラー</div>
        <button class="toggle-btn" id="toggleButton">実行</button>
    </div>

    <script>
        const button = document.getElementById('toggleButton');
        const errorMessage = document.getElementById('errorMessage');
        const serverMassage = document.getElementById('serverMessage');
        let isSelected = false;

        errorMessage.style.display = 'none'; // 正常な応答時にエラーメッセージを非表示
        serverMassage.style.display = 'block'; // 正常な応答時にエラーメッセージを非表示

        button.addEventListener('click', () => {
            isSelected = !isSelected;
            button.classList.toggle('selected', isSelected);
            button.textContent = isSelected ? "運転中..." : "実行";

            fetch('/toggle', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ isSelected })
            })
            .then(response => {
                console.log('サーバーの応答:', response); // サーバー応答のデバッグ
                if (!response.ok) {
                    throw new Error("サーバーの応答が不正です");
                }
                return response.json();
            })
            .then(data => {
                console.log('サーバーからの応答:', data);
                errorMessage.style.display = 'none'; // 正常な応答時にエラーメッセージを非表示
                serverMassage.style.display = 'block'; // 正常な応答時にエラーメッセージを非表示
            })
            .catch(error => {
                console.error('エラー:', error);
                console.error('サーバーからの応答')
                errorMessage.style.display = 'block'; // エラー時にエラーメッセージを表示
                serverMassage.style.display = 'none'; // 正常な応答時にエラーメッセージを非表示
            });
        });
    </script>
</body>
</html>

実行

cargo run

最後に

他のパソコンや端末でやてみたいと思うかもしれませんが、http://localhost:8000このURLを打ち込んでもうまくいきません!
ターミナルで

ifconfig

でわかります

% ifconfig   
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
	options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
	inet 127.0.0.1 netmask 0xff000000 <= この行!
	inet6 ::1 prefixlen 128 
	inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
	nd6 options=201<PERFORMNUD,DAD> ...

つまり他のパソコンや端末で動かすためには、
調べたやつ:127.0.0.1 :8000ということなのでhttp://127.0.0.1:8000に行けばうまくいきます

よくわからない時はGeminiChatGPTに聞くとわかったりします

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?