CodeIgniter4 CORS 跨域问题

当使用前后端分离,并且前端后端域名不统一时,我遇到了跨域的问题

1
Access to XMLHttpRequest at http://localhost/api/login from origin http://localhost:8010 has been blocked by CORS policy: Response to preflight request doesnt pass access control check: NoAccess-Control-Allow-Origin header is present on the requested resource.```
1
Access to XMLHttpRequest at http://localhost/api/login from origin http://localhost:8010 has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

我们只需要在返回的 response 中添加 header就可以了

首先我们创建一个 Filter 用来批量在生成的 response 中添加 headers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
App\Filters\Api.php
<?php
namespace App\Filters;

use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;

class Api implements FilterInterface
{
public function before(RequestInterface $requset)
{

}

public function after(RequestInterface $request, ResponseInterface $response)
{
$response->setHeader(Access-Control-Allow-Origin, *);
$response->setHeader(Access-Control-Allow-Headers, Content-Type);
return $response;
}
}

接下来我们将注册并配置 App\Filters\Api::class, 编辑配置文件 App\Config\Filters.php

1
2
3
4
5
6
7
8
...
public $aliases = [
csrf => \CodeIgniter\Filters\CSRF::class,
toolbar => \CodeIgniter\Filters\DebugToolbar::class,
honeypot => \CodeIgniter\Filters\Honeypot::class,
api => \App\Filters\Api::class, //注册 Filter
];
...

配置该 filter 对哪些 uri 生效

public $filters = [
        api => [
            after =>[
                api/*,
            ]
        ]
    ];

至此,在每个路径为 api/* 的请求返回前,就会执行 after 中的代码,添加 headers

一元多项式的乘法与加法运算(数组解法)

02-线性结构2 一元多项式的乘法与加法运算

设计函数分别求两个一元多项式的乘积与和。

输入格式:

输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式:

输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出 0 0。

输入样例:

1
2
4 3 4 -5 2  6 1  -2 0
3 5 20 -7 4 3 1

输出样例:

1
2
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <stdio.h>

void putX(int A[][2], int numA, int B[][2], int numB);
void putSum(int A[][2], int numA, int B[][2], int numB);
int main(){
int num1, num2;
scanf("%d", &amp;num1);
int Arr1[num1][2];
for(int i = 0; i < num1; i++){
scanf("%d", &amp;Arr1[i][0]);
scanf("%d", &amp;Arr1[i][1]);
}
scanf("%d", &amp;num2);
int Arr2[num2][2];
for(int i = 0; i < num2; i++){
scanf("%d", &amp;Arr2[i][0]);
scanf("%d", &amp;Arr2[i][1]);
}
putX(Arr1, num1, Arr2, num2);
putSum(Arr1, num1, Arr2, num2);
return 0;
}

void putX(int A[][2], int numA, int B[][2], int numB){
if(numA == 0 || numB == 0){
printf("0 0\n");
return;
}
int max = A[0][1] + B[0][1] + 1;
int Arr[max];
for(int i = 0; i < max; i++){
Arr[i] = 0;
}
for(int i = 0; i < numA; i++){
for(int k = 0; k < numB; k++){
Arr[A[i][1] + B[k][1]] += A[i][0] * B[k][0];
}
}
int isNeedSpace = 0;
for(int i = max -1; i > -1; i--){
if(Arr[i] == 0) continue;
if(isNeedSpace){
printf(" ");
}
printf("%d %d", Arr[i], i);
isNeedSpace = 1;
}
printf("\n");
return;
}

int compote(int a, int b){
if(a == b){
return 0;
}else if( a > b){
return 1;
}else{
return -1;
}
}

void putSum(int A[][2], int numA, int B[][2], int numB){
int i = 0, k = 0, isEmpty = 1, isNeedSpace = 0;
while(i < numA &amp;&amp; k < numB){
int ps = compote(A[i][1], B[k][1]);
int sum;
switch(ps){
case 0:
sum = A[i][0] + B[k][0];
if(sum == 0){
i++;
k++;
continue;
};
if(isNeedSpace) printf(" ");
printf("%d %d", sum, A[i][1]);
isNeedSpace = 1;
isEmpty = 0;
i++;
k++;
break;
case 1:
if(isNeedSpace) printf(" ");
printf("%d %d", A[i][0], A[i][1]);
isNeedSpace = 1;
isEmpty = 0;
i++;
break;
case -1:
if(isNeedSpace) printf(" ");
printf("%d %d", B[k][0], B[k][1]);
isNeedSpace = 1;
isEmpty = 0;
k++;
break;
}
}
if(i < numA){
for(;i < numA;i++){
if(isNeedSpace){
printf(" ");
}
printf("%d %d", A[i][0], A[i][1]);
isEmpty = 0;
isNeedSpace = 1;
}
}else if(k < numB){
for(;k < numB;k++){
if(isNeedSpace){
printf(" ");
}
printf("%d %d", B[k][0], B[k][1]);
isEmpty = 0;
isNeedSpace = 1;
}
}
if(isEmpty){
printf("0 0");
}
return;
}

记一次服务器数据被删除的恢复-losf 数据恢复

公司的主控的Redis是之前别人搭的,用root:root启动并且监听了公网IP,没有加密码。被黑客扫描到并利用漏洞删除了服务器中的数据文件,涉及数据库代码文件等。

登陆服务器后发现文件都被删除了,df -h 发现磁盘占用并没有减少。结合之前清除nginx日志的经历,应该是MySQL服务还在运行中,所以文件没有立即释放。

经过与TG群里的大佬沟通学习,最后通过 losf 查看到了已删除但未被释放的文件,再通过 proc 内的文件句柄 用 cp 命令拷贝到原目录。经过数小时的拷贝,数据库数据总算恢复了。幸好给代码做了git仓库,不然代码要回滚好几个版本。之后迁移到新的服务器。

几点经验及教训:

  • 一定要对服务器进行备份(虽然现在也没做,但是关键数据还是要做备份的)
  • 要采用最小权限原则进行服务的部署,避免root启动及公网直接访问
  • 对敏感命令进行限制如 rm -rf 命令
  • 一定不要重启服务器
  • 付款也无法找回数据(我们的数据库大概300G左右,黑客说付款可以找回数据,但是经过观察流量图并没有这么大的流量进行通信)
  • 各个领域认识人是多么的重要

debian puppeteer 安装问题汇总

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>ERROR: Failed to download Chromium r588429! Set "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" env variable to skip download.
{ Error: EACCES: permission denied, mkdir '/data/wwwroot/example/dispa/node_modules/puppeteer/.local-chromium'
errno: -13,
code: 'EACCES',
syscall: 'mkdir',
path: '/data/wwwroot/example/dispa/node_modules/puppeteer/.local-chromium' }
npm WARN dispa@1.0.0 No description
npm WARN dispa@1.0.0 No repository field.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! puppeteer@1.8.0 install: `node install.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the puppeteer@1.8.0 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2018-09-11T01_37_36_695Z-debug.log

直接看一开始的 Error 还以为是网络问题没法下载 chrome ,尝试设置了 PUPPETEER_SKIP_CHROMIUM_DOWNLOAD 没用
,后来才看见底下的 permission denied 原来是没权限

运行 sudo npm i puppeteer 安装即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
node:30630) UnhandledPromiseRejectionWarning: Error: Failed to launch chrome!
/data/wwwroot/example/dispa/node_modules/puppeteer/.local-chromium/linux-588429/chrome-linux/chrome: error while loading shared libraries: libasound.so.2: cannot open shared object file: No such file or directory


TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md

at onClose (/data/wwwroot/example/dispa/node_modules/puppeteer/lib/Launcher.js:333:14)
at Interface.helper.addEventListener (/data/wwwroot/example/dispa/node_modules/puppeteer/lib/Launcher.js:322:50)
at emitNone (events.js:111:20)
at Interface.emit (events.js:208:7)
at Interface.close (readline.js:368:8)
at Socket.onend (readline.js:147:10)
at emitNone (events.js:111:20)
at Socket.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
(node:30630) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:30630) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

经过翻看 issues 这个问题是因为依赖问题导致的

执行 wget -qO- --no-check-certificate https://raw.githubusercontent.com/Garbee/puppeteer/cd00f7d936c942f8f378a332401024e501b186ce/utils/linux/debian-check.sh | bash 后,在 shell 执行列出的命令,安装相关依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(node:32460) UnhandledPromiseRejectionWarning: Error: Failed to launch chrome!
[0911/100703.525676:ERROR:zygote_host_impl_linux.cc(89)] Running as root without --no-sandbox is not supported. See https://crbug.com/638180.


TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md

at onClose (/data/wwwroot/example/dispa/node_modules/puppeteer/lib/Launcher.js:333:14)
at Interface.helper.addEventListener (/data/wwwroot/example/dispa/node_modules/puppeteer/lib/Launcher.js:322:50)
at emitNone (events.js:111:20)
at Interface.emit (events.js:208:7)
at Interface.close (readline.js:368:8)
at Socket.onend (readline.js:147:10)
at emitNone (events.js:111:20)
at Socket.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
(node:32460) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:32460) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

设置 --no-sandbox 参数:

1
const browser = await puppeteer.launch({headless: true, args:['--no-sandbox']});

或者切换到非 root 用户

谁偷了我的内存?记一次内存占用过高的排查

2018-08-21: 内存升到44G了,看不下去了,决定手动清理

1
2
sync
echo 2 > /proc/sys/vm/drop_caches

又看了很多文章,每打开一个文件就会增加 dentry 这个程序有大量的 Curl 请求以及多进程的任务组。这个应该就是问题了吧。


项目服务器是 8H64G 的 EC2,因为项目数据量很大,监控程序一直显示真实内存占用在 47G 左右,本以为是Mysql占用过大导致的。htop图显示如下:


图中显示 Mysql 内存占用 2.1%,但是出现了很多列,肤浅的我错误的认为这些都是 Mysql,以 n*2.1 来计算 Mysql 的占用,经过V2er们的指点,得知了在 htop 中默认是以线程展示数据的,Mysql是多线程程序,多个线程之间的内存是共享的,通过 H 指令切换到非线程模式。


内存占用最高的还是 Mysql 不过他的内存占用也只有 2.4%。但是内存使用显示已经用了 48G 的内存。

首先有人提到了 tmpfs ,系统分配了 31G 的 tmpfs,本以为确实是这里占用掉了内存,但是查完资料发现 tmpfs 不使用的话是不会占用内存的,有人让我贴出了 cat /proc/meminfo

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
cat /proc/meminfo 
MemTotal: 62919396 kB
MemFree: 2228000 kB
MemAvailable: 60639408 kB
Buffers: 327824 kB
Cached: 10384060 kB
SwapCached: 0 kB
Active: 8945140 kB
Inactive: 3568212 kB
Active(anon): 1801992 kB
Inactive(anon): 9432 kB
Active(file): 7143148 kB
Inactive(file): 3558780 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 76 kB
Writeback: 0 kB
AnonPages: 1801496 kB
Mapped: 52352 kB
Shmem: 9940 kB
Slab: 48031092 kB
SReclaimable: 47962884 kB
SUnreclaim: 68208 kB
KernelStack: 3376 kB
PageTables: 14700 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 31459696 kB
Committed_AS: 3442324 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
AnonHugePages: 26624 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 12288 kB
DirectMap2M: 63987712 kB

这位朋友提出了 “Google Slab 占用高” 的建议,通过 Google 得到了 slabtop 这条命令执行之后发现占用最高的是 dentry, google 后得到了这篇文章 记一次内存使用率过高的报警 从文中得知 nss-softokn 的 bug 导致 curl 大量请求后, dentry 缓存飙升

服务器的监控模块,第三方接口对接的实现都是根据 curl 实现的,curl 的使用确实很多。 根据文中的方法进行排查与修复,当时内存占用还是在 47G ,因为dentry是会自动清理的,所以没有进行手动了清理。现在内存使用已经下降到了 36G。

通过这次事件,深深的感受到了没有运维的痛苦之处,毕竟不是专业搞运维的。当然,下次遇到同样的情况的话也就会往这方面考虑了,遇到问题,解决问题,理解问题,在问题中得到提升。当然,再次感慨社区的力量与人性的善。

[typecho 插件] GoogleRecaptcha

typecho_GoogleRecaptcha

为 Typecho Admin 开启Google invisible Recaptcha 验证

开启 Google reCAPTCHA

前往 Google reCAPTCHA 开启 reCAPTCHA 并 获取参数

  1. 选择 Invisible reCAPTCHA ,填写 Domains 进行注册
  2. 获取 Site key & Secret key
    <https://i.loli.net/2018/01/09/5a5413230deab.png

插件配置

将 Site Key & Secret Key 填入对应的配置项

配置加载 JS 使用的地址

配置后端验证 response 使用的地址

Github