关于Chrome跨域The request client is not a secure context and the resource is in more-private address space loca相关提示的解决
最近想使用serve 配置一个本地的 chrome 脚本注入功能, 没想到浏览器提示:
Access to script at ‘http://localhost:85/index.js‘ from origin ‘http://www.xxx.com‘ has been blocked by CORS policy: The request client is not a secure context and the resource is in more-private address space local.
貌似是chrome有设置, 在地址栏中输入:chrome://flags/#block-insecure-private-network-requests
然后选Disabled ,relaunch 后就能恢复正常了, 根据翻译:
block-insecure-private-network-requests
防止非安全上下文向更私密的IP地址发出子资源请求。如果1)IP1是本地主机,而IP2不是,或者2)IP1是私有的,而IP2是公共的,则IP地址IP1比IP2更私有。这是全面实施CORS-RFC1918的第一步:https://wicg.github.io/cors-rfc1918–Mac、Windows、Linux、Chrome OS、Android、Fuchsia
阻止不安全的专用网络请求
应该是处于安全考虑, 禁止向私有地址请求和发生数据
直播服务器搭建方法
直播服务器搭建流程
- 服务器上安装node-media-server
- 本地安装ffmpeg
- 测试推流
- 浏览器查看直播内容
1. 安装node-media-server
## 在服务器上启动node-media-server 服务
docker run --name nms -d -p 1935:1935 -p 8000:8000 -p 8443:8443 illuspas/node-media-server
2. 本地安装 ffmpeg
- 下载解压对应版本的ffmpeg到本地: https://github.com/BtbN/FFmpeg-Builds/releases
- 添加环境变量
3. 测试推流
## 在本地找到视频文件目录, 执行推流命令
ffmpeg -re -i hello.mp4 -c copy -f flv rtmp://localhost/live/hello
4. 浏览器查看直播
使用NodePlayer.js 播放直播内容: https://github.com/illuspas/NodePlayer.js
<canvas id="video" width="640" height="480" data-url="ws://localhost:8000/live/hello"></canvas>
<input type="button" onclick="play()" value="play">
<script src="NodePlayer.js"></script>
<script>
function play() {
var url = document.getElementById("video").dataset.url;
var np = new Module.NodePlayer();
np.setPlayView('video');
np.setScaleMode(1);
np.on('start', () => {
Module.print('NodePlayer on start');
});
np.on('close', () => {
Module.print('NodePlayer on close');
});
np.on('error', (err) => {
Module.print('NodePlayer on error', err);
});
// np.enableVideo(true);
// np.enableAudio(true);
np.start(url);
}
</script>
相关下载
- node-media-server: https://github.com/illuspas/Node-Media-Server
- ffmpeg: https://github.com/BtbN/FFmpeg-Builds/releases
- NodePlayer: https://github.com/illuspas/NodePlayer.js
Espruino单片机上的javascript
话说一直想用javascript语法写单片机程序, 因为我本身是web开发出身, 太熟悉js语法了, 以至于看到c 或 python都感觉很别扭, 于是就在网上找到了这个espruino, espruino是一个固件, 可以让esp8266等芯片支持使用js语法编程, 大大减少了web人员学习单片机开发的成本, 甚至可以让本身会js的人直接上手, 了解基础api后, 就可以直接开发自己的单片机项目了, 这里是官网: https://www.espruino.com/ , Espruino文档: http://www.espruino.com/Reference#software
但是, 官网提供的开发工具用着很不习惯, 而且代码都在一个文件中, 很不方便管理.
于是我就自己根据espruino的aip, 自己写了个命令行工具, 可以使用自己熟练的ide, 然后配合命令行工具进行开发, 执行的时候就像nodejs一样方便, 目前这个命令行工具叫espjs, 文档地址: https://www.kancloud.cn/shuai/espjs
espjs开源地址 github: https://github.com/zhaishuaigan/espjs
espjs国内下载: https://fetch.ngapp.net/soft/espjs/espjs-latest.zip
这里简单说明一下使用方法:
- 将此压缩包里面的文件放到不包含空格和中文的目录中. 如 c:\espruino-tools
- 配置系统环境变量path, 添加 c:\espruino-tools
- 进入项目目录, 在目录的地址栏输入 cmd, 进入命令行.
- 输入espjs flash esp01s 烧写espruino固件
- 输入espjs upload 上传当前目录中的代码到设备
然后设备就开始运行代码了, 之后修改代码只需要执行upload 即可更新代码,
实例可参考 demo 目录下的文件
index.js 或 main.js 会被当做入口文件加载执行
注意事项:
1: 端口是自动选择的, 插上设备后会自动选择, 如果有多个设备, 可以使用port命令切换设备
2: 默认的波特率是115200, 如需修改请到config.json中修改
3: 如果要增加开发板支持, 请到config.json 的Flash字段追加
4: 模块不支持远程加载, 例如 require(“MQTT”) 会提示模块不存在, 解决方法是 手动下载mqtt模块(modules add MQTT), 然后使用 require(“modules/MQTT.min.js”) 进行引用.
小程序客服消息处理
三种消息类型:
// 文本消息
{
"signature": "ee6e400de7972484ec6f3014c2f77504925a4707",
"timestamp": "1552298008",
"nonce": "540004383",
"openid": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
"encrypt_type": "aes",
"msg_signature": "74c419155e49cefab8ab1dbd440b9389acc47e2a",
"URL": "http:\/\/qiang.lt.ngapp.net\/wechat\/noti/fy",
"ToUserName": "zhaishuaigan",
"FromUserName": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
"CreateTime": 1552293166,
"MsgType": "text",
"Content": "hello",
"MsgId": 1,
"Encrypt": "PloOW0ucj9SkMpMC...."
}
// 事件消息
{
"signature": "3e5860da822266b9f03f8d5380615f9be0ae2db7",
"timestamp": "1552301914",
"nonce": "693467019",
"openid": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
"encrypt_type": "aes",
"msg_signature": "eda0cdd567b35df4501ee2041e0d191db81798f2",
"ToUserName": "gh_cc23a0a84984",
"FromUserName": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
"CreateTime": 1552301914,
"MsgType": "event",
"Event": "user_enter_tempsession",
"SessionFrom": "open-type='contact'",
"Encrypt": "oMP\/xo2RdcbK07vvoxxxx....."
}
// 图片消息
{
"signature": "ebd79f0c44f01dc26ef83ffeeadbdb3af5b960da",
"timestamp": "1552302190",
"nonce": "1322948029",
"openid": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
"encrypt_type": "aes",
"msg_signature": "06613ca44e189d95140166898f80a27ab10baa80",
"ToUserName": "gh_cc23a0a84984",
"FromUserName": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
"CreateTime": 1552302190,
"MsgType": "image",
"PicUrl": "http:\/\/mmbiz.qpic.cn\/mmbiz_jpg\/WwPGxFUiaTRZ6zVvTTGVbhfa9Vic801ux7OHobAAiaD3xRMYeJzbic4ISvwn736dpK0OMTlaYvX7GoTRgE8LqObkIQ\/0",
"MsgId": 22223624286040849,
"MediaId": "3WiHLigPtkJtqoLvPD2HgPsAtb3vzDvTWyo0sP5s-dshtS7oZOlCW7c3RuD1nwBt",
"Encrypt": "gictSCCy+Zxxxx...."
}
ThinkPHP 5.1保存消息代码
$request = request()->param();
$data = [
'signature' => $request['signature'],
'timestamp' => $request['timestamp'],
'nonce' => $request['nonce'],
'openid' => $request['openid'],
'encrypt_type' => $request['encrypt_type'],
'msg_signature' => $request['msg_signature'],
'to_username' => $request['ToUserName'],
'from_username' => $request['FromUserName'],
'msg_type' => $request['MsgType'],
'msg_id' => isset($request['MsgId']) ? $request['MsgId'] : '',
'encrypt' => isset($request['Encrypt']) ? $request['Encrypt'] : '',
];
$msgInfo = [];
switch ($request['MsgType']) {
case 'text':
$msgInfo['text'] = $request['Content'];
break;
case 'image':
$msgInfo['pic'] = $request['PicUrl'];
$msgInfo['media_id'] = $request['MediaId'];
break;
case 'event':
$msgInfo['event'] = $request['Event'];
$msgInfo['session_from'] = $request['SessionFrom'];
break;
}
$data['msg_info'] = json_encode($msgInfo);
CustomerMessage::create($data);
return '';
数据库表结构设计
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateCustomerMessageTable extends Migrator
{
public function change()
{
$this->table('customer_message')
->addColumn(Column::string('signature')
->setDefault('')
->setComment('签名'))
->addColumn(Column::integer('timestamp')
->setDefault(0)
->setComment('时间戳'))
->addColumn(Column::string('nonce')
->setDefault('')
->setComment('随机数'))
->addColumn(Column::string('openid')
->setDefault('')
->setComment('客户id'))
->addColumn(Column::string('encrypt_type')
->setDefault('')
->setComment('加密方式'))
->addColumn(Column::string('msg_signature')
->setDefault('')
->setComment('消息签名'))
->addColumn(Column::string('to_username')
->setDefault('')
->setComment('消息接收者'))
->addColumn(Column::string('from_username')
->setDefault('')
->setComment('消息来源'))
->addColumn(Column::string('msg_type')
->setDefault('')
->setComment('消息类型'))
->addColumn(Column::text('msg_info')
->setNull(true)
->setComment('消息内容'))
->addColumn(Column::string('msg_id')
->setDefault('')
->setComment('消息id'))
->addColumn(Column::text('encrypt')
->setNull(true)
->setComment('加密数据'))
->addColumn(Column::dateTime('create_time')
->setDefault('CURRENT_TIMESTAMP')
->setComment('创建时间'))
->addColumn(Column::dateTime('update_time')
->setDefault('CURRENT_TIMESTAMP')
->setComment('更新时间'))
->addColumn(Column::dateTime('delete_time')
->setNull(true)
->setComment('删除时间'))
->create();
}
}
写给刚入行的程序员
源地址: 顶级程序员
1.作为前端开发者,使用双显示器能大幅提高开发效率。
2.学编程最好的语言不是PHP,是English。
3.自己做的东西交付之前先测试一遍。
4.问别人之前最好先自己百度,google一下,以免问出太低级的问题。
5.把觉得不靠谱的需求放到最后做,很可能到时候需求就变了,或者取消了。
6.读好书,垃圾书会浪费你时间。
7.不要炫技,面向人脑编程更便于维护。
8.没事别重复造轮子,你造的轮子大多数时候只有你觉得好用。接手你的轮子的人会在背后骂你上百遍。
9.不要先写框架再写实现。最好反过来,从原型中提炼框架。
10.新技术一定不要找书,书一旦印出来就过时了。
11.请勿久坐,多喝水,尤其是遇到很久都解决不了的问题的时候,多走动走动。
12.考虑可维护性比考虑性能更重要。
13.越难解决的bug往往犯的错误越低级。
14.比起鼓励师,不如给程序员找一个靠谱的产品经理。
15.熬夜低效率写代码,不如好好睡觉。
16.你遇到的问题,大多数人都遇到过,并且网上都有完整的解决方案,你找不到,只是你懒得去找。
17.多沟通,不少加班工作是由于沟通少造成的。
18.普通程序员+google=超级程序员。实在不行,百度也可以,学会利用搜索引擎来辅助自己解决问题。
19.早点找女朋友,生活作息会更健康。你懂的!
20.永远别小看程序媛。即使是青铜,说不定背后有个王者在帮她。
nodejs开发的神器 now
now是什么?
now 允许您轻松、快速和可靠地将JavaScript(Node.js)或Docker支持的网站、应用程序和服务带到云中。实际上,包含package.json或Dockerfile的任何目录都可以通过一个命令:now传输到云。
每次部署一个项目,now 将提供一个新的、唯一的URL(甚至在上传完成之前)。这些URL将看起来像这样(我的应用程序-随机字符串):my-app-erkgfjtrna.now.sh 。
当您部署到生产时,您只需选择适当的别名(自定义域)即可。
官网地址: https:/zeit.co
使用方法
- 下载命令行工具:
npm install -g now
- 创建开发目录
mkdir my-project && cd my-project
- 创建package.json
{
"name": "koa",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"koa": "^2.6.1"
}
}
- 创建index.js
const Koa = require('koa');
const app = new Koa();
app.use(ctx => {
ctx.body = 'Hello Koa';
});
app.listen(80);
- 登录
now login
然后输入邮箱地址收取验证邮件, 点击邮件里的验证链接, 这里需要翻墙, 因为验证页面有个js在google上. - 执行
now --public
会输出类似下面的结果.> Deploying D:\xxxx\my-project under shuai
> Synced 2 files (366B) [1s]
> Using Node.js 8.11.3 (default)
> https://my-project-lcjucjkwmi.now.sh [in clipboard] (sfo1) [3s]
> Building…
- 执行完成后, 就可以打开上面的地址看到运行结果
别名使用
now --public && now alias shuai
即可生成一个 shuai.now.sh 的地址, 方便记忆
使用自己的域名
now --public && now alias shuai.com
需要根据提示验证域名所有权就能使用自己的域名访问了, 而且自动生成https证书
Vagrant+Virtual Box 快速搭建开发环境
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
# config.vm.network "forwarded_port", guest: 80, host: 80
# config.vm.network "forwarded_port", guest: 3306, host: 3306
config.vm.network "private_network", ip: "10.0.0.3"
config.vm.provision "shell", inline: <<-SHELL
# 更换aliyun软件源
cp /etc/apt/sources.list /etc/apt/sources.list.bak
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse' > /etc/apt/sources.list
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse' >> /etc/apt/sources.list
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse' >> /etc/apt/sources.list
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse' >> /etc/apt/sources.list
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse' >> /etc/apt/sources.list
apt-get update
# 安装docker
apt-get -y install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
apt-get -y update
apt-get -y install docker-ce docker-compose
# 使用aliyun加速docker镜像
mkdir -p /etc/docker
echo '{' > /etc/docker/daemon.json
echo ' "registry-mirrors": ["https://kag9wqej.mirror.aliyuncs.com"]' >> /etc/docker/daemon.json
echo '}' >> /etc/docker/daemon.json
systemctl daemon-reload
systemctl restart docker
# 把vagrant用户添加到 docker 组
usermod -G docker vagrant
# ssh登录后, 进入/vagrant目录, 并启动docker compose , 然后 输出一下当前正在运行的容器
echo 'cd /vagrant && docker-compose up -d && docker ps' >> /home/vagrant/.bashrc
SHELL
end
Ant Design
一个服务于企业级产品的设计体系,基于『确定』和『自然』的设计价值观和模块化的解决方案,让设计者专注于更好的用户体验。
官网: https://ant.design/index-cn
文档: https://ant.design/docs/react/introduce-cn
Ant Design of React
这里是 Ant Design 的 React 实现,开发和服务于企业级后台产品。
特性
- 提炼自企业级中后台产品的交互语言和视觉风格。
- 开箱即用的高质量 React 组件。
- 使用 TypeScript 构建,提供完整的类型定义文件。
- 全链路开发和设计工具体系。
支持环境
- 现代浏览器和 IE9 及以上(需要 polyfills)。
- 支持服务端渲染。
- Electron
安装
使用 npm 或 yarn 安装#
我们推荐使用 npm 或 yarn 的方式进行开发,不仅可在开发环境轻松调试,也可放心地在生产环境打包部署使用,享受整个生态圈和工具链带来的诸多好处。
$ npm install antd --save
$ yarn add antd
如果你的网络环境不佳,推荐使用 cnpm。
浏览器引入
在浏览器中使用 script 和 link 标签直接引入文件,并使用全局变量 antd。
我们在 npm 发布包内的 antd/dist 目录下提供了 antd.js antd.css 以及 antd.min.js antd.min.css。你也可以通过 或 UNPKG 进行下载。
强烈不推荐使用已构建文件,这样无法按需加载,而且难以获得底层依赖模块的 bug 快速修复支持。
注意:3.0 之后引入 antd.js 前你需要自行引入 moment。
示例
import { DatePicker } from 'antd';
ReactDOM.render(<DatePicker />, mountNode);
引入样式:
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
按需加载
下面两种方式都可以只加载用到的组件。
使用 babel-plugin-import(推荐)。
// .babelrc or babel-loader option
{
"plugins": [
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }] // `style: true` 会加载 less 文件
]
}
注意:webpack 1 无需设置 libraryDirectory。
然后只需从 antd 引入模块即可,无需单独引入样式。等同于下面手动引入的方式。
// babel-plugin-import 会帮助你加载 JS 和 CSS
import { DatePicker } from 'antd';
手动引入
import DatePicker from 'antd/lib/date-picker'; // 加载 JS
import 'antd/lib/date-picker/style/css'; // 加载 CSS
// import 'antd/lib/date-picker/style'; // 加载 LESS
Vant - 有赞移动端 Vue 组件库
A Vue.js 2.0 Mobile UI at YouZan
特性
- 50+ 个经过有赞线上业务检验的组件
- 单元测试覆盖率超过 90%
- 完善的中英文文档和示例
- 支持 babel-plugin-import
- 支持 TypeScript
- 支持 SSR
安装
npm i -S vant
快速上手
方式一. 使用 babel-plugin-import (推荐)
# 安装 babel-plugin-import 插件
npm i babel-plugin-import -D
// 在 .babelrc 或 babel-loader 中添加插件配置
// 注意:webpack 1 无需设置 libraryDirectory。
{
"plugins": [
["import", {
"libraryName": "vant",
"libraryDirectory": "es",
"style": true
}]
]
}
接着你可以在代码中直接引入 Vant 组件,插件会自动将代码转化为方式二中的按需引入形式。
import { Button } from 'vant';
方式二. 按需引入组件
import Button from 'vant/lib/button';
import 'vant/lib/vant-css/base.css';
import 'vant/lib/vant-css/button.css';
方式三. 导入所有组件
import Vue from 'vue';
import Vant from 'vant';
import 'vant/lib/vant-css/index.css';
Vue.use(Vant);
CDN
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/vant/lib/vant-css/index.css">
<!-- 引入组件 -->
<script src="https://unpkg.com/vant/lib/vant.min.js"></script>
更多内容请参考 快速上手.
贡献代码
修改代码请阅读我们的 开发指南。
使用过程中发现任何问题都可以提 Issue 给我们,当然,我们也非常欢迎你给我们发 PR。
浏览器支持
现代浏览器以及 Android 4.0+, iOS 6+.
手机预览
可以手机扫码以下二维码访问手机端 demo:
链接
开源协议
本项目基于 MIT 协议,请自由地享受和参与开源。