写点什么

与前端训练营的日子 -- Week19

用户头像
SamGo
关注
发布于: 2021 年 03 月 12 日

不知不觉已经到了最后两周的学习任务了,其实原本这周就要结束训练营的课程的,但春节多给了一周的学习时间,所以这周是 Week 19。其实我也打算这周把 Week 20 的学习任务也完成了(因为 Week 20 的课程已经解锁了),但周末有约🤣,看情况吧,尽力周日也把 Week 20 的学习任务也完成了。


课程发布系统结构图:

利用 Express,实现一个简单的 Server(静态服务器)

以下命令在终端操作


mkdir server ## 创建一个文件夹,名为servercd server ## 进入server文件夹目录npx express-generator ## 通过express-generator进行初始化项目(注意当前路径是在server文件夹目录下)npm install ## 安装需要的依赖(注意当前路径是在server文件夹目录下)
复制代码


准备工作完成后,可以将server文件夹里的routesview文件夹以及app.js里的相关代码删除,只需要利用public文件夹的代码就可以完成一个简单的 Server 工作了,一个纯粹的静态服务器。这 Server 负责线上服务。


app.js删除相关代码后的完整代码如下:


var createError = require('http-errors');var express = require('express');var path = require('path');var cookieParser = require('cookie-parser');var logger = require('morgan');
var app = express();
app.use(logger('dev'));app.use(express.json());app.use(express.urlencoded({ extended: false }));app.use(cookieParser());app.use(express.static(path.join(__dirname, 'public')));
// catch 404 and forward to error handlerapp.use(function(req, res, next) { next(createError(404));});
// error handlerapp.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page res.status(err.status || 500); res.render('error');});
module.exports = app;
复制代码


app.js处理完后,基本不需要再修改就可以满足本周学习任务了。

实现一个 Publish-Server

Publish-Server 负责接收客户端(publish-tool)发送的文件以及将文件复制到线上服务器的工作。

server.js部分代码

let http = require("http");let unzipper = require("unzipper");
http.createServer(function (request, response) { // 解压文件并复制到本地服务器,注意这是测试整个发布链路 request.pipe(unzipper.Extract({ path: '../server/public/' }));}).listen(8082);
复制代码

实现 Publish-Tool

Publish-Server 负责将项目文件(多文件会进行压缩)发送到 Publish-Server。


publish.js部分代码

let http = require("http");let archiver = require("archiver");
let request = http.request({ hostname: "127.0.0.1", port: 8082, method: "POST", headers: { 'Content-Type': 'application/octet-stream', }}, response => { console.log(response);});
const archive = archiver('zip', { zlib: { level: 9 } // Sets the compression level.});
archive.directory('./sample/', false);archive.finalize();archive.pipe(request);
复制代码

通过 Github OAuth 实现一个登录实例


改造server.js

let http = require("http");let https = require("https");let unzipper = require("unzipper");let querystring = require('querystring');
// 2. auth路由:接收code,用code+client_id+client_secret请求获得token
function auth(request, response) { let query = querystring.parse(request.url.match(/^\/auth\?([\s\S]+)$/)[1]); getToken(query.code, function (info) { // 通过<a></a>标签将标签回传给publish-tool response.write(`<a href='http://localhost:8083/?token=${info.access_token}'>publish</a>`) response.end(); });}
function getToken(code, callback) { // 省略部分代码 let request = https.request({ hostname: "github.com", path: `/login/oauth/access_token?code=${code}&client_id=${client_id}&client_secret=${client_secret}`, port: 443, method: "POST" }, function (response) { let body = ""; response.on('data', chunk => { body += (chunk.toString()); }) response.on('end', chunk => { callback(querystring.parse(body)); }) }); request.end();}
// 4. publish路由:用token获取用户信息,检查权限,接受发布
function publish(request, response) { let query = querystring.parse(request.url.match(/^\/publish\?([\s\S]+)$/)[1]); if (query.token.length > 0) { getUser(query.token, info => { if (info.login === "Sammmmmmm") { request.pipe(unzipper.Extract({ path: '../server/public/' })); request.on('end', function () { response.end("success !"); }) } }); }}
function getUser(token, callback) {
let request = https.request({ hostname: "api.github.com", path: `/user`, port: 443, method: "GET", headers: { Authorization: `token ${token}`, "User-Agent": 'toy-publish-by-samdev' } }, function (response) { let body = ""; response.on('data', chunk => { body += (chunk.toString()); }) response.on('end', chunk => { callback(JSON.parse(body)); }) }); request.end();}
http.createServer(function (request, response) {
if (request.url.match(/^\/auth\?/)) { return auth(request, response); } if (request.url.match(/^\/publish\?/)) { return publish(request, response); }
}).listen(8082);
复制代码


改造publish.js


let http = require("http");let archiver = require("archiver");let child_process = require("child_process");let querystring = require("querystring");
// 1. 打开 https://github.com/login/oauth/authorize,获取code
child_process.exec(`open https://github.com/login/oauth/authorize?client_id=${client_id}`);
// 3. 再创建一个server,接收token,后点击发布,将文件传到publish-serverhttp.createServer(function (request, response){ let query = querystring.parse(request.url.match(/^\/\?([\s\S]+)$/)[1]); pubulish(query.token);}).listen(8083);
function pubulish(token) { let request = http.request({ hostname: "127.0.0.1", port: 8082, method: "POST", path: "/publish?token=" + token, headers: { 'Content-Type': 'application/octet-stream', } }, response => { console.log(response); }); const archive = archiver('zip', { zlib: { level: 9 } // Sets the compression level. }); archive.directory('./sample/', false); archive.finalize(); archive.pipe(request);}
复制代码


改造之后,就可以利用 Github 的用户信息,做个简单的用户鉴权,从而控制发布权限。

本周学习内容

  • 实现一个发布系统

  • 通过 Express 搭建一个 Web server

  • 编写一个 Publish server

  • 编写一个 Publish server

  • 通过 Github OAuth 实现一个登录实例

参考资料

Installing Express

Stream | Node.js v13.14.0 Documentation

Authorizing OAuth Apps - GitHub Docs

用户头像

SamGo

关注

还未添加个人签名 2018.12.16 加入

iOS渣渣,Flutter练习生,极客大学在学🤣🤣

评论

发布
暂无评论
与前端训练营的日子 -- Week19