Skip to main content

· 3 min read

create-react-app用get向后端发送请求的时候是OK的,但是换成post请求就会报跨域请求的错误--CORS

参考官网有2种解决方法:

这里演示如何将 http://127.0.0.1:3001/test开始的api代理到http://127.0.0.1:8002

方案1:修改package.json:

添加一行配置,但是react新版只支持字符串的配置,这就意味着如果你无法请求多个域名的api

"proxy": "http://localhost:8002",

注意:此时,前端请求的时候就不用加BASE_URL

方案2:创建src/setupProxy.js,注意必须是这个文件名

npm i http-proxy-middleware --save

创建src/setupProxy.js

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
app.use(
'/test',
createProxyMiddleware({
target: 'http://127.0.0.1:8002',
changeOrigin: true,
})
);
};

此时再去发动post请求:

import React, { Component } from 'react'
import pageStyle from '../../page.module.css'
// import homeStyle from './index.module.css'
import axios from "axios";
export default class ExampleHome extends Component {
state = {
arr:[]
}
componentDidMount() {
axios.post("/test/1",{}).then(
res=>{
console.log(res.data.data)
this.setState({
arr : res.data.data
})
},
err=>{}
)
}

render() {
return (
<div className={pageStyle.container}>
{
this.state.arr.map((item,index)=>{
return <li key={index}>{item}</li>
})
}
</div>
)
}
}

发现没有报错了,页面可以正常显示

值得注意的是, npm run build之后,代理是失效的,需要借助nginx caddy等代理工具完成代理

有人说请求的时候把BASE_URL加上不就行了,我们来试试?

修改前端react代码:

import React, { Component } from 'react'
import pageStyle from '../../page.module.css'
// import homeStyle from './index.module.css'
import axios from "axios";
export default class ExampleHome extends Component {
state = {
arr:[]
}
componentDidMount() {
const BASE_URL = "http://127.0.0.1:8002"
axios.post(`${BASE_URL}/test/1`,{}).then(
res=>{
console.log(res.data.data)
this.setState({
arr : res.data.data
})
},
err=>{}
)
}

render() {
return (
<div className={pageStyle.container}>
{
this.state.arr.map((item,index)=>{
return <li key={index}>{item}</li>
})
}
</div>
)
}
}

打开浏览器控制台,发现已经CORS报错了

点开 network, 已经飙红了,发现请求压根都没到达后端就被浏览器拦截了:

详细信息:

我们来看看编译后的代码:

访问url: 控制台和network都报错

总结

react在开发阶段可以用src/setupProxy.js来实现代理,部署的时候需借助nginx caddy等代理软件配置代理

· 2 min read

我相信很多coder都遇到这样一个问题: 无论是克隆自己的代码还是他人的都gg

就像下面这样:

看到这些报错信息,真是心凉啊

于是想到网络上一个段子:

其实不用代理,有时候也可以访问github

首先我们要明白的是:防火墙最善使用的武器是 – DNS污染

我们先ping一下:

好家伙直接给解析到了 127.0.0.1

我们手动修改dns 然他解析到正确的地址

# 8.8.8.8 是google的dns server
dig @8.8.8.8 [-tcp] domain

IP LOCKUP 检查一下 有无投毒 确认是微软 OK没错了

修改 /etc/hosts

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost

#添加一行
20.205.243.166 github.com

这里利用了dns的解析原理: dns会先来/etc/hosts来找,找不着 它就会去解析,防火墙也是利用这个漏洞来墙github

最后我们再 go mod tidy一下:

OK, 无任何报错信息

· One min read

jquery

// jQuery document ready
$(document).ready(function() {

});

$(document).ready(function() {
console.log( "ready!" );
});

$(function(){

})

native js

document.addEventListener("DOMContentLoaded", function() {
// code
});
document.addEventListener("DOMContentLoaded", function(event) { 
//we ready baby
});
window.onload = function() {

};
document.addEventListener("DOMContentLoaded", fn);

· One min read

有时候我们需要定期的更新配置文件,如此处的getfolders.go需要去3个服务器爬取对应的信息,而每天目录都在变,如果你不更新,就会出现搜不到单的情况

//判断文件是否过时
//pth: 文件目录
//hour: 距现在多少小时算过时
func IsFileOutOfDate(pth string, hour int) bool {
tm1, err := getFileModTime(pth)
if err != nil {
return true
}

tm2 := time.Now().Unix() //unix定义返回的是s

if tm2-tm1 > int64(hour*3600) {
return true
} else {
return false
}
}

//获取文件修改时间 返回unix时间戳
func getFileModTime(pth string) (int64, error) {
f, err := os.Open(pth)
if err != nil {
return time.Now().Unix(), err
}
defer f.Close()

fi, err := f.Stat()
if err != nil {
return time.Now().Unix(), err
}

return fi.ModTime().Unix(), nil
}

相关定义src/io/fs/fs.go

参考:https://github.com/scott-x/gutils/blob/master/fs/time.go

· One min read

package middlewares

import (
"github.com/gin-gonic/gin"
"net/http"
)

func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
method := c.Request.Method

//告诉浏览器 你的Header里面可以添加什么

c.Header("Access-Control-Allow-Origin", "*") //固定写法
//哪些Headers可以加:我们加一些常用的,当然想用什么加什么,把你要用的加进去,我们现在用的是x-token
//虽然和下面的冲突了,但是没关系
c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token,Authorization,Token,x-token")
//哪些方法可以加
c.Header("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE,OPTIONS,PATCH")
//哪些Headers可以加
c.Header("Access-Control-Expose-Headers", "Content-Length,Access-Control-Allow-Origin,Access-Control-Allow-Methods,Content-Type")
c.Header("Access-Control-Allow-Credentials", "true")

//前端如果跨域,浏览器就会发起OPTIONS请求 询问后端是否安全?后端处理这个OPTIONS请求即可
if method == "OPTIONS" {
//如果不像返回内容 就用下面的方法
c.AbortWithStatus(http.StatusNoContent)
}
}
}

· One min read

之前遇到个问题,在一段代码中这样设置WriteHeader,在浏览器怎么样都不是json。

w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json; charset=utf-8")

后来才知道

如果这两种修改一起做,就必须让 w.WriteHeader 在所有的 w.Header.Set 之后,因为 w.WriteHeader 后 Set Header 是无效的。

所以正确的应该是

w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)