×
搜过:
前端黑客技术
Nodejs
JavaScript
React
Vue
React
Vue
React
Vue
推荐:
前端黑客技术
Nodejs
JavaScript
React
Vue
查询中 ...

×

记录生活,记录你

———— 的代码

×
随机生成
Write here ...
换一换
确定
做个前端,来点Nginx by:花满楼

做个前端,来点Nginx

自从Nodejs火了,前端能做的事、要做的事越来越多了;同时对前端的要求也就越来越高,如果现在还只是停留在浏览器端写页面做交互,估计很难找到(更好的)工作了,Node中间层、Node微服务、网关这些可以和业务分离的地方以后可能都是前端的事了;Nodejs是把锋利的瑞士军刀,但你也不要想多了;合理的选型,各司其职,职尽其能,才能发挥各自最大的作用;毕竟一切从实际出发,实事求是,理论联系实际才是最佳的方法论;比如Nodejs可以做反向代理(http-proxy),可以很快的搭建静态资源站,但这些并不是Nodejs最擅长的,这些交给Nginx显然是个更好的选择,既可以把这些事做更好,还给Nodejs服务减压了!

一、快速拾起Nginx

Nginx是一个高性能的Web和反向代理服务器,稳定、强大、系统资源占用低,这些就不说了;

在nginx.conf这个配置文件里,一个server {}块可以对应一个站点的服务,每个server {}块里可以配置多个location {}块来对站点进行路由级别的控制,既可以通过proxy_pass target设置反向代理的server,也可以直接通过root dir来访问目录下的静态文件;server_name设置访问的域,多个用空格隔开,或者用通配符和正则;location后面可以是正则以及nginx提供的丰富的匹配符和变量;记住大括号前面的空格不能省,每行结束语句的分号不能省;

a. 比如用Nodejs启动了一个站点监听3000端口,用a.famanoder.cn来访问

server { listen 80; server_name a.famanoder.cn; location / { proxy_pass http://localhost:3000; } }

b. 比如把所有的静态资源放到了dist目录,用cdn.famanoder.cn来访问

server { listen 80; server_name cdn.famanoder.cn; location / { index index.html; root D:\sources\dist; } }

c. 用vue做的一个移动端的项目,用m.famanoder.cn来访问,所有数据接口由famanoder.cn提供;

server { listen 80; server_name m.famanoder.cn; location /api { # 代理api,以免跨域 proxy_pass https://famanoder.cn; } location / { index index.html; root D:/vue/dist; } }

以上只是最简单的站点和反向代理设置,通过匹配符和正则可以做更多的控制;

二、常用匹配符和变量

=   等于,严格匹配

!=  不等于

~   区分大小写匹配

!~  区分大小写不匹配

~*  不区分大小写匹配

!~* 不区分大小写不匹配

*   任意字符

-f和!-f 判断是否存在文件

-d和!-d 判断是否存在目录

-e和!-e 判断是否存在文件或目录

-x和!-x 判断文件是否可执行

对于location,匹配的优先级为:

(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)

Nginx里有if指令,但是没有else指令和&&判断,但可以通过set变通的实现:

比如限制GET请求参数中的SQL关键词:

set $invalidQuery 1; if( $request_method = GET ){ set $invalidQuery '${invalidQuery}1'; } if( $query_string ~* "select|union|exec" ){ set $invalidQuery '${invalidQuery}1'; } if( $invalidQuery = '111' ){ return 403; }

常用变量:

$args : 请求行中的参数,同$query_string。等于js中的location.search.slice(1)。

$content_type : 请求头中的Content-Type字段。

$document_root : 当前请求在root指令中指定的值。

$host : 请求主机头字段,否则为服务器名称。等于js中的location.host。

$http_user_agent : 客户端agent信息。等于js中的navigator.userAgent。

$http_cookie : 客户端cookie信息。等于js中的document.cookie。

$limit_rate : 这个变量可以限制连接速率。

$request_method : 客户端请求的动作,通常为GET或POST。

$remote_addr : 客户端的IP地址。

$remote_port : 客户端的端口。等于js中的location.port。

$http_referer :网页来源。等于js中的document.referer。

$remote_user : 已经经过Auth Basic Module验证的用户名。

$request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。

$scheme : HTTP方法(如http,https)。等于js中的location.protocol。

$server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。

$server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。

$server_name : 服务器名称。

$server_port : 请求到达服务器的端口号。

$request_uri : 包含请求参数的原始URI,不包含主机名,等于js中的location.pathname+location.search。

$uri : 不带请求参数的当前URI,$uri不包含主机名,等于js中的location.pathname。

$document_uri : 与$uri相同。

三、常见设置

1、worker_processes 4   # 开启多进程,一般为cpu核数,等于Nodejs中的require('os').cpus().length

2、error_log  logs/error.log  info;   # log文件的地址和级别(debug, info, notice, warn, error, crit)

3、log_format 格式名称 具体格式   # 定义日志内容的格式可以包含$remote_addr $status $http_user_agent等参数

4、开启gzip

gzip  on;

gzip_proxied any;  

gzip_min_length  1024;

gzip_buffers     4 8k;

gzip_types       text/css application/javascript application/atom+xml application/rss+xml text/plain image/svg+xml application/json text/javascript; 

默认的配置文件中只有gzip on作用不大,需要自行配置后续gzip字段;给所有需要开启gzip的资源添加mimeType,图片不需要gzip(没有明显效果,体积还可能增大),白白损耗性能;

四、解决前端跨域问题

在前后端分离的时候,前后端搭建了两套环境,前端请求数据的时候会跨域,一般是用Nodejs做中转,比如使用http-proxy和request模块,或者在webpack的dev-server里配置proxy,浏览器兼容性比较理想的情况下还可以直接设置CORS;这样对于打包上线也不需要做太多改动;当然有时候还需要jsonp;

1. 设置CORS

server { listen 80; server_name cdn.famanoder.cn; location / { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Credentials true; add_header Access-Control-Allow-Methods GET,POST,OPTIONS; index index.html; root D:/sources/dist; } } # 如果不想设置星号的话,这个变通的做法貌似更灵活,还可以通过跨域反过来限制某些资源的是否可访问 if ($http_referer ~* 'famanoder.cn') { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Credentials true; add_header Access-Control-Allow-Methods GET,POST,OPTIONS; }

2. 做api中转

server { listen 80; server_name m.famanoder.cn; location /api { proxy_pass https://localhost:3000; } }

五、从http切换到https

对于一般的散户来说,Letsencrypt是个不错的选择,可以免费为多个域名提供一套证书(散户福利!Nodejs多站点切换Htpps协议);可以新建一个站点专门为申请证书服务,以免以后重新申请时重启应用或再次搭建;对于切换到https,只需在80端口上直接对指定域名做301跳转到https对应地址,server块内做很小改动即可:

server { listen 80; server_name *.famanoder.com famanoder.com; location / { # 迁移到https return 301 https://$host$request_uri; } location ~* 'acme-challenge' { # 2333端口留做以后申请证书用 proxy_pass http://localhost:2333; } } server { # 监听443端口,开启ssl listen 443 ssl; server_name cdn.famanoder.cn; # 把申请到的证书加进来 ssl_certificate D:/crt.pem; ssl_certificate_key D:/key.pem; location / { index index.html; root D:\sources\dist; } }

六、Nginx真的超级强大,而且配置起来并不繁琐,常常简单的设置就可以达到非常强大的功能,比如做安全访问限制、负载均衡等;

如果你很喜欢一个东西,那么是否应该拿它来做更多有意义的事情!如果你很喜欢JS,那么是否应该拿它来做更多有意义的事情!那么好的,听说新版Nginx开始支持js语法了!如果你已在路上,就勇敢的向前吧!






业余MongoDB小记 by:花满楼

业余MongoDB小记

1、现在网上大多初级教程都忘记强调一个生产环境的致命问题:没有绑定IP和端口、没有身份权限认证导致向全网公开了Mongodb的连接,并且拥有root权限!!!也就是说,任何人电脑可以mongo启动Mongodb的,都可以mongo ip连接到一个远程未做ip、端口限制和权限认证的Mongodb数据库,并且可以随意操作!近年,全球上万个裸奔的Mongodb遭黑客比特币勒索都与这一问题密切相关!当然也包括我这个小白用户!

2、限制ip:启动时加上--bind_ip=127.0.0.1(只允许哪些ip可以访问)

3、允许访问的端口限制:--port=12345(最好不用默认的27017)

4、权限认证:非--auth启动情况下,切换到相应数据库,比如:use users,然后使用createUser(貌似3.0以后)

db.createUser({user:'name',pwd:'pswd',roles:[{role:'readWrite',db:'database'}]})

然后启动时加上--auth

5、命令行mongo操作认证:

mongo ip:port 

use database

db.auth('name','pswd')

// .....

6、mongoose安全连接:

mongoose.connect('mongodb://name:paswd@ip:port/database')

7、koa-mongo安全连接:

app.use(mongo({

user:'name',

pass:'pswd',

host: 'i.p.i.p',

port: 12345,

db: 'test'

}));

8、mongoose查询_id,使用Test.find(_id:'5867fddf4aee37201fb4d1d3',cb)即可;使用mongodb操作就不一样了,_id为Object;{_id:'str'}查询不到数据的,一般会出现ObjectID is not defined的情况;可以直接使用BSON

import {ObjectID} from 'BSON';

然后cx.mongo.db('db').collection('col').find({_id:ObjectID('5867fddf4aee37201fb4d1d3')}).toArray(cb)

9、










Nodejs同步与备份服务器仓库 by:花满楼

Nodejs同步与备份服务器仓库

听说Github上有个仓库叫famanoder/gitsync,里面用Nodejs实现了一个接口,用来远程执行git命令,来同步更新和备份服务器资源;由于服务器资源的特殊重要性,该接口做了个简单的签名认证,防止链接被盗取后的恶意操作;当然这只是个简单的认证,要更全面的防范,扩展一下也是很容易的;

实现背景:

最近项目的一个需求是客户端需要可以多个版本切换,比如当前最新版本为3.5.0,那么对应前端的资源引用路径应该是//cdn.host/3.5.0/js/*.js,如此一来,前端的静态资源就需要按需求版本划分为多个包了,OK,复制粘贴就完事了嘛!大不了用Nodejs写个复制粘贴也不麻烦的;这里最容易首先想到的一个巨坑就是,一旦需要修复旧版本的bug,需要同步修复的文件到很多版本包,如果涉及的模块错综复杂的话,就得像git里需要手动解决冲突了,呵呵了吧!但转念一想,其实这个问题不会存在的,因为如果客户那里出问题了的话,如果没升级到最新版,我们首先是提醒用户升级,如果是新版的问题,那么改问题,当前版本不可提交的话,改上个版本提交,同步到当前版本就是,这样的话,说到底多版本控制其实就是最多两个版本控制了;如果有版本涉及到会员收费呢,有的用户就是不愿意付费咋办,那时候最多就不止两个版本了,好吧,反正有用户愿意付费,我们麻烦点也没啥~接下来的问题就是前端开发环境的配置多版本问题了;目前是webpack,开发环境npm run dev,package.json的scripts为:

"dev":"webpack --config ./webpack.config.dev.js --progress --colors"

如果以后每个版本都有个独立的包的话,那么势必webpack的配置也会有多个,而多个webpack配置唯一不一样的地方就是版本号!设想下可能是这样:

"dev3.5.0":"webpack --config ./webpack.config.dev3.5.0.js --progress --colors" "dev4.0.0":"webpack --config ./webpack.config.dev4.0.0.js --progress --colors" "dev5.0.0":"webpack --config ./webpack.config.dev5.0.0.js --progress --colors" 。。。

貌似可以哈!原谅我的强迫症,每次复制粘贴相关模块就算了,连开发环境的配置也得重新弄一份,以后要加或改个loader、plugin什么的,不是得每个配置文件走一遍。。。

这时候Nodejs该做点什么了:比如,命令行输入node startWebpack 3.5.0,那么首先尝试启动3.5.0版本,如果没有该版本,则创建3.5.0版本并启动它;到这的话,package.json的scripts的相关webpack启动都是多余的了,接下来要做的就是在startWebpack.js里根据输入的版本号启动对应版本,打包对应版本的前端资源;同时开多个版本的话也互不影响,各自独立工作;目前实现了三种命令,注意不是三个命令:

1、node startWebpack init newVersion [from oldVersion]    

初始化一个版本,可以指定从哪个版本的基础上生成新版本 

2、node startWebpack version

启动一个版本

3、除了上面两个,其它参数统一返回已存在的所有版本号

详细代码就不出了,可能这种需求不具有普遍性,坑啊!

原来的webpack.config.js里需要提前注入一个version参数;

var agrs=process.argv.slice(2).join(' '); var matAegsInit=agrs.match(/init\s+([^\s]+)(?:\sfrom\s(.+))?/); var matAegsStart=agrs.match(/\s+/); function startWebpack(version,webpackConfig){ process.title = process.cwd()+' Webpack ' +version; webpack(webpackConfig,(err,stats)=>{ if(err) throw err; process.stdout... }); } module.exports=function bootstrapWebpackVersionCtrl(WebpackVersionConfig){ if(matAegsInit&&matAegsInit.length&&matAegsInit[1]){ initAndStartWebpack(); }else if(!matAegsStart){ startWebpack(); }else{ getVersionList(); } }

以上代码只是大概的轮廓,可忽略,重点在于用代码的方式让webpack更加灵活可控,其中还要借助shelljs模块用代码实现命令行的很多操作;我可不会告诉别人Github上的那个famanoder/gitsync其实是从这衍生而来的;

gitsync可以做什么呢?

1、最简单的做法是,放出了一个url,限定访问的过期时间或次数,配合query参数请求服务器执行相应的git命令(事实上可以执行绝大多数命令行可执行的命令),比如:先git commit -m abc然后git pull origin master,甚至到指定目录执行其它可执行命令,为了安全考虑限制下吧,命令限制完了,最好还加个简单的签名,服务器上不比你本地的!

2、就我的个人小站而言,乌七八糟的堆了一大堆,散落着七八个仓库,最近越来越感觉这种做法不靠谱,所已现在统一合为一个仓库了,各种操作也容易,同步备份更方便;既然gitsync是Nodejs写的,那么再加一个定时任务,定时执行git pull、git push,那么就相当于定时备份整个服务器的资源了,现在就一个仓库,就算服务器不小心挂了,或是被黑的一塌糊涂,也可以安然的从github拉取一份,重启就OK了;

3、shelljs可以做的还有更多,比如,我公司内部对外网的访问做了ip限制,很多时候我的线上服务挂了,我无法即时登录服务器重启,这时如果gitsync放出了一个path参数入口的话,shelljs.cd(query.path);shelljs.exec('npm start');即可重启服务了,当然有pm2更好了;

4、gitsync本应非常简单,如果需要过多的维护,说明该换方案了;

function App(req,res){ // ... const ser={req,res}; SimpleRouter.call(ser,{ '/gitsync':()=>{ const query=parseUrl(req.url); validateQuery(err,query=>{ // ... validateSignature(err,baseQuery=>{ // ... sj.exec(query.git,{async:true},(code,stdout,err)=>{ // ... res.end(out); }); }); }); }, '*':'404.html' }); }

详细地址:https://github.com/famanoder/gitsync


如果你已在路上,就勇敢的向前吧!







新开设博客侧记 by:李杨

新开设博客侧记

博主其人,高中时期与我同桌,大学时期又与我同校,到如今已有将近十年的友谊。他与我最大的不同在于,我偏好文艺性的东西,而他对逻辑推理、数学思维、程序设计有着持续的着迷。他的性格属于典型的理工科男生的性格,害羞,沉默寡言,但是思维及其活跃。尤其是谈到他兴趣相关的内容,他总是能够提出很多匪夷所思的见解。

大学期间,我读经济学专业,他读工商管理专业,我们四年都学习着与各自兴趣完全不相关的内容。上天好像特别喜欢这种耍人的把戏,把我们抛离自己理想的轨道,然后又让我们挣扎着靠近它。所幸的是,我们都持有各自的兴趣,坚持它,并一直保持浓厚的关注,积极地去实践它。

在空余时间,我们有时一起散步,聊天。他经常告诉我,他又掌握了某项电脑技巧,明白了某个程序,以及下一步打算之类的。兴奋,满怀希望,仿佛为自己人生理想的画卷又勾勒出完美的一笔。他从未谈到他的担忧,沉迷于数字和程序的世界里,他从未怀疑这么做的意义。我能够理解他为何不断在此方面取得持续进步,像他这样只关注自身行动而非用多余的担忧去束缚自己的人,成功只是时间早晚的问题。

如今,我们都已参加工作,他怀着对兴趣的追求和对自身能力的信任,如愿进入一家网络企业工作,参与程序开发与维护。繁忙的工作与庸常的生活往往不知不觉消磨掉一个人如火的斗志,但对于一份真挚的热爱,它不但不会被生活遗弃,反而会逐渐壮大为一股引导生活的力量。朋友的坚持,不应该仅仅归咎于幸运,而更应当归功于他真正的热爱。工作对他而言,不只是一项指定的任务,而是一次训练,一次拓展。他保持始终如一的激情,即使在工作之余,依然积极钻研,攀向一个个未知的高峰。

这一切是值得庆贺的,所有的磨练在付出眼泪后都应该收获掌声。对于朋友前进途中遭遇的挫折、困难,我没有给予任何实质性的帮助,但是在他有所成就时,我必须给他鼓励、祝贺。我衷心希望他以及每一个真正努力的人们能再接再厉,也希望他们的成就能真正有益于社会,为社会所认可和赞赏。

毕业之后有很长一段时间我们没有联系,这次受其所托,嘱咐我为其新开发的网站写篇序言。基于多年的友谊和出于鼓励的目的,也终于觉得自己或许可以帮助他做点什么,所以不辞愚钝,聊献拙芹,同时感谢朋友对我的信任。

 
 2015.10.19.于东莞。




283
4
散户福利!Nodejs多站点切换Htpps协议 by:花满楼

散户福利!Nodejs多站点切换Htpps协议

记录一些要点,以便于常记起时有据可循!

纯属赶个时髦,折腾了两天终于将个人小站的全部服务由http协议切换到了https,整个过程虽然也不算太麻烦,但也不得不承认,个人对互联网安全这方面的知识确认比较欠缺;

Letsencrypt是由Mozilla、思科和EFF等组织发起的,免费向广大互联网网站提供SSL证书,目的在于加速推进互联网由Http过渡到Https,很高兴周末能够与其不期而遇,这对于一个互联网散户来说,绝对是大大的福利,所以决定乘周末折腾一番:先搞到证书,再改程序; 

获取letsencrypt颁发的免费的SSL证书也是相对比较简单的,我还是个windows服务器,目前没能耐去折腾Linux,所以要下载letsencrypt-win-simple的安装包,运行letsencrypt.exe就开始了:第一步输入邮箱,如果不是第一次申请会跳过前两步,然后有5个选项供你选择,一般选M,输入M,Enter就到了让你输入需要证书的域,接着输入这个域对应的站点的根目录,输入一个线上运行的域即可,指定的根目录需要是能够直接访问的,因为他会访问你输入的域以及根目录下的某个文件,我很纳闷他是怎么在我站点新建的那些目录和验证文件,也就是说,他会在你指定的目录下新建两层目录和一个他需要访问的验证文件,准确的说他要知道这个乱码文件里的一段乱码内容来完成认证;完成认证后就会在C:\Users\Administrator\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org目录下生成证书文件;接下来的步骤就相对可以随意些了;

如果你就一个主域和一个站点,那么就可以拿证书去改程序了;

如果真的这样就完事了,那么是否感觉太快了,以致于没啥体验了;按照上面的步骤一个域下面可以生成一次证书,那么重复这些步骤,生成多个域下面的多个证书自然也是可以的了,问题在于必要性,或许折腾就是在为你的天真弱知买单;

Ok,我很天真;我为主域和两个二级域各生成了一次证书,接下来改程序咯!

我的站点是用Nodejs搭建的,内部由http-proxy代理来串起来的3个小站点,没有使用Nginx完全是为了以业余的玩性多去理解一点Nodejs;接下来主站监听443端口,二级站点由http-proxy代理分发;

var https=require('https'); var http=require('http'); var fs=require('fs'); var server = http.createServer(app); var httpsServer=https.createServer({ key: fs.readFileSync('./privatekey.pem'), cert: fs.readFileSync('./certificate.pem') },app); httpsServer.listen(443); server.listen(80);

代理中间件大概的样子:

app.use(function(req,res,next){ var proxy = httpProxy.createProxyServer({ headers:{ 'x-forward-ip':req.ip.match(/([\w\.]+)/g)[1] } }); proxy.on('error', function (err, req, res) { res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('Something went wrong.'); }); switch (req.headers.host){ case 'm.famanoder.cn': proxy.web(req, res, { target: 'https://localhost:2333' }); break; case 'cdn.famanoder.cn': proxy.web(req, res, { target: 'https://localhost:3222' }); break; default: next(); } });

这样主域用https访问一点问题没有,问题在于二级站点的访问浏览器始终会提示网站的证书不受信任,没办法,只好这样访问二级站点:https://cdn.famanoder.com:4000/,是的,带端口访问当然没问题,这样的话就没走代理了,可始终感觉不太方便,别扭,只能重想办法了;

又是一个机缘巧合,准备起身下班时看到了一篇文章,除了标题,全英文的,但直觉告诉了我,内容有我想要的东西;一脸懵逼的走马观花的看了一遍,果然豁然开朗了:在命令行里启动letsencrypt加--san参数来申请证书,可以为一个域绑定多个附带的域,也就说多个域可以共用同一套证书,那么代理的问题自然就解开了;输入主域后,再输入多个域用逗号隔开,然后他会依次去每个域验证,最后生成共用的一套证书;于是我决定了:今晚加餐!

Letsencrypt的验证方式为访问这个格式的地址:

http://cdn.famanoder.com/.well-known/acme-challenge/RHha4Dx3YaUzi7tu_C6p9mPk-TNpuLVN5hMQro2N1_Q

他会依次访问每个域的这个乱码文件,估计这个文件里有他想要的另一段乱码内容,打开看看就知道了;主站用的Express,cdn站点使用的原生Nodejs,两个站点的访问结果都是直接下载了文件,可能MIME头要改改,因为现在是多个域要访问同一个目录下的文件,索性在填写根目录时别填真正的根目录,而是填一个多个根目录共同所属的目录,比如D:\,修改路由文件如下:

// www(Express) app.get('/.well-known/acme-challenge/:ids',function(req,res,next){ require('fs').readFile('D:/.well-known/acme-challenge/'+req.params.ids,function(err,data){ err&&console.log(err); res.end(data); }); }); // www(Koa2) router.get('/.well-known/acme-challenge/:ids',async (cx,next)=>{ await next(); let data=await fs.readFileSync('D:'+cx.request.url); cx.response.body=data; }); // cdn if (req.url.indexOf('acme-challenge')!=-1) { var pathname=url.parse(req.url).pathname; fs.readFile('D:'+pathname,function(err,data){ err&&console.log(err); res.writeHead(200,{ 'content-type':'text/html' }); res.end(data); return false; }); } return false;

这样,多个域依次验证通过了,生成了同一套证书,有效期3个月,有效期内系统正常的话,3个月后会自动续期;那么就可以继续走http-proxy代理了,二级站点的https访问也不需要带端口了;接下来就是替换所有的http为https了,或者直接去掉协议,//www.famanoder.com格式也可以,浏览器会自动识别采用相应的协议;

由于Letsencrypt的验证域必须是线上可访问的,所以本地开发要另外配置,比如用Git自带的openssl生成一套证书作为开发调试时用也是可以的,只是浏览器会提示证书不受信用;

总之,说复杂也不复杂,说简单也不是那么简单,事情就是那么个事情,折腾就是为天真弱知买单嘛!

如果你已在路上,就勇敢的向前吧!






1/9

记录一些要点

以便于常记起时有据可循

WWW-Authenticate and 401

浅笑ゞ倾城
如果不想做个登录页面,还需要做用户认证,可以使用
WWW-Authenticate 
即:服务端在需要认证的页面,获取header上的authorization,
authorization = new Buffer(authorization, 'base64').toString()
验证是否存在和合法,验证不通过设置header返回401,浏览器就会自己弹窗提示输入验证信息,然后发送请求再次认证
cx.status = 401;
cx.set('WWW-Authenticate', 'Basic realm="famanoder.com"');
 

2017-11-21 17:26
0
0
f

vscode和flow相关的配置

famanoder
'types' can only be used in a .ts file 
文件 > 首选项 > 设置 
加一条"javascript.validate.enable": false

[flow] Experimental decorator usage 
.flowconfig的[options]下加一句
esproposal.decorators=ignore

vscode不支持Decorator,根目录新增jsconfig.json
{
   "compilerOptions": {
      "experimentalDecorators": true,
      "emitDecoratorMetadata": true
   }
}
 
2017-11-10 11:45
0
0

所有的奋斗,都是一种不甘平凡

浅笑ゞ倾城
很多时候,我们做很多事情,不是因为知道这件事能成功,而是因为相信它是对的。
更重要的是,我们期待着,终有一天,时间会证明它是对的。
—— Mr.李
2017-09-22 20:06
0
5
f

熬夜

famanoder
熬夜,是缓解压力的一种方式,世界都睡了,爹妈都睡了,老板都睡了,老师都睡了,竞争对手都睡了,全世界都睡了,你用这好不容易偷来的时光,赶紧做点自己喜欢的事儿。
2017-09-05 15:17
53
76

nginScript

浅笑ゞ倾城
Lua是一个强大的脚本语言,不过,在市场采用率方面仍然不是很理想,而且对于一线开发人员和DevOps工程师来说,它也不在他们的“必备技能”之列。
nginScript并不是要取代Lua,nginScript的目标是要通过使用一门流行的编程语言为广大的社区提供一种编程式的配置方案。
 
这段话明明意思就是:js比lua流行,nginScript要取代Lua!

2017-09-03 14:35
0
0
1/11
famanoder

famanoder loves you !

花名:花满楼

职业:Web前端

邮箱:915905174@qq.com

地址:前端江湖

描述:

花满楼的小站,一个小前端业余的自娱自乐;自打步入前端,从最初的html到HTML5,从最初的css到CSS3,从最初的ES3到ES6,从最初的JavaScript到Nodejs,从PC端到移动端,一路走来,浪迹前端 2 载有余,说实话,除了颜值,没什么拿的出手的了,仅以此记录年轻的追逐和前进的脚步!

join me

Friends

独乐乐,与众乐乐,孰乐?

有朋自远方来,不亦乐乎!

Repositories

Allways bet on JavaScript !

前端学习分享,与君共勉!