手把手教你如何发布系统和GitHub的oAuth登录

实现线上Web服务

  • 下载安装VM Box, Ubuntu 镜像

    • Oracle VM VirtualBox 下载地址: https://www.virtualbox.org/
    • Ubuntu 20.04.1 LTS (Focal Fossa) 下载地址:https://releases.ubuntu.com/20.04/
  • 新建一个Node Server(Linux,Ubuntu-64bit)

  • 启动Node Server的时候引入Ubuntu 镜像

  • Ubuntu 镜像启动后需要更改镜像地址
    在这里插入图片描述

  • 填写用户名和服务器名,密码
    在这里插入图片描述

  • 勾选Install OpenSSH server
    在这里插入图片描述

  • 安装完毕,点击Reboot重启
    在这里插入图片描述

  • 手动重启
    在这里插入图片描述

  • 输入用户名和密码登录成功
    在这里插入图片描述

  • 用apt安装nodejs

sudo apt install nodejs

在这里插入图片描述

  • 用apt安装npm
sudo apt install npm

在这里插入图片描述

  • 用npm 全局安装 n

    用node 写的node版本管理

sudo npm install -g n

在这里插入图片描述

  • 用 n 来管理node版本
    要最新的node, 这里安装最新版会有问题,所以还是安装14.11.0
sudo n 14.11.0

在这里插入图片描述

  • PATH=$“PATH”

  • 在本地创建server文件夹,然后用express快速搭建一个服务器


mkdir server
cd server
npx express-generator // 要是经常初始化项目,可以全局安装 npm install -g express-generator
npm install
npm start //默认3000端口
  • 在虚拟机上启动ssh
service ssh start

默认22端口

在这里插入图片描述

  • 虚拟机设置22端口(PS:只有虚拟机用户才需要配置端口,正常的机器不需要)

在这里插入图片描述
在这里插入图片描述

  • 用scp命令

把本地目录的所有文件从8022 端口copy到虚拟机上
P后面跟端口号
127.0.0.1 如果是真的服务器,就用服务器的ip地址就可以了

因为copy整个目录,所以加个-r

scp -P 8022 -r ./* eve@127.0.0.1:/home/eve/server

在这里插入图片描述

虚拟机上创建完目录再在本地试一次,这次成功了,可以看到虚拟机上的文件,这个时候不需要在虚拟机上npm install ,只要虚拟机上的node modules 和本地的保持一致即可
在这里插入图片描述

  • 在虚拟机上执行npm start
    这个时候监听的是3000端口,所以还是要添加新的端口映射
    在这里插入图片描述

  • 添加新的端口映射(PS:只有虚拟机用户才需要配置端口,正常的机器不需要)

在这里插入图片描述

这个时候可以在浏览器看到
在这里插入图片描述

然后虚拟机上的效果
在这里插入图片描述

  • 访问一下style.css也可以看到
    在这里插入图片描述

实现一个发布系统

在本地新建两个文件夹publish-tool和publish-server,然后全都先npm init一下,然后再各新建publish.js和erver.js文件

mkdir publish-tool
cd publish-tool
npm init
touch publish.js

mkdir publish-server
cd publish-tool
npm init
touch server.js

  • publish.js的代码

let http = require('http');

let fs = require("fs");

    let request = http.request({
        hostname:"127.0.0.1",
        port:8082,
        method: "POST",
        headers:{
            'Content-Type':'application/octet-stream', // 流式传输的类型
        }
    }, response => {
        console.log(response);
        
    })
    
    let file = fs.createReadStream("./package.json");


file.on('data', chunk => {
    console.log(chunk.toString());
    request.write(chunk);
})
file.on('end', chunk => {
    console.log("read finished");
    request.end(chunk);
})

  • server.js 的代码
let http = require('http');
let fs = require('fs');

http.createServer((req, res) => {
    console.log(req.headers);

    req.on('data', chunk => {
        console.log(chunk);

    })
    req.on('end', chunk => {
        res.end('success');
    })
}).listen(8082);

  • 用vscode分别打开着两个文件,然后点击左边的debug按钮

    • 先监听server.js,下图是运行完publish才会收到结果
      在这里插入图片描述

    • 再运行publish.js
      在这里插入图片描述

  • 修改一下两个文件的代码

// publish.js
let http = require('http');

let fs = require("fs");

    let request = http.request({
        hostname:"127.0.0.1",
        port:8082,
        method: "POST",
        headers:{
            'Content-Type':'application/octet-stream', // 流式传输的类型
          
        }
    }, response => {
        console.log(response);
        
    })
    
    let file = fs.createReadStream("./sample/sample.html"); // 记得新建sample.html
 


file.on('data', chunk => {
    console.log(chunk.toString());
    request.write(chunk);
})
file.on('end', chunk => {
    console.log("read finished");
    request.end(chunk);
})

// server.js
let http = require('http');
let fs = require('fs');

http.createServer((req, res) => {
    console.log(req.headers);

    let outFile = fs.createWriteStream("../server/public/index.html") // 我的server文件夹和publish-tool、publish-server是在同一个路径下

    req.on('data', chunk => {
        console.log(chunk);
        outFile.write(chunk);

    })
    req.on('end', chunk => {
        outFile.end();
        res.end('success');
    })
}).listen(8082);
<!-- sample.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello</title>
</head>
<body>
    <h1>Hello333</h1>
</body>
</html>

  • 然后继续监听publish-server,运行publish-tool,只要没有报错即可,然后你再进入到之前的server文件夹里,启动server,然后在浏览器打开3000端口,这个时候可以看到原来的index.html被sample.html覆盖了

cd server
npm start //默认3000端口

在这里插入图片描述

  • 发布系统

因为总是要发布,所以命令可以统一写在package.json里的script
在这里插入图片描述

其他文件也是这样写,只是后面的文件名不一致

  • 服务器上启动多个服务
npm start&

在这里插入图片描述

在这里插入图片描述

  • publish-server 用的端口8022,所以还是要设置端口转发(PS:只有虚拟机用户才需要配置端口,正常的机器不需要)

在这里插入图片描述

这个时候代码里改一下publish.js的端口
在这里插入图片描述

  • 然后本地运行publish.js
    在这里插入图片描述

  • 在浏览器打开8080端口可以看到Hello333,这个时候就是模拟了本地访问线上的服务器
    在这里插入图片描述

单文件发布

// publish.js

let http = require('http');

let fs = require("fs");


fs.stat('./sample/sample.html', (err, stats) => { // 单文件场景

    let request = http.request({
        hostname:"127.0.0.1",
        port:8082,
        // port:8882,
        method: "POST",
        headers:{
            'Content-Type':'application/octet-stream', // 流式传输的类型
            'Conten-Length':stats.size,
        }
    }, response => {
        console.log(response);
        
    })
    
    let file = fs.createReadStream("./sample/sample.html");

    
    file.pipe(request);
    
    file.on('end', () => request.end());
})
// server.js
let http = require('http');
let fs = require('fs');

http.createServer((req, res) => {
    console.log('req');
    let outFile = fs.createWriteStream("../server/public/index.html")
    req.pipe(outFile);
}).listen(8082);

可以修改一下sample.html,然后再启动监听server服务,运行publish.js之后,在浏览器看3000端口内容是否跟sample.html内容一致

多文件发布

新增一张图片和sample.html放在一起

  • 在publish-tool安装archiver压缩
npm install --save archiver

在这里插入图片描述

  • publish.js的代码修改

let http = require('http');

let fs = require("fs");

let archiver = require("archiver");

    let request = http.request({
        hostname:"127.0.0.1",
        port:8082,
        // port:8882,
        method: "POST",
        headers:{
            'Content-Type':'application/octet-stream', // 流式传输的类型
            // 'Conten-Length':stats.size,
        }
    }, response => {
        console.log(response);
        
    })
    

     // 创建archiver实例
    const  archive = archiver('zip', {
        zlib:{level:9}
    })

    archive.directory('./sample/', false);

    archive.finalize(); // 填好压缩内容
    archive.pipe(fs.createWriteStream("tmp.zip")
     archive.pipe(request);

    

然后直接运行publish.js,可以看到当前文件下的tmp.zip压缩文件
在这里插入图片描述

  • server.js文件修改
let http = require('http');
let fs = require('fs');

http.createServer((req, res) => {
    console.log('req');

    let outFile = fs.createWriteStream("../server/public/tmp.zip")
    req.pipe(outFile);
}).listen(8082);

然后重新运行一次publish.js文件,就可以在server/public/路径下看到tmp.zip压缩文件了
在这里插入图片描述

  • 在服务端进行解压
    sudo npm install --save unzipper
sudo npm install --save unzipper

在这里插入图片描述

  • server.js解压代码修改
let http = require('http');
let unzipper = require('unzipper');

http.createServer((req, res) => {
    console.log('req');

    req.pipe(unzipper.Extract({path:'../server/public/'}));
}).listen(8082);

然后再重新启动publish.js这样就可以在server文件夹里看到解压后的文件了

在这里插入图片描述

Github oAuth 登录实例

  • 先从GitHub主页的settings进去,然后在左边列表找到Developer settings进去

在这里插入图片描述

  • 然后选择New Github App

在这里插入图片描述

  • New Github App填写内容

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 提交后获取私钥
    在这里插入图片描述

  • 参考oAuth的文档
    https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/

  • oAth的总体思路

    • publish-tool打开https://github.com/login/oauth/authorize?client_id=xxx
    • publish-server的auth路由:接收code,用code+client_id +client-secret换取token
    • 创建server,接收token,点击发布
    • 用token获取用户信息,检查权限
    • publish路由:接收发布
  • 修改publish.js代码


let http = require('http');

let fs = require("fs");

let archiver = require("archiver");

let child_process = require("child_process");

// 打开https://github.com/login/oauth/authorize

child_process.exec(`open https://github.com/login/oauth/authorize?client_id=Iv1.73af973ded44837a`)

// 创建server,接收token,点击发布



     // 创建archiver实例
    const  archive = archiver('zip', {
        zlib:{level:9}
    })

    archive.directory('./sample/', false);

    archive.finalize(); // 填好压缩内容
    archive.pipe(fs.createWriteStream("tmp.zip"))
    
    archive.pipe(request);
   

然后运行publish.js,浏览器会自动打开授权页面

在这里插入图片描述

  • 完整版publish.js代码

let http = require('http');

let fs = require("fs");

let archiver = require("archiver");
let querystring = require('querystring');

let child_process = require("child_process");

// 打开https://github.com/login/oauth/authorize

child_process.exec(`open https://github.com/login/oauth/authorize?client_id=xxx`)

// 创建server,接收token,点击发布


http.createServer((req, res) => {
    let query = querystring.parse(req.url.match(/^\/\?([\s\S]+)$/)[1]);
    // console.log({query});
    publish(query.token)
}).listen(8083);

function publish(token){
 let request = http.request({
        hostname:"127.0.0.1",
        port:8082,
        // port:8882,
        method: "POST",
        path:`/publish?token=${token}`,
        headers:{
            'Content-Type':'application/octet-stream', // 流式传输的类型
            // 'Conten-Length':stats.size,
        }
    }, response => {
        console.log(response);
        
    })
    let file = fs.createReadStream("./sample/sample.html");
// 创建archiver实例
    const  archive = archiver('zip', {
        zlib:{level:9}
    })

    archive.directory('./sample/', false);

    archive.finalize(); // 填好压缩内容
    archive.pipe(fs.createWriteStream("tmp.zip"))
    
    archive.pipe(request);
}

  • 完整版server.js代码
let http = require('http');
let https = require('https');
// let fs = require('fs');
let unzipper = require('unzipper');
let querystring = require('querystring');


function auth(req, res) {
let query = querystring.parse(req.url.match(/^\/auth\?([\s\S]+)$/)[1]);
// console.log({query});
getToken(query.code, function (info) {
    // res.write(JSON.stringify(info));
    res.write(`<a href='http://localhost:8083/?token=${info.access_token}'>publish</a>`);
    res.end();
    // console.log(info);
})
}
function getToken(code, callback) {

    let request = https.request({
        hostname:"github.com",
        path:`/login/oauth/access_token?code=${code}&client_id=Ixxx&client_secret=xxx`,
        port:443,
        method:"POST",
    }, function(response){
        console.log(response);
        let body = ""
        response.on('data', chunk => {
            console.log(chunk.toString());
            body += chunk.toString()
        })
        response.on('end', chunk => {
            // let o = querystring.parse(body)
            // console.log(o);
            callback(querystring.parse(body))
        })
    })
    request.end();
}
function publish(req, res) {
let query = querystring.parse(req.url.match(/^\/publish\?([\s\S]+)$/)[1]);
getUser(query.token, info => {
    if (info.login === 'EveWeiGit') {
    req.pipe(unzipper.Extract({path:'../server/public/'}));
    req.on('end', function() {
        res.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":"wei-publish",
        }
    }, function(response){
        // console.log(response);
        let body = ""
        response.on('data', chunk => {
            console.log(chunk.toString());
            body += chunk.toString()
        })
        response.on('end', chunk => {
            let o = JSON.parse(body)
            console.log('o', o, o.login);
            callback(o)
        })
    })
    request.end();
}

http.createServer((req, res) => {
    // console.log('req');

    if(req.url.match(/^\/auth\?/)) {
        return auth(req, res)
    }
    if(req.url.match(/^\/publish\?/)) {
        return publish(req, res)
    }

}).listen(8082);
  • 先启动监听server.js
  • 然后运行publish.js,

在这里插入图片描述

  • 点击publish
    就可以发布了,先把之前的server/public/ 下的文件删除,这样操作后就可以看到发布过去的图片和sample.html了

公众号

欢迎大家关注我的公众号: 石马上coding,一起成长
石马上coding

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值