Gowhich

Durban's Blog

现在的https越来越流行,这个未来应该是必备技能了,下面举个Yii2的项目,进行https配置,https证书自己需要准备好,不会的可以看我的文章
下面就是示例配置【仅供参考】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
server {
listen 443 ssl http2;

ssl_certificate /etc/letsencrypt/live/gowhich.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gowhich.com/privkey.pem;

ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache builtin:1000 shared:SSL:10m;

resolver 8.8.8.8 8.8.4.4 valid=300s;

resolver_timeout 5s;

server_name www.gowhich.com gowhich.com;

access_log /home/wwwlogs/www.gowhich.com.log access;
error_log /home/wwwlogs/www.gowhich.com.error.log;

index index.html index.htm index.php default.html default.htm default.php;
root /home/wwwroot/www1.gowhich.com/web;

include yii.conf;

if ($host = 'gowhich.com') {
rewrite ^/(.*)$ https://www.gowhich.com/$1 permanent;
}

location ~ [^/]\.php(/|$) {
# comment try_files $uri =404; to enable pathinfo
try_files $uri =404;
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
include fastcgi.conf;
#include pathinfo.conf;
}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 30d;
}

location ~ .*\.(js|css)?$ {
expires 12h;
}
}

Install certbot 安装certbot

安装步骤可到这里 https://certbot.eff.org/#debianjessie-nginx 根据自己的服务器情况选择具体的安装版本

配置证书

可以使用如下命令,这样的好处是我们可以在下次进行自动更新证书的话,可以方便的处理证书

1
certbot certonly --webroot -w /home/wwwroot/www1.gowhich.com/web -d gowhich.com -d www.gowhich.com

注意这里的webroot路径一定是你静态文件能够被访问到的,不然,无法进行证书验证

比如我的另外一个域名可以这样设置【Flask项目】

1
certbot certonly --webroot -w /home/wwwroot/www.walkerfree.com/walkerfree/static -d walkerfree.com -d www.walkerfree.com

输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for walkerfree.com
http-01 challenge for www.walkerfree.com
Using the webroot path /home/wwwroot/www.walkerfree.com/walkerfree/static for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0003_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0003_csr-certbot.pem

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/walkerfree.com/fullchain.pem. Your cert will
expire on 2018-01-22. To obtain a new or tweaked version of this
certificate in the future, simply run certbot again. To
non-interactively renew *all* of your certificates, run "certbot
renew"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

然后就可以进行nginx配置了

当我们不希望每次都来自己更新,或者自己忘记了更新,证书过期了,不就很危险了,执行下面的命令试试 是否可以正常的自动更新,如果可以的话 我们就把此命令加入我们的定时任务中就可以了

1
sudo certbot renew --dry-run

加入定时任务

1
30 2 * * 1 /usr/bin/certbot renew  >> /var/log/certbot-renew.log

每周一半夜2点30分执行renew任务。


2019-02-20补充

通过下面命令可以通过certbot自己的服务器来验证证书 - 这个只在自己的网站不支持验证证书的情况下使用

1
certbot certonly --standalone --preferred-challenges http -d walkerfree.com -d www.walkerfree.com

注意:前提可能需要将自己本地监听80端口的服务器暂时停掉一会

打开“终端”,根据自己的版本选择命令

早期的OS X(10.6~10.8)系统可以使用如下两条命令来开始或者关闭系统隐藏文件的显示:

1
2
defaults write com.apple.Finder AppleShowAllFiles Yes && killall Finder //显示隐藏文件
defaults write com.apple.Finder AppleShowAllFiles No && killall Finder //不显示隐藏文件

当升级到OS X 10.9 Mavericks版本之后,这两条命令需要做一些修改,变成了如下命令:

1
2
defaults write com.apple.finder AppleShowAllFiles Yes && killall Finder //显示隐藏文件
defaults write com.apple.finder AppleShowAllFiles No && killall Finder //不显示隐藏文件

复制命令,在“终端”中粘贴命令,按下enter键–执行。

GIT

设置HTTP协议

  • socks5方式
1
2
git config --global http.proxy 'socks5://127.0.0.1:1080' 
git config --global https.proxy 'socks5://127.0.0.1:1080'
  • http方式
1
2
git config --global http.proxy "http://127.0.0.1:6667"
git config --global https.proxy "http://127.0.0.1:6667"
  • 取消设置
1
2
git config --global --unset http.proxy
git config --global --unset https.proxy

设置SSH协议

创建文件 ~/.ssh/config 【如果存在可忽略】

1
2
3
4
5
6
7
8
9
10
11
Host bitbucket.org
User git
HostName altssh.bitbucket.org
Port 443
ProxyCommand connect -S 127.0.0.1:1080 %h %p

Host github.com
User git
HostName ssh.github.com
Port 443
ProxyCommand connect -S 127.0.0.1:1080 %h %p%

终端 terminal

打开终端执行下面命令即可,无须重启终端

1
2
export http_proxy="socks5://127.0.0.1:1080"
export https_proxy="socks5://127.0.0.1:1080"

设置完后 执行下面命令查看自己的IP

1
curl -i http://ip.cn

有个问题就是设置完代理,上面的命令无法测试自己的IP了,应该是这个地址也同时被墙了。

参考:https://blog.kelu.org/tech/2017/06/19/setting-socks5-proxy.html

工作中难免会遇到处理大文件的时候,有这种stream的处理方式,就不需要一次处理太大的文件,从而导致内存不够用,或者内存占用太多。

fs.createWriteStream 似乎不会自己创建不存在的文件夹,所以在使用之前需要注意,保存文件的文件夹一定要提前创建。

1
2
3
4
5
const path = '/xxxxxx/ddd/';

if (!fs.existsSync(path)) {
fs.mkdirSync(path);
}

创建完文件夹,我们就可以进行文件添加操作了。我们希望在使用文件添加操作的时候是通过saveFile(filePath, fileData);这样的方式来调用。

这里我采用了Promise的方式,个人比较喜欢这样的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* [saveFileWithStream description]
* @param {String} filePath [文件路径]
* @param {Buffer} readData [Buffer 数据]
*/
static saveFile(filePath, fileData) {
return new Promise((resolve, reject) => {
// 块方式写入文件
const wstream = fs.createWriteStream(filePath);

wstream.on('open', () => {
const blockSize = 128;
const nbBlocks = Math.ceil(fileData.length / (blockSize));
for (let i = 0; i < nbBlocks; i += 1) {
const currentBlock = fileData.slice(
blockSize * i,
Math.min(blockSize * (i + 1), fileData.length),
);
wstream.write(currentBlock);
}

wstream.end();
});
wstream.on('error', (err) => { reject(err); });
wstream.on('finish', () => { resolve(true); });
});
}

实际调用的时候,如下

1
2
3
4
5
try {
await saveFileWithStream(filePath, fileData); // 这里的fileData是Buffer类型
} catch (err) {
console.log(err.stack);
}

最近NodeJs 版本 8.5 已经支持了 ESM module,感觉之前的babel编译可以放弃不用了,不过这个只是一个实验性的,具体稳定与否,是否可以上生产环境,还是需要测试一段时间的。

体验环境搭建:

NodeJs: v8.5.0

依赖包:

1
2
3
4
5
6
7
"dependencies": {
"axios": "^0.16.2",
"koa": "^2.3.0",
"koa-router": "^7.2.1",
"koa-views": "^6.1.0",
"twig": "^1.10.5"
}

这里使用的是koajs,大家可以使用下express

模块引入不在需要require了,哈哈,感觉不一样的体验

1
2
3
4
5
import koa from 'koa';
import koaRouter from 'koa-router';
import axios from 'axios';
import views from 'koa-views';
import path from 'path';

像这样是不是感觉,瓦萨,还不错

继续看下面的配置

1
2
3
4
5
6
app.use(views(path.resolve() + '/views', {
map: {
html: 'twig',
},
extension: 'twig',
}));

对于web开发,推荐koa-views,可以支持很多模板,想用哪个就用哪个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const viewsTest = async (ctx, next) => {
ctx.state = {
title: 'viewsTest',
};

await ctx.render('views_test', {
title: 'viewsTest',
});
return next();
};

router.get('/views', viewsTest);

app
.use(router.routes())
.use(router.allowedMethods());

app.listen(8888);

好了,我的index.mjs创建完成,注意这里的index文件是以mjs结尾的 ,不然稍后运行的话是不会执行的。

view_test.twig模板其实很简单,为了测试简单加下就好了。

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
</head>

<body>
{{ title }}
</body>

</html>

目录结果也给大家演示下

|-index.mjs

|-node_modules

|-package.json

|-package-lock.json

|-views

|-views_test.twig

运行我们的程序

1
node --experimental-modules index.mjs

出现下面的提示就是运行起来了

1
2
$ node --experimental-modules index.mjs
(node:6999) ExperimentalWarning: The ESM module loader is experimental.

感觉开发代码又便捷了很多呀。

最近使用vim变成javascript程序,自己的一些写代码的习惯并不是很好,需要经常通过格式化程序帮助自己来格式化代码,

vim-autoformat这个插件肯定是少不了,问题就是如何才能通过eslint来格式化代码,毕竟越来越多的高手都在用eslint来规范自己的代码,网上有些文章说的就是如何配置全局,但是我不喜欢全局配置,毕竟不是每个项目的内容都一样,而且版本可能也有要求,因地制宜才好,于是研究了下,自己摸索出来一个方法

1
2
3
4
5
6
7
8
9
10
11
12
" auto-formatter
function! ESlintFormatter()
let l:npm_bin = ''
let l:eslint = 'eslint'
if executable('npm')
let l:npm_bin = split(system('npm bin'), '\n')[0]
endif
if strlen(l:npm_bin) && executable(l:npm_bin . '/eslint')
let l:eslint = l:npm_bin . '/eslint'
endif
let g:formatdef_eslint = '"SRC=eslint-temp-${RANDOM}.js; cat - >$SRC; ' . l:eslint . ' --fix $SRC >/dev/null 2>&1; cat $SRC | perl -pe \"chomp if eof\"; rm -f $SRC"'
endfunction

然后针对javascript类型的文件进行调用

1
autocmd FileType javascript :call ESlintFormatter()

这样就可以了。欢迎采用

在使用eslint的时候,遇到async/await语法 会报错,总是提示 no-await-in-loop。举个例子看下面的代码的逻辑

1
2
3
4
5
for (let i = 0; i < userRedpacketItem.length; i += 1) {
userRedpacketItem[i].product_id = await productModel.redpacketMapPrdIdToRefId(ctx, userRedpacketItem[i].product_id);
// 是否过期
userRedpacketItem[i] = userHasRedpacketModel.markExpire(userRedpacketItem[i]);
}

注意点是在for循环中使用了await

有点懵了,不能await,那我怎么取值进行更新值呢,根本就没有办法处理了,难我要先进行取值然后在进行循环赋值?嗯,这样肯定不行的,看来自己还是有点菜,不知其中的规范用法,好了,进行不断学习找到了解决办法,看下面的代码

1
2
3
4
5
6
7
await Promise.all(userRedpacketItem.map(async (item) => {
let newItem = item;
newItem.product_id = await productModel.redpacketMapPrdIdToRefId(ctx, item.product_id);
// 是否过期
newItem = userHasRedpacketModel.markExpire(item);
return newItem;
}));

嗯这样就不报错了,而且这个方法觉得也很node。

最近玩了下Yii2的验证码部分,正常的逻辑都可以走通的,网上的例子也是没有问题的,关键有问题的部分是在module中使用的时候,分享给大家,往下看之前可以去看看正常情况下是如何使用的。

controller部分的代码,这里的跟网上的都类似

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public function actions()
{
return [
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => null,
'backColor' => 0x000000, //背景颜色
'maxLength' => 6, //最大显示个数
'minLength' => 5, //最少显示个数
'padding' => 5, //间距
'height' => 40, //高度
'width' => 130, //宽度
'foreColor' => 0xffffff, //字体颜色
'offset' => 4, //设置字符偏移量 有效果
],
];
}

model 部分的代码【这里是需要注意的】

1
2
3
4
5
6
7
8
9
10
11
public function rules()
{
return [
['username', 'required', 'message' => '登录账号不能为空'],
['password', 'required', 'message' => '登录密码不能为空'],
['verifyCode', 'required', 'message' => '验证码不能为空'],
['verifyCode', 'captcha', 'captchaAction' => 'admin/default/captcha', 'message' => '验证码输入错误'],
['rememberMe', 'boolean'],
['password', 'validatePassword'],
];
}

rules中的verifyCode,需要加一个captchaAction对应的值,不然会出现验证码验证不通过,而且验证码的的数字也不会变化,原因应该是默认使用了site/captcha导致的

view部分的代码【由于php跟html的混排导致我无法忍受页面样式的混乱排版,所以尽量将参数配置部分拿出来】

1
2
3
4
5
6
7
8
9
10
11
$captchaConfig = [
'name' => 'captchaimg',
'captchaAction' => ['/admin/default/captcha'],
'template' => '<div class="form-group"><div>{image}</div></div>',
'imageOptions' => [
'id' => 'captchaimg',
'title' => '换一个',
'alt' => '换一个',
'style' => 'cursor:pointer;margin-left:25px;',
],
];
1
<?=Captcha::widget($captchaConfig);?>

页面中总有一些操作是,需要图片加载完之后去做的,下面的代码可实现,需要的拿走

1
2
3
4
5
6
$("img").one("load", function(v) {
// 逻辑处理
$(v.target).parent().parent().find('.over-shade').css({'height':$(v.target).height()});
}).each(function() {
if(this.complete) $(this).load();
});
0%