uWebSockets.js 框架经验

目录结构

project/
│
├── src/
│      ├── app.ts
│      ├── routes/
│      │      ├── userRoutes.ts
│      │      └── index.ts
│      ├── entities/
│      │      └── User.ts
│      ├── utils/
│      │      └── parseQuery.ts
│      └── index.ts
│
├── ormconfig.json
└── package.json

User 实体 (User.ts)

//  src/entities/User.ts

import  {  Entity,  PrimaryGeneratedColumn,  Column  }  from  'typeorm';

@Entity()
export  class  User  {
      @PrimaryGeneratedColumn()
      id:  number;

      @Column()
      name:  string;

      @Column()
      email:  string;
}

ORM 配置 (ormconfig.json)

//  ormconfig.json

{
      "type":  "postgres",
      "host":  "localhost",
      "port":  5432,
      "username":  "postgres",
      "password":  "password",
      "database":  "test",
      "entities":  ["src/entities/*.ts"],
      "synchronize":  true
}

请求参数解析函数 (parseQuery.ts)

//  src/utils/parseQuery.ts

export  const  parseQuery  =  (req:  any):  Promise<any>  =>  {
      return  new  Promise((resolve,  reject)  =>  {
          let  body  =  '';
          req.on('data',  (chunk:  string)  =>  {
              body  +=  chunk;
          });
          req.on('end',  ()  =>  {
              try  {
                  const  params  =  JSON.parse(body);
                  resolve(params);
              }  catch  (error)  {
                  reject(new  Error('Failed  to  parse  request  body'));
              }
          });
      });
};

路由处理函数 (userRoutes.ts)

//  src/routes/userRoutes.ts

import  {  User  }  from  '../entities/User';
import  {  Connection  }  from  'typeorm';
import  {  parseQuery  }  from  '../utils/parseQuery';

export  const  userRoutes  =  (dbConnection:  Connection)  =>  ({
      '/user':  {
          POST:  (res,  req)  =>  {
              parseQuery(req).then(async  (params)  =>  {
                  try  {
                      const  user  =  new  User();
                      user.name  =  params.name;
                      user.email  =  params.email;
                      await  dbConnection.manager.save(user);
                      res.end(JSON.stringify(user));
                  }  catch  (error)  {
                      res.writeStatus('500  Internal  Server  Error').end(error.message);
                  }
              }).catch(error  =>  {
                  res.writeStatus('400  Bad  Request').end(error.message);
              });
          },
          //  其他处理函数...
      },
      //  其他路由和对应的处理函数...
});

路由入口 (index.ts)

//  src/routes/index.ts

import  {  userRoutes  }  from  './userRoutes';
//  可以在这里导入其他路由模块

export  const  routes  =  (dbConnection:  Connection)  =>  ({
      ...userRoutes(dbConnection),
      //  ...其他路由模块
});

uWebSockets.js 应用 (app.ts)

//  src/app.ts

import  {  create  }  from  'uWebSockets.js';
import  {  Connection,  createConnection  }  from  'typeorm';
import  {  routes  }  from  './routes';
import  {  parseQuery  }  from  './utils/parseQuery';

let  dbConnection:  Connection;

createConnection().then(async  connection  =>  {
      dbConnection  =  connection;
      console.log('Connected  to  the  database');

      const  app  =  create({
          keyFile:  './ssl/key.pem',
          certFile:  './ssl/cert.pem',
      });

      //  设置路由
      const  routeHandlers  =  routes(dbConnection);
      for  (const  route  in  routeHandlers)  {
          for  (const  method  in  routeHandlers[route])  {
              app[method.toLowerCase()](route,  routeHandlers[route][method]);
          }
      }

      app.listen(3000,  token  =>  {
          if  (token)  {
              console.log('Listening  to  port  3000');
          }  else  {
              console.log('Failed  to  listen  to  port  3000');
          }
      });
});

主入口文件 (index.ts)

//  src/index.ts

import  './app';  //  引入主应用文件

//  这个文件可以留空,或者添加一些其他的逻辑

定时事务

//  src/utils/timedTransactions.ts

export  function  startTimedTransactions()  {
      //  每6秒执行一次的事务
      setInterval(()  =>  {
          //  这里调用你的事务处理函数
          console.log('Running  6-second  transaction');
          //  runSixSecondTransaction();
      },  6000);

      //  每33分钟执行一次的事务
      setInterval(()  =>  {
          //  这里调用你的事务处理函数
          console.log('Running  33-minute  transaction');
          //  runThirtyThreeMinuteTransaction();
      },  33  *  60  *  1000);

      //  每天早上1点到5点之间执行的事务
      const  now  =  new  Date();
      const  todayMidnight  =  new  Date(now.getFullYear(),  now.getMonth(),  now.getDate(),  0,  0,  0);
      const  nextRun  =  new  Date(todayMidnight.getTime()  +  (now.getHours()  >=  1  &&  now.getHours()  <  5  ?  0  :  1)  *  24  *  60  *  60  *  1000);

      setTimeout(()  =>  {
          //  这里调用你的事务处理函数
          console.log('Running  daily  transaction');
          //  runDailyTransaction();

          //  设置第二天的时间
          const  tomorrowMidnight  =  new  Date(todayMidnight.getTime()  +  24  *  60  *  60  *  1000);
          setInterval(()  =>  {
              //  这里调用你的事务处理函数
              console.log('Running  daily  transaction');
              //  runDailyTransaction();
          },  tomorrowMidnight.getTime()  -  todayMidnight.getTime());
      },  nextRun.getTime()  -  now.getTime());
}

跨域处理
在uWebSockets.js中,跨域可以通过设置响应头来处理。

//  设置跨域
function  setCrossDomainHeaders(res:  any)  {
      res.writeHeader('Access-Control-Allow-Origin',  '*');
      res.writeHeader('Access-Control-Allow-Methods',  'GET,POST,PUT,DELETE,OPTIONS');
      res.writeHeader('Access-Control-Allow-Headers',  'Content-Type,  Authorization');
}

//  在app.ts中使用
app.options('/user',  (res,  req)  =>  {
      setCrossDomainHeaders(res);
      res.end();  //  对于OPTIONS请求,结束响应
});

Token验证中间件
中间件可以通过拦截请求并在传递给路由处理程序之前执行一些逻辑来实现。

//  src/middlewares/tokenValidator.ts

export  function  tokenValidator(req:  any,  res:  any,  next:  Function)  {
      const  token  =  req.getHeader('Authorization');
      if  (!token)  {
          res.writeStatus('401  Unauthorized').end('Access  denied');
          return;
      }

      //  假设我们有解析token的函数,这里获取用户信息
      //  const  userInfo  =  decodeToken(token);
      const  userInfo  =  {  id:  'user123',  name:  'John  Doe'  };  //  假的用户信息
      req.userInfo  =  userInfo;  //  将用户信息附加到请求对象

      next();  //  调用下一个中间件或路由处理程序
}

将所有内容整合到app.ts

//  src/app.ts

import  {  create  }  from  'uWebSockets.js';
import  {  Connection,  createConnection  }  from  'typeorm';
import  {  routes  }  from  './routes';
import  {  parseQuery  }  from  './utils/parseQuery';
import  {  tokenValidator  }  from  './middlewares/tokenValidator';
import  {  startTimedTransactions  }  from  './utils/timedTransactions';

let  dbConnection:  Connection;

createConnection().then(async  connection  =>  {
      dbConnection  =  connection;
      console.log('Connected  to  the  database');

      const  app  =  create({
          keyFile:  './ssl/key.pem',
          certFile:  './ssl/cert.pem',
      });

      //  设置路由,使用中间件进行token验证
      const  routeHandlers  =  routes(dbConnection);
      for  (const  route  in  routeHandlers)  {
          for  (const  method  in  routeHandlers[route])  {
              const  originalHandler  =  routeHandlers[route][method];
              routeHandlers[route][method]  =  (res,  req)  =>  {
                  tokenValidator(req,  res,  ()  =>  originalHandler(res,  req));
              };
          }
      }

      //  设置跨域
      app.any('/*',  (res,  req)  =>  {
          setCrossDomainHeaders(res);
          //  继续处理请求
          app.run(req,  res);
      });

      //  设置路由
      for  (const  route  in  routeHandlers)  {
          for  (const  method  in  routeHandlers[route])  {
              app[method.toLowerCase()](route,  routeHandlers[route][method]);
          }
    

      app.listen(3000,  token  =>  {
          if  (token)  {
              console.log('Listening  to  port  3000');
          }  else  {
              console.log('Failed  to  listen  to  port  3000');
          }
      });
});

 安装所需的依赖项

npm  install  uwebsockets.js  typeorm  mysql  reflect-metadata

安装和部署

git  clone  https://github.com/uNetworking/uWebSockets.git
cd  uWebSockets

npm  install
npm  run  build

"dependencies":  {
      "uwebsockets.js":  "file:./path/to/uWebSockets.js"
}

FROM  node:latest

#  设置工作目录
WORKDIR  /usr/src/app

#  复制项目文件
COPY  .  .

#  安装依赖项(如果使用  npm  包管理器)
RUN  npm  install  --silent

#  暴露端口
EXPOSE  3000

#  启动应用
CMD  [  "node",  "your-app.js"  ]

 


































posted @ 2024-01-19 21:07  pearlcity  阅读(100)  评论(0编辑  收藏  举报