# web server 筆記
## 使用的框架
伺服器使用 Nginx
前端使用 react, node.js, npm, JS語言
後端使用 flask
## Flask相關指令
開始 Flask
```
sudo systemctl start flask.service
```
開機啟動 Flask
```
sudo systemctl enable flask.service
```
查看 Flask 狀態
```
sudo systemctl status flask.service
```
重啟 Flask
```
sudo systemctl restart flask.service
```
使用 flask 啟動程序
```
flask run
flask run --debug
flask run --host=0.0.0.0 --port=5000
```
`sudo systemctl daemon-reload`
你新增或刪除了 Systemd 的服務文件後需要重須啟動。
注意:這不會立即啟動或重啟服務,只是讓 Systemd 更新服務的配置。
`sudo lsof -i :5000`
查看在 Port 5000 上運行的服務
### Notice
不管何時,如果你嘗試 debug Flask Server。使用 curl 去嘗試是個好主意。
如果跑在Port 5000,通過本地訪問
```
curl http://127.0.0.1:5000
```
如果使用 Nginx 反向代理,使用
```
curl http://141.147.150.224/service5000/
```
另一個例子
```
curl http://141.147.150.224/service5000/api/get_dashboard_data
```
嘗試重開
```
sudo systemctl restart flask.service
```
### 配置後台運行
```
sudo vim /etc/systemd/system/flask.service
````
:::success
```
[Unit]
Description=Flask App
After=network.target
[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu
ExecStart=/usr/bin/python3 /home/ubuntu/app.py
Restart=always
[Install]
WantedBy=multi-user.target
```
:::
然後重開
```
sudo systemctl daemon-reload
sudo systemctl restart flask.service
```
### `python3 app.py`
當 Server 出現問題時,無法跑起來。可以手動跑跑看,這樣會出現錯誤信息。
## react 指令
### 套件 `create-react-app`
可以幫你生出一套框架,並安裝一些東西。
## 各種安裝指令
安裝 Flask
```
pip install flask flask-cors
```
安裝 react 的 axios,一個Http庫
```
npm install axios
```
## 防火牆指令
允許Port 5000
```
sudo ufw allow 5000
```
不允許 Port 5000
```
sudo ufw deny 5000
```
查看防火牆
```
sudo ufw status
```
重啟防火牆
```
sudo ufw reload
```
## Nginx 安裝
```
sudo apt update && sudo apt upgrade -y
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
```
## 啟動 pyhton 虛擬環境
```
sudo apt install python3-venv
source venv/bin/activate
python3 -m venv venv
```
最後一個venv是名稱,可以自己改。
## Nodejs 安裝
安裝 Node Package Manager
```
sudo apt install npm
node -v
建議版本要是Node 14 or Higher。
npm -v
```
更新 Node.js
```
sudo apt update
sudo apt upgrade
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
node -v
npm -v
```
`npm install react-router-dom`
路由解決方案,用於解決頁面切換
```
npm install @tanstack/react-query --legacy-peer-deps
npm install @tanstack/react-query-devtools --legacy-peer-deps
```
安裝 React Query
## nodejs 指令
```
sudo npm isntall
```
sudo npm install 會尋找文件 package.json 去下載。
```
npm run build
```
使用 npm run build 來構件靜態網站,類似於編譯。
```
sudo chown -R $USER:$USER ~/.npm
```
修改 ~/.npm 權限,從root擁有變為$USER擁有
固定會議室
https://meet.google.com/aas-rfvw-afo
觀測cpu
cat /proc/cpuinfo | grep "MHz"
watch -n 1 "grep 'MHz' /proc/cpuinfo"
## 框架內容
`package.json`
一份 json文件,有一些配置資料。使用 `npm install`來安裝配置。
`package-lock.json`
一份18k行的json文件,儲存套件資料。
`public/index.html`
主要的html。
`src/index.js`
使用了 App, styles.css 的文件。
`src/styles.css`
一個 css 設定檔。
`src/App.js`
src/components/FileUpload.js
## 以下未整理
伺服器傳送
const exectureable = [
{ title: 'Cabbage', executable_name: 'Asd', input_num: 3 },
];
伺服器接收
const exectureable = [
{ executable_name: 'Asd', input_num: 3, input_data1: 1, input_data2: 2, input_data3: 3 },
];
# 變成 string
```
<pre>{JSON.stringify(data, null, 2)}<\pre>
<script>
async function fetchData() {
try {
const response = await fetch("http://141.147.150.224/service5000/api/data");
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
document.getElementById("output").innerText = data.message;
} catch (error) {
document.getElementById("output").innerText = `Error: ${error.message}`;
}
}
</script>
```
與伺服器進行數據傳輸的函數的命名規則
get 取得
fetch 取得
post 提交
update 更新
delete 刪除
/api/save_dashboard_data
/api/get_dashboard_data
/api/upload_executable
使用 curl
server接收
```
curl -X POST -H "Content-Type: application/json" \
-d '{"key": "value"}' \
http://localhost:5000/save_dashboarddata
```
server傳送
```
curl http://localhost/service5000/api/get_dashboard_data
```
後端api驗證用戶
const handleLogin = async () => {
const response = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
});
const data = await response.json();
if (response.ok && data.token) {
localStorage.setItem('token', data.token); // 保存 token
navigate('/dashboard');
} else {
alert('Login Failed');
}
};
Mutation更新數據
import React from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
const postData = async (newData) => {
const response = await fetch('/api/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newData),
});
if (!response.ok) {
throw new Error('Failed to post data');
}
return response.json();
};
const AddDataButton = () => {
const queryClient = useQueryClient();
const mutation = useMutation(postData, {
onSuccess: () => {
queryClient.invalidateQueries(['serverData']); // 更新數據後重新拉取
},
});
const handleClick = () => {
mutation.mutate({ name: 'New Item' });
};
return (
<button onClick={handleClick} disabled={mutation.isLoading}>
{mutation.isLoading ? 'Adding...' : 'Add Data'}
</button>
);
};
export default AddDataButton;
當前的組件和函數
<FileUpload SERVER_IP={SERVER_IP} />
const postData = async (url, newData) => {
const AddExecutableButton = () => {
const DashboardPage = () => {
async function fetchDashboardData () {
const LoginPage = () => {
const dashboard_component = ({ title, executable_name, input_num }) => {
一開始會到login page
然後到dashboard,dashboard會請求資料,並使用dashboard_component和FileUpload渲染。
當點擊FileUpload,進入新畫面,有Title,輸入框,參數數量,輸入框,可執行檔路徑,傳送資料