编程

使用 axios 请求后端模型时,有一些最佳实践可以帮助你编写更健壮、可维护的代码。以下是一些常见的最佳实践:

1. 创建 API 服务层

axios 请求封装在专门的服务层中,而不是在组件中直接编写请求代码。这样可以提高代码的可复用性、可测试性并保持组件的清晰。

示例:

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
// api.js
import axios from 'axios';

// 创建 axios 实例
const apiClient = axios.create({
baseURL: 'https://your-api-endpoint.com',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem('token')}` // 如果需要身份验证
}
});

// 获取用户信息
export function getUserInfo(userId) {
return apiClient.get(`/users/${userId}`);
}

// 更新用户信息
export function updateUserInfo(userId, data) {
return apiClient.put(`/users/${userId}`, data);
}

// 创建用户
export function createUser(data) {
return apiClient.post('/users', data);
}

然后在 Vue 组件中使用这些 API 方法:

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
// UserProfile.vue
import { getUserInfo, updateUserInfo } from './api';

export default {
data() {
return {
user: {}
};
},
mounted() {
this.fetchUserInfo(1); // 获取用户信息
},
methods: {
async fetchUserInfo(userId) {
try {
const response = await getUserInfo(userId);
this.user = response.data;
} catch (error) {
console.error('Error fetching user info:', error);
}
},
async saveUserInfo() {
try {
const response = await updateUserInfo(this.user.id, this.user);
this.user = response.data;
} catch (error) {
console.error('Error saving user info:', error);
}
}
}
};

2. 错误处理

始终为 API 请求添加错误处理,避免应用崩溃并提供用户友好的反馈。你可以使用 try/catchasync/await)或者 then/catch(Promise)来捕获错误。

示例:

1
2
3
4
5
6
7
8
try {
const response = await axios.get('/api/endpoint');
// 成功处理
} catch (error) {
console.error('API请求失败', error);
// 错误提示
this.$toast.error('请求失败,请稍后重试');
}

你还可以根据错误的类型和状态码,做出不同的响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
axios.get('/api/endpoint')
.then(response => {
// 处理响应数据
})
.catch(error => {
if (error.response) {
// 请求已发出,且服务器响应了状态码
if (error.response.status === 401) {
// 处理未授权错误
} else if (error.response.status === 500) {
// 处理服务器错误
}
} else if (error.request) {
// 请求已发出,但没有响应
console.error('没有响应');
} else {
console.error('发生了其他错误', error.message);
}
});

3. 请求拦截器和响应拦截器

使用 axios 的拦截器来处理请求和响应。请求拦截器可以在发送请求之前做一些通用处理(例如添加认证信息),响应拦截器可以统一处理错误。

请求拦截器:

1
2
3
4
5
6
7
8
9
10
11
12
13
apiClient.interceptors.request.use(
config => {
// 可以在请求头中添加认证信息或其他全局信息
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => {
return Promise.reject(error);
}
);

响应拦截器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiClient.interceptors.response.use(
response => {
// 可以在这里做响应的统一处理,例如根据返回的状态码做全局的处理
return response;
},
error => {
// 统一错误处理
if (error.response.status === 401) {
// 处理未授权,可能是用户需要重新登录
alert('未授权,请重新登录');
}
return Promise.reject(error);
}
);

4. 请求的参数和数据结构

确保你发送到后端的请求数据结构与后端期望的模型一致。你可以通过 axiosparams(GET 请求)或 data(POST 请求)属性来绑定数据。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
// GET 请求
axios.get('/api/users', {
params: {
page: 1,
limit: 10
}
});

// POST 请求
axios.post('/api/users', {
name: 'John Doe',
email: '[email protected]'
});

5. 全局配置和环境变量

如果有多个接口或后端环境,使用环境变量来管理不同的 API 根路径、API 密钥等。

示例:

1
2
3
4
5
6
const apiClient = axios.create({
baseURL: process.env.VUE_APP_API_BASE_URL || 'https://your-api-endpoint.com',
headers: {
'Content-Type': 'application/json'
}
});

然后在 .env 文件中设置环境变量:

1
VUE_APP_API_BASE_URL=https://dev.api.com

6. 分页和懒加载

对于数据量大的接口,建议使用分页、懒加载等技术来优化性能。通过在请求中添加分页参数,将数据分批获取,避免一次性请求大量数据。

示例:

1
2
3
4
5
6
7
8
9
10
async fetchUsers(page = 1, limit = 20) {
try {
const response = await axios.get('/api/users', {
params: { page, limit }
});
this.users = response.data;
} catch (error) {
console.error(error);
}
}

7. 缓存和重复请求防止

如果某些请求会多次发送相同的数据,可以考虑缓存请求结果,或者在发送新请求之前,检查是否已发起了相同请求。

总结

  • 封装 API 服务层:将 axios 请求抽象成服务方法,方便管理和复用。
  • 错误处理:处理请求失败的情况,显示用户友好的错误信息。
  • 请求和响应拦截器:统一处理请求和响应,尤其是认证和错误处理。
  • 避免重复请求:缓存或防止发送重复的请求。
  • 分页和懒加载:提高性能,避免一次性加载大量数据。

这样,你的 axios 请求会更加清晰、可维护,并且具有良好的扩展性。

话不多说,先看效果,非常之暴力+魔幻。

很多年前看到b站的弹幕,就非常想开发一个可以全网弹幕的工具。
彼时,还没有ChatGPT这么强大的伙伴,而我,一个前端菜鸡,想完成这一切是非常难的。
而如今不同了,在ChatGPT的加持下,我,已然成长为一个StrongMan!

事情应该从前几天开始说起,这不,最近闲下来的我想给自己的博客的主机源码升级一下评论的插件,写着写着忽然想到,如果做成弹幕岂不是更好玩?然后又想起曾经想要做的全网弹幕插件,想到是不是可以用tampermonkey来实现。于是先用tampermonkey先简单实现了一版,但是又觉得但单调了。以来很多人不想用tampermonkey,也不想再为这个功能专门装个tampermonkey,此外既然是弹幕,多少得加上一些设置功能,设置特效啊啥的,所以就干脆写成独立的插件吧。然后就在ChatGPT的帮助下爆肝几个晚上开发了这个弹幕插件–弹幕局v1.0
在ChatGPT的帮助下,源码很快就写出来了。

安装了这个插件之后,在网页上按下”F4“即可唤出这个弹幕面板,输入内容就可以发送弹幕了。
值得一提的是,可以允许用户切换频道,后端我已经完全开源出来了(基于CloudFlare的Pages),源码在这里:https://github.com/Chorder/danmuju,你可以基于开源的后端源码,搭建一个只属于你和你小伙伴的专属私人弹幕频道,这样相对来说就更加私密和安全了。
这个开源的后端是基于CloudFlare的Pages构建的,如果你对Pages很熟悉,应该一看就明白,只需要克隆仓库过去,用wrangler 创建一个D1数据库,然后在pages项目上绑定数据库,配置从Github仓库构建,框架选Vue/Vite,即可。如果你对上述这些不是很熟悉,也不用着急,过段时间我会再详细补充一下文档。

弹幕局插件包含一个设置界面,这里可以开启和关闭弹幕,也可以设置弹幕的字体和字号、速度等,一开始甚至想要加上自定义css,不过想到css可能会引入很多的安全问题,就这样也够用了,那就先这样吧,以后的版本有时间可以再慢慢完善。

目前的弹幕可以横着飞,竖着非,斜着飞,嘎嘎乱飞,已经很暴力了,我个人很喜欢,哈哈!

对了,怎么安装:

目前火狐的插件已经上传了正在审核中,审核完成我挥第一时间在这里分享。Chrome的插件想要上传得支付5美金,算了算了,还是走开源路线吧。。。

所以想要尝鲜的小伙伴可以从Github直接下载客户端源码或者压缩包,临时加载插件,方法如下:

插件源码地址:

Chrome:https://github.com/Chorder/danmuju/tree/master/clients/danmuju-chrome
Firefox:https://github.com/Chorder/danmuju/tree/master/clients/danmuju-firefox

压缩包下载地址:

https://github.com/Chorder/danmuju/tree/master/clients

上面链接打开之后有两个压缩包:danmuju-chrome_1.0.zip 和 danmuju-firefox_1.0.zip,需要哪个版本就下载哪个版本。下载下来解压之后就能看到源代码,觉得哪里不爽就自己改(改完可以PR到仓库呀!)
尤其是如果觉得快捷键(目前是F4)用的不爽,可以修改插件源码content.js的第501行,修改成你想要的快捷键即可。

火狐,点击临时加载附加组件,选择danmuju-firefox_1.0.zip即可安装。

Chrome和Edge,打开开发模式,直接把压缩包下载下来解压,然后点击”加载解压缩的拓展“即可安装。

经过测试,Chrome版的zip是可以在Edge良好运行的。如果安装之后看不到弹幕,需要点开插件的设置面板,把弹幕开关开启一下。

安装好弹幕,打开百度或者这个网页,你应该可以看到我发的测试弹幕了。

最后关于全网弹幕这个思路,再简单讲几点

  1. 安全
    这个插件最应该防范的就是前端攻击,例如XSS、浏览器沙箱逃逸等。前者我已经测试过基本没啥问题,dom型和非dom型的xss都测试过,希望大佬们再帮忙测一测,如有bug希望即使反馈(也可以在Github直接提交PR修了,哈哈哈哈)
    而沙箱逃逸嘛这个。。但凡有这种漏洞想必遭殃的也不止这一个插件了。

  2. 可玩性
    这个东西我之所以想要开发,就是希望当我们在浏览任何网页的时候,都能有网友在旁边提供帮助,增加网页的交互性。

  3. 后续期待

希望这个东西可以给Web3.0时代增添更多的乐趣,我觉得弹幕是一个有趣的发明。我能想到的一些好玩的使用场景,比如说在配置内网地址192.168.x.x的路由器的时候,跨域弹幕会很好玩,它就像有个网友老司机在身边指导你。

目前服务端和客户端都开源在了https://github.com/Chorder/danmuju
希望多多支持,多多PR~

另外给插件写了个简单的官网,在这里,以后有重要内容会在官网上更新:https://danmuju.pages.dev/

Windows系统下C语言中使用自定义包的方法:

首先明确GOPATH的路径,执行go env | findstr GOPATH

1
2
3
4
C:\Users\CHORDER>go env | findstr GOPATH
set GOPATH=C:\Users\CHORDER\go

C:\Users\CHORDER>

接着在GOPATH目录中创建相应的自定义包,这里定义一个example包,并创建两个源码文件src1.gosrc2.go,源码内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* C:\Users\CHORDER\go\src\chorder.net\example\src1.go */

package example

import "fmt"

func init(){
fmt.Printf("\nchorder.net/example/src1.go init() has been called.")
}

func Src1(){
fmt.Printf("\nchorder.net/example/src1.go Src1() has been called.")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
/*C:\Users\CHORDER\go\src\chorder.net\example\src2.go*/

package example

import "fmt"

func init(){
fmt.Printf("\nchorder.net/example/src2.go init() has been called.")
}

func Src2(){
fmt.Printf("\nchorder.net/example/src2.go Src1() has been called.")
}

编写代码调用这两个包中的方法:

packge_test.go

1
2
3
4
5
6
7
8
package main

import "chorder.net/example"

func main(){
example.Src1()
example.Src2()
}

执行结果:

1
2
3
4
5
6
>go run packge_test.go

chorder.net/example/src1.go init() has been called.
chorder.net/example/src2.go init() has been called.
chorder.net/example/src1.go Src1() has been called.
chorder.net/example/src2.go Src1() has been called.

最近的这几个VirtualBox版本(6.1.4、6.1.6、6.1.8)比以前多了一些变化,主要体现在Guest Additions上。

在6.1.4、6.1.6的版本里,曾经遇到过虚拟机和宿主机(Guest and Host)之间不能共享粘贴板(Clipboard)的bug,以及Windows 7、Debian10的Guest机器无法全屏的Bug。

之前的解决方法是,在 VirtualBox官网上下载Virtualbox 6.1.2版本的Guest Additions ISO,挂载并且安装ISO镜像中的VBoxLinuxAdditions.run文件后,即可解决这些问题。

但在今天的6.1.8版本的Release Changelog中,提到已经解决了多个这样的Bug,于是试试运气,结果遇到这样的问题:

1
VboxClient: The parent session seems to be non-X11. Exiting...

这里分享我在Windows 10 Host,Debian 10.0 Guest上的解决方法:

先注销当前用户:

再在登录的时候选择X11选项:

即可解决。

0x00 前言

Rails 6.0 发布已经有一段时间了,之前没有什么项目可以练手,最近总算遇到可以使用Rails 6开发的场景了。Rails 6中新增了一些功能和特性,有一些内容官方文档里并没有写的很具体,所以在摸索的过程中也遇到了一些坑点。这里以一个新工程从头到尾的构建,来简单记录在Rails6中使用jQuery和Bootstrap的过程。希望能够给新来的同学做个参考。

编程和码字的水平有限,如有错漏敬请指教,也请多包涵!下面就开始吧。

0x01 环境准备

  • 操作系统: Debian 10 ( 4.19.0-8-amd64 )
  • Ruby版本: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
  • Rails版本: Rails 6.0.2.1
1
2
3
4
5
6
7
test@debian:~$uname -a
Linux debian 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64 GNU/Linux
test@debian:~$ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
test@debian:~$rails -v
Rails 6.0.2.1

0x02 创建项目

这里新建一个项目“TestApp”,并在其中建立控制器“Test”和测试方法“test”:

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
test@debian:~$rails new TestApp
create
create README.md
create Rakefile
create .ruby-version
create config.ru
create .gitignore
create Gemfile
...
├─ [email protected]
├─ [email protected]
└─ [email protected]
Done in 59.74s.
Webpacker successfully installed 🎉 🍰
test@debian:~/TestApp$rails g controller Test test --no-stylesheets
Running via Spring preloader in process 22413
create app/controllers/test_controller.rb
route get 'test/test'
invoke erb
create app/views/test
create app/views/test/test.html.erb
invoke test_unit
create test/controllers/test_controller_test.rb
invoke helper
create app/helpers/test_helper.rb
invoke test_unit
invoke assets
invoke scss
test@debian:~$

创建好之后,修改test页面,添加一个表单和按钮,用于稍后测试Bootstrap。(在执行创建控制器和方法的命令后,Rails已经为我们自动添加了到Test控制器test方法的路由,所以不需要我们再新增路由。)

app/views/test/test.html.erb 代码:

1
2
3
4
5
6
7
<h1>Test#test</h1>
<p>Find me in app/views/test/test.html.erb</p>

<form>
<input id="test" type="text"/>
<button id="test_btn">点我</button>
</form>

启动Rails服务,访问http://localhost:3000/test/test:

1
2
3
4
5
6
7
8
9
10
11
test@debian:~/TestApp$rails s
=> Booting Puma
=> Rails 6.0.2.1 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.1 (ruby 2.6.5-p114), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop

此时应用已经创建成功。

0x03 添加jQuery和Bootstrap库

这里采用yarn作为Javascript包管理器。在TestApp目录中运行bin/yarn,如果出现以下内容,说明yarn没有安装:

1
2
3
test@debian:~/TestApp$bin/yarn
Yarn executable was not detected in the system.
Download Yarn at https://yarnpkg.com/en/docs/install

安装方法在这里, 以当前使用的Debian 10为例,安装的方法是:

1
2
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

安装好yarn之后,就可以用yarn添加jQuery包和Bootstrap包:

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
test@debian:~/TestApp$yarn add jquery 
yarn add v1.21.1
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > [email protected]" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning "webpack-dev-server > [email protected]" has unmet peer dependency "webpack@^4.0.0".
[4/4] Building fresh packages...

success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ [email protected]
info All dependencies
└─ [email protected]
Done in 9.98s.
test@debian:~/TestApp$yarn add bootstrap
yarn add v1.21.1
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > [email protected]" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning "webpack-dev-server > [email protected]" has unmet peer dependency "webpack@^4.0.0".
warning " > [email protected]" has unmet peer dependency "popper.js@^1.16.0".
[4/4] Building fresh packages...

success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ [email protected]
info All dependencies
└─ [email protected]
Done in 13.33s.

由于Bootstrap还需要基于popper.js,不装的话会报依赖错误,所以安装一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
test@debian:~/TestApp$yarn add popper.js
yarn add v1.21.1
[1/4] Resolving packages...
warning [email protected]: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > [email protected]" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning "webpack-dev-server > [email protected]" has unmet peer dependency "webpack@^4.0.0".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ [email protected]
info All dependencies
└─ [email protected]
Done in 11.78s.

安装的执行结果:

因为众所周知的原因,网速慢的同学就尴尬了,这里可能要等很久,所以你需要选一个科学一点的方式。

此时查看TestApp/node_modules目录,所需的前端库已经添加好了:

1
2
3
4
5
6
7
test@debian:~/TestApp$ls node_modules/jquery/
AUTHORS.txt bower.json dist external LICENSE.txt package.json README.md src
test@debian:~/TestApp$ls node_modules/bootstrap/
dist js LICENSE package.json README.md scss
test@debian:~/TestApp$ls node_modules/popper.js/
dist index.d.ts index.js.flow package.json README.md src
test@debian:~/TestApp$

0x04 使用Bootstrap

跟Rails5有所不同的是,Rails6采用webpack打包的方式,把需要打包的资源统一放在一个文件里(Rails6之前是采用Gemfile的方式引入第三方库,再通过Asset Pipeline汇聚)。

于是在安装好所需的前端库之后,就需要在app/javascript/packs/application.js中先引用它:

以Bootstrap为例,在其中添加import 'bootstrap'引入语句:

与此同时还需要在application.scss中引入Bootstrap的CSS样式表:

app/assets/stylesheets/application.scss文件中添加@import "bootstrap/dist/css/bootstrap";


2020/05/28 Patch

纠个错,如果想要通过@import "bootstrap/dist/css/bootstrap";的方式引用bootstrap相关的CSS,需要把app/assets/stylesheets/application.css文件重命名为app/assets/stylesheets/application.scss
如果直接使用app/assets/stylesheets/application.css的话,那么采用如下方式来引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* File: app/assets/stylesheets/application.css
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require bootstrap/dist/css/bootstrap
*= require_tree .
*= require_self
*/

Ending Patch


接着继续修改app/views/test/test.html.erb文件中的代码,添加相应的CSS类来测试Bootstrap是否已经引入成功:

1
2
3
4
5
6
7
8
9
<h1>Test#test</h1>
<p>Find me in app/views/test/test.html.erb</p>

<form>
<div class="form-group">
<input id="test" type="text" class="form-control"/>
<button id="test_btn" class="btn btn-success">点我</button>
</div>
</form>

启动应用,再次访问测试页面:

虽然界面有点丑,但是从渲染效果来看,Bootstrap已经成功引入了。

0x05 使用jQuery

继续修改app/javascript/packs/application.js,添加用于测试jQuery的代码:

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
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")


// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

import 'bootstrap'

$(document).on('turbolinks:load', function(){
$("#test_btn").click(function(){
alert($("#test").val());
});
});

保存并运行,刷新https://localhost:3000/test/test页面,发现添加的代码无法执行,控制台中有报错:

1
2
ReferenceError: $ is not defined 
application.js:21

这是因为jQuery库也需要引入一下,但是引入的方式有些不同,并不是在页面中直接引入,而是需要在config/webpack/environment.js中添加以下引入代码:

1
2
3
4
5
6
var webpack = require('webpack');
environment.plugins.append( 'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
})
)

通过声明一个全局的导出,就可以在全局的JS代码文件中使用”$”符号了。

刷新并再次访问,代码能够运行,控制台也没有再报错,说明jQuery已经成功集成:

另一种方法

还有一种方法是通过在JS文件按中使用import $ from 'jquery'来使”$”符生效,但是这样比较繁琐,需要在每个JS文件中出现,所以不再介绍了,当然,也提供一下详细的代码参考

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
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")


// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

import 'bootstrap'
import $ from 'jquery' // 在每个JS文件中加上这一行,也可以替代声明全局变量。

$(document).on('turbolinks:load', function(){
$("#test_btn").click(function(){
alert($("#test").val());
});
});

0x06 总结

在网上主要参考了这篇文章。Rails 6中的变化还是挺大的,不知道webpack会不会真的成为Rails的未来,感觉之前使用coffee script来写JS的同学不是很多,但是我倒是已经非常习惯于使用它来开发前端功能了。

但是想必Rails的先驱们有着他们更成熟的考虑吧,那就一起继续探索好了。

最近有不少好剧,有时候网速不好追剧太累了,而且有的有广告。看了一下几个主流的视频网站,有不少都还是用的标准的hls协议,没有在此基础上做修改(所以容易导致影视资源泄漏)。用标准hls协议的好处就是我们可以基于hls协议很方便地将影视资源多线程快速下载到本地,既可以流畅观看又可以去广告(部分)。

于是写了一个多线程的m3u8的文件下载器,基于python3纯原生库,安全放心:

代码链接:

https://github.com/Chorder/m3u8_downloader

顺便说一句,m3u8文件挺有意思的,结合ffmepg的缺陷,曾经爆出过播放器任意文件读取漏洞 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-1897 ,但是亲测在浏览器中m3u8文件其实还有更多妙用。感兴趣的童鞋可以进一步玩耍一下。

在PostgresSQL中如果尝试删除一个用户,可能会遇到这个报错:

1
2
ERROR:  role "XXX" cannot be dropped because some objects depend on it
DETAIL: privileges for table YYY

这是因为没有撤销该用户的权限所导致的。

具体以一个例子来说明。创建一张叫做“xxx”的表,再创建一个“test”用户,并将这张表的所有权限赋予“test”用户。

直接尝试删除这个用户,就会出现这个权限提示。

1
2
3
4
5
6
7
8
9
root=# CREATE TABLE xxx ( id SERIAL PRIMARY KEY , name CHAR(15) NOT NULL );
CREATE TABLE
root=# CREATE USER test PASSWORD 'test';
CREATE ROLE
root=# GRANT ALL ON xxx TO test;
GRANT
root=# DROP USER test;
ERROR: role "test" cannot be dropped because some objects depend on it
DETAIL: privileges for table xxx

可以通过下面这条语句查询PG中“test”用户的权限,并根据查询到的结果撤销之。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root=# SELECT * FROM information_schema.table_privileges WHERE grantee='test';
grantor | grantee | table_catalog | table_schema | table_name | privilege_type | is_grantable | with_hierarchy
---------+---------+---------------+--------------+------------+----------------+--------------+----------------
root | test | root | public | xxx | INSERT | NO | NO
root | test | root | public | xxx | SELECT | NO | YES
root | test | root | public | xxx | UPDATE | NO | NO
root | test | root | public | xxx | DELETE | NO | NO
root | test | root | public | xxx | TRUNCATE | NO | NO
root | test | root | public | xxx | REFERENCES | NO | NO
root | test | root | public | xxx | TRIGGER | NO | NO
(7 rows)

root=# REVOKE ALL ON xxx FROM test;
REVOKE
root=# DROP USER test;
DROP ROLE
root=#

批量撤销用户在数据库中所有表的权限:

1
2
revoke all on database XX from test;
revoke all on all tables in schema public from test;

PG权限的基本操作

赋予权限的语句是

1
GRANT *privilege ON *obj TO *user

撤销权限的语句从语法上与之对应:

1
REVOKE *privilege ON *obj FROM *user
  • privilege − SELECT,INSERT,UPDATE,DELETE, RULE,ALL
  • obj − 要授予访问权限的对象名称,可以是 table, view,sequence
  • user可以是以下情况
    • PUBLIC − 所有用户
    • GROUP group − 用户组
    • username − 用户名 (PUBLIC 是代表所有用户的简短形式)

删除用户:

查看用户权限:

先介绍一下:

XVA是Citrix XenServer导出的虚拟机格式镜像

OVA是Virtualbox常见的开放虚拟映像

RAW是纯粹的磁盘映像文件

在多个虚拟化平台之间进行镜像转换时,思路是先将特定平台镜像转换成中间映像(RAW),再转换成目标平台的虚拟化格式。

从Citrix XenServer XVA文件转Virtualbox格式时,先将xva转换成raw,运行:

1
qemu-img convert -O raw target.xva output.raw

qemu-img包含在Debian系的qemu-utils软件包中,如果没有,安装即可:

1
apt-get install qemu-utils

转换完成后,得到output.raw,再使用Virtualbox的VBoxManage将raw转换成VHD,就可以在Virtualbox使用了(似乎也可以在Vmware中使用)。

1
2
"c:Program Files\Oracle\VirtualBox\VBoxManage.exe" convertfromraw output.raw output.vhd --format VHD

参考自:

https://bart.jakubowski.in/2013/10/21/xva-to-vhd/

XenServer默认是没有ISO镜像目录的,如果需要创建自定义镜像的虚拟机,需要先创建ISO光盘映像目录,再导入镜像。方法如下:

首先登录XenServer,运行如下命令,在/var/目录下创建存放ISO的目录(也可自定义成其他目录),使用xe命令创建镜像分区。

1
2
3
mkdir -p /var/iso_import

xe sr-create name-label=ISO type=iso device-config:location=/var/iso_import/ device-config:legacy_mode=true content-type=iso

后面只需要将镜像iso文件导入/var/iso_import目录中,在XenServer可视化控制台中刷新(rescan)即可看到镜像。创建虚拟机时即可从自定义的镜像启动。

Windows10在升级到1903之后,菜单栏突然多出了一个“ms-resource:AppName/text”的空条目,逼死强迫症。
如何安全删除这个图标呢?
方法如下:

以Administrator身份运行powershell

在Powershell中运行:

1
Get-AppxPackage -all *HolographicFirstRun* | Remove-AppPackage -AllUsers

打开任务管理器,kill掉explorer.exe进程(保持Powershell在前台运行)。在Powershell中,进入这个目录:

1
cd $Env:localappdata\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy`

如果能进入,运行以下删除目录语句:

Remove-Item -Recurse -Force .\TempState\

在任务管理器中重新打开Explorer.exe。此时查看菜单,ms-resource:AppName/text图标应该已经删除了。

参考自:

https://answers.microsoft.com/en-us/windows/forum/all/ms-resourceappnametext-appeared-on-start-menu-all/e6c5d10b-bad9-4eae-835f-99f438f3bd91

原文:

1
2
3
4
5
6
7
8
9
10
11
12
Run Powershell with Admin privilege
On the prompt, run this command:

Get-AppxPackage -all *HolographicFirstRun* | Remove-AppPackage -AllUsers

Open Task manager, kill explorer.exe (keep the powershell console open)
Back on the prompt, type:
cd $Env:localappdata\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy
If the previous command succesfully put you on AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy directory inside your profile dir, then run:
Remove-Item -Recurse -Force .\TempState\
Start explorer.exe back up from task manager (File -> New Task)
The rogue start menu item should be gone.
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×