目录

基于Nginx轻量级嵌入式Web前后端框架搭建

基于Nginx轻量级嵌入式Web前后端框架搭建

基于Nginx轻量级嵌入式Web前后端框架搭建

1 项目概述

本项目基于Nginx和FastCGI实现了一个轻量级嵌入式Web前后端框架,支持用户权限管理、设备状态监控、远程控制等功能。前端采用TypeScript+HTML开发,后端使用C/C++实现,前后端通过FastCGI协议通信。

项目源码:

2 核心特性

a. 设备监控与控制(未实现)

  • 实时监控设备状态
  • 远程控制智能设备

b. 用户管理

  • 基于htpasswd的用户认证系统
  • 细粒度权限控制

c. 响应式设计(未实现)

  • 适配不同终端设备
  • 现代化UI交互体验

3 技术架构

3.1 前端技术栈

  • TypeScript
  • Webpack构建工具
  • Bootstrap响应式框架
  • FastCGI通信协议

3.2 后端技术栈

  • C/C++高性能实现
  • Nginx 1.14.0 Web服务器
  • FastCGI后端服务

4 开发环境配置

4.1 系统要求

  • CMake ≥ 3.10
  • GCC/G++编译器
  • Node.js ≥ 22.17.1
  • Nginx 1.14.0

4.2 环境初始化

# 安装基础依赖
sudo apt-get install libssl-dev

# 克隆项目
git clone https://gitcode.com/aiprtem_iot/tinyweb_nginx.git

# 设置环境变量
source envsetup

5 构建与部署

5.1 构建流程

a. 预构建依赖

meprebuild

b. 主构建

mebuild

c. 打包发布

mepack

d. 系统安装

sudo meinstall

PS: 程序会默认安装到“/opt/webserver/`目录下。

5.2 服务管理

启动服务

可以通过/opt/webserver/scripts/目录下的脚本启动服务。

# FastCGI后端
./fcgiServer.sh start

# Nginx前端
./nginxd.sh start

停止服务

./fcgiServer.sh stop
./nginxd.sh stop

6 开发指南

6.1 目录结构

tinyweb/       # 前端项目
webserver/     # 后端实现
├── doc/       # 文档
├── prebuilt/  # 预构建依赖
├── scripts/   # 服务控制脚本
├── src/       # 源代码
└── test/      # 测试代码

6.2 扩展开发

a. 新增API接口

  • webserver/src/中添加FastCGI处理模块
功能概述

b. 服务器初始化

  • 全局变量管理(如 cgi_sock)和信号处理(如 cleanup_handler)。
  • 支持守护进程和停止模式。

c. 请求处理

  • JSON 请求解析(如 web_process_login)。
  • 业务逻辑实现(登录等)。

d. 接口配置

  • 套接字路径(FCGI_SOCKET_PATH)。
  • 线程数和日志文件设置。
  • 更新Nginx配置

e. 前端功能扩展

  • tinyweb/src/中添加TypeScript模块
  • 通过Webpack打包

7 登录模块实现

7.1 接口设计

登录接口

// 从项目源码中提取的实际接口定义
{
  "path": "/api/v1/auth/login",
  "method": "POST",
  "request": {
    "username": "string",
    "password": "string"
  },
  "response": {
    "token": "string",
    "user": {
      "id": "string",
      "username": "string"
    }
  }
}

7.2 项目结构框图

部署模块

后端模块

前端模块

Nginx配置

静态文件服务

反向代理

login.ts

API路由

数据库交互

login.html

静态资源

Webpack打包

HTTP请求

响应数据

静态资源

API服务

反向代理

前端模块

后端模块

部署模块

用户访问

7.3 前端实现

登录页面(HTML)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户登录</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f5f5f5;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }
        .login-container {
            background: white;
            padding: 2rem;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
            width: 300px;
        }
        h1 {
            text-align: center;
            color: #333;
            margin-bottom: 1.5rem;
        }
        .form-group {
            margin-bottom: 1rem;
        }
        label {
            display: block;
            margin-bottom: 0.5rem;
            color: #555;
        }
        input {
            width: 100%;
            padding: 0.5rem;
            border: 1px solid #ddd;
            border-radius: 4px;
            box-sizing: border-box;
        }
        button {
            width: 100%;
            padding: 0.75rem;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 1rem;
        }
        button:hover {
            background-color: #45a049;
        }
        .error {
            color: red;
            margin-top: 1rem;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="login-container">
        <h1>用户登录</h1>
        <form id="loginForm">
            <div class="form-group">
                <label for="username">用户名</label>
                <input type="text" id="username" name="username" required>
            </div>
            <div class="form-group">
                <label for="password">密码</label>
                <input type="password" id="password" name="password" required>
            </div>
            <button type="submit">登录</button>
        </form>
        <div id="errorMessage" class="error"></div>
    </div>
    <!-- Script will be automatically injected by webpack -->
</body>
</html>

登录请求RESFUL API接口定义

api:/api/v1/auth/login

// 从tinyweb/src/login.ts提取的接口定义
interface LoginResponse {
    token: string;
    user: {
        id: string;
        username: string;
    };
}

登录表单实现(TypeScript)

// 从tinyweb/src/login.ts提取的核心逻辑
document.addEventListener('DOMContentLoaded', () => {
    const loginForm = document.getElementById('loginForm') as HTMLFormElement;
    
    loginForm.addEventListener('submit', async (e) => {
        e.preventDefault();
        
        const username = (document.getElementById('username') as HTMLInputElement).value;
        const password = (document.getElementById('password') as HTMLInputElement).value;

        const response = await fetch('/api/v1/auth/login', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ username, password })
        });

        if (response.ok) {
            const data: LoginResponse = await response.json();
            localStorage.setItem('authToken', data.token);
            window.location.href = 'index.html';
        }
    });
});

7.4 后端实现

7.4.1 FastCGI 服务器初始化
#include "fcgi_server.h"

int cgi_sock = -1;
int daemon_mode = 0;  // 默认不以守护进程方式运行
int stop_mode = 0;    // 默认不是停止模式

#define PID_FILE "/tmp/fcgiserver.pid"

// Signal handler to clean up socket file on exit
void cleanup_handler(int sig) {
    log_info("Received signal %d, cleaning up and exiting...", sig);
    if (cgi_sock >= 0) {
        close(cgi_sock);
        cgi_sock = -1;
    }
    unlink(FCGI_SOCKET_PATH);
    unlink(PID_FILE);  // 删除PID文件
    log_info("Cleanup complete, exiting");
    exit(0);
}
7.4.2 请求处理逻辑
#include "web_login.h"

void web_process_login(fcgxEnvParams *envParams, char *recvBuf, int len) {
    // 解析 JSON 请求
    struct json_object *infor_object = json_object_new_object();
    if (NULL == infor_object) {
        log_error("Failed to create JSON object");
        return;
    }

    // 处理登录逻辑
    // ...
}
7.4.3 与前端交互的接口定义
#define FCGI_SOCKET_PATH     "/var/run/fcgiserver.sock"
#define CGI_THREAD_NUM  4

#define FCGI_SERVER_LOG_FILE_NAME "/tmp/fcgi_server.log"

#define FCGX_URL_STRING_MAX_LEN   10240

**FastCGI处理模块

功能概述
  1. 服务器初始化

    • 全局变量管理(如 cgi_sock)和信号处理(如 cleanup_handler)。
    • 支持守护进程和停止模式。
  2. 请求处理

    • JSON 请求解析(如 web_process_login)。
    • 业务逻辑实现(登录等)。
  3. 接口配置

    • 套接字路径(FCGI_SOCKET_PATH)。
    • 线程数和日志文件设置。©**

8 最佳实践

a. 嵌入式适配

  • 修改webserver/toolchain.cmake配置交叉编译
  • 优化Nginx配置减少内存占用

b. 性能调优

  • 启用FastCGI连接池
  • 优化SQL查询

9 常见问题

Q: 如何添加新用户?

cd /opt/webserver/bin
./htpasswd -c /root/.webserver/htpasswd 用户名

Q: 如何调试FastCGI服务?

  • 启用debug日志级别
  • 使用gdb附加到fcgi进程