golang beego 框架 反向代理 跨域
通常在前端开发中,多个node工程相互调用或者存在跨域,并且很难解决时,可以考虑运用golang的反向代理。
值得一提的是,ReverseProxy是golang的"net/http/httputil"包自带的,功能强大,使用简单。
反向代理的基本写法
- 第一种方式
type ProxyHandler struct {}
func(* ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
//fmt.Println(r.RequestURI)
// /a?b=123
defer func() {
if err := recover();err != nil{
w.WriteHeader(500)
log.Println(err)
}
}()
fmt.Println(r.URL) // /a?b=123
fmt.Println(r.URL.Path) // /a
if r.URL.Path == "/a"{
newreq,_ := http.NewRequest(r.Method,"http://" + "10.53.51.237:8080",r.Body)
//newreq,_ := http.NewRequest(r.Method,"https://" + "baidu.com",r.Body)
newresponse,_ := http.DefaultClient.Do(newreq)
res_cont,_ := ioutil.ReadAll(newresponse.Body)
w.Write(res_cont)
return
}
w.Write([]byte("default index"))
}
func main() {
http.ListenAndServe(":8080",&ProxyHandler{})
}
- 第二种方式
func main() {
// 增加一个反向代理服务器用于测试webpack_dev_server
http.HandleFunc("/", ServeHTTP)
//http.Handle("/faceDetect.html", &ReverseProxy{"/"})
//http.ListenAndServeTLS(":8444","../conf/7567053_devapi.smileai.net.pem", "../conf/7567053_devapi.smileai.net.key", nil)
http.ListenAndServe(":8089", nil)
}
func ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r != nil {
msg, _ := r.(string)
logs.Error(msg)
}
}()
if r.RequestURI == "/favicon.ico" {
io.WriteString(w, "Request path Error")
return
}
remote, err := url.Parse("http://" + "127.0.0.1:8080")
if err != nil {
panic(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
proxy.ServeHTTP(w, r)
}
NewSingleHostReverseProxy即为创建爱你反向代理实例的方法。
结合beego的写法
1. 在beego的routers里面添加路由
package routers
import (
"github.com/astaxie/beego"
"smileai-proxy/controllers"
)
func init() {
beego.Router("/conversation", &controllers.MainController{}, "get:GetConversation")
beego.Router("/conversation/*", &controllers.MainController{}, "get:GetConversation")
beego.Router("/management/*", &controllers.MainController{}, "get:GetManagement")
beego.Router("/management", &controllers.MainController{}, "get:GetManagement")
}
2. 在controller处理逻辑
package controllers
import (
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
"net/http/httputil"
"net/url"
)
//MainController 网页代码入口
type MainController struct {
beego.Controller
}
func (t *MainController) GetConversation() {
defer func() {
if r := recover(); r != nil {
logs.Error(fmt.Errorf("%v", r))
}
}()
ConversationURL := beego.AppConfig.String("ConversationURL")
remote, err := url.Parse(ConversationURL)
if err != nil {
panic(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
proxy.ServeHTTP(t.Ctx.ResponseWriter, t.Ctx.Request)
}
func (t *MainController) GetManagement() {
defer func() {
if r := recover(); r != nil {
logs.Error(fmt.Errorf("%v", r))
}
}()
Management := beego.AppConfig.String("ManagementURL")
remote, err := url.Parse(Management)
if err != nil {
panic(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
proxy.ServeHTTP(t.Ctx.ResponseWriter, t.Ctx.Request)
}
3. 在main中设置监听
func main() {
beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
// 允许访问所有源
AllowAllOrigins: true,
// 可选参数"GET", "POST", "PUT", "DELETE", "OPTIONS" (*为所有)
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
// 指的是允许的Header的种类
AllowHeaders: []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
// 公开的HTTP标头列表
ExposeHeaders: []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
// 如果设置,则允许共享身份验证凭据,例如cookie
AllowCredentials: true,
}))
beego.BConfig.Listen.HTTPPort = 8090
beego.Run()
}
4. 最后在beego的conf/app.conf里面添加两个配置
ConversationURL="http://10.53.51.237:8081"
ManagementURL="http://10.53.51.237:8080"
总结
这里通过beego添加conversation和management两个路由,分别代理8081和8080两个端口,当前端访问这两个端口时,可以通过beego的8090端口加上对应的路由去访问,解决了跨域问题。
这里需要注意,8080和8081要解决自身路由问题,比如说,因为反向代理会将自身的"/conversation"转发到"http://10.53.51.237:8080", 也就是8080自身的路由必须可访问,即:"http://10.53.51.237:8080/conversation" 。