0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在Golang中实现反向代理

开关电源芯片 来源:github 作者:zhaoyang 2021-08-23 10:22 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

【导读】在本文中,我们将了解反向代理,它的应用场景以及如何在 Golang 中实现它。

反向代理是位于 Web 服务器前面并将客户端(例如 Web 浏览器)的请求转发到 Web 服务器的服务器。它们让你可以控制来自客户端的请求和来自服务器的响应,然后我们可以利用这个特点, 可以增加缓存、做一些提高网站的安全性措施等。

在我们深入了解有关反向代理之前,让我们快速看普通代理(也称为正向代理)和反向代理之间的区别。

在正向代理中,代理代表原始客户端从另一个网站检索数据。它位于客户端(浏览器)前面,并确保没有后端服务器直接与客户端通信。所有客户端的请求都通过代理被转发,因此服务器只与这个代理通信(服务器会认为代理是它的客户端)。在这种情况下,代理可以隐藏真正的客户端。

img

另一方面,反向代理位于后端服务器的前面,确保没有客户端直接与服务器通信。所有客户端请求都会通过反向代理发送到服务器,因此客户端始终只与反向代理通信, 而从不会直接与实际服务器通信。在这种情况下,代理可以隐藏后端服务器。几个常见的反向代理有 Nginx, HAProxy。

反向代理使用场景

负载均衡(Load balancing):反向代理可以提供负载均衡解决方案,将传入的流量均匀地分布在不同的服务器之间,以防止单个服务器过载。

防止安全攻击:由于真正的后端服务器永远不需要暴露公共 IP,所以 DDoS 等攻击只能针对反向代理进行, 这能确保在网络攻击中尽量多的保护你的资源,真正的后端服务器始终是安全的。

缓存:假设你的实际服务器与用户所在的地区距离比较远,那么你可以在当地部署反向代理,它可以缓存网站内容并为当地用户提供服务。

SSL 加密:由于与每个客户端的 SSL 通信会耗费大量的计算资源,因此可以使用反向代理处理所有与 SSL 相关的内容, 然后释放你真正服务器上的宝贵资源。

Golang 实现

import (

“log”

“net/http”

“net/http/httputil”

“net/url”

// NewProxy takes target host and creates a reverse proxy// NewProxy 拿到 targetHost 后,创建一个反向代理func NewProxy(targetHost string) (*httputil.ReverseProxy, error) {

url, err := url.Parse(targetHost)

if err != nil {

return nil, err

}

return httputil.NewSingleHostReverseProxy(url), nil

}

// ProxyRequestHandler handles the http request using proxy// ProxyRequestHandler 使用 proxy 处理请求func ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {

return func(w http.ResponseWriter, r *http.Request) {

proxy.ServeHTTP(w, r)

}

}

func main() {

// initialize a reverse proxy and pass the actual backend server url here

// 初始化反向代理并传入真正后端服务的地址

proxy, err := NewProxy(“http://my-api-server.com”)

if err != nil {

panic(err)

}

// handle all requests to your server using the proxy

// 使用 proxy 处理所有请求到你的服务

http.HandleFunc(“/”, ProxyRequestHandler(proxy))

log.Fatal(http.ListenAndServe(“:8080”, nil))

}

是的没错!这就是在 Go 中创建一个简单的反向代理所需的全部内容。我们使用标准库 net/http/httputil 创建了一个单主机的反向代理。到达我们代理服务器的任何请求都会被代理到位于 http://my-api-server.com。如果你对 Go 比较熟悉,这个代码的实现一目了然。

修改响应

HttpUtil 反向代理为我们提供了一种非常简单的机制来修改我们从服务器获得的响应, 可以根据你的应用场景来缓存或更改此响应,让我们看看应该如何实现:

// NewProxy takes target host and creates a reverse proxyfunc NewProxy(targetHost string) (*httputil.ReverseProxy, error) {

url, err := url.Parse(targetHost)

if err != nil {

return nil, err

}

proxy := httputil.NewSingleHostReverseProxy(url)

proxy.ModifyResponse = modifyResponse()

return proxy, nil

}

func modifyResponse() func(*http.Response) error {

return func(resp *http.Response) error {

resp.Header.Set(“X-Proxy”, “Magical”)

return nil

}

}

可以在 modifyResponse 方法中看到 ,我们设置了自定义 Header 头。同样,你也可以读取响应体正文,并对其进行更改或缓存,然后将其设置回客户端。

在 modifyResponse 中,可以返回一个错误(如果你在处理响应发生了错误), 如果你设置了 proxy.ErrorHandler, modifyResponse 返回错误时会自动调用 ErrorHandler 进行错误处理。

// NewProxy takes target host and creates a reverse proxyfunc NewProxy(targetHost string) (*httputil.ReverseProxy, error) {

url, err := url.Parse(targetHost)

if err != nil {

return nil, err

}

proxy := httputil.NewSingleHostReverseProxy(url)

proxy.ModifyResponse = modifyResponse()

proxy.ErrorHandler = errorHandler()

return proxy, nil

}

func errorHandler() func(http.ResponseWriter, *http.Request, error) {

return func(w http.ResponseWriter, req *http.Request, err error) {

fmt.Printf(“Got error while modifying response: %v

”, err)

return

}

}

func modifyResponse() func(*http.Response) error {

return func(resp *http.Response) error {

return errors.New(“response body is invalid”)

}

}

修改请求

你也可以在将请求发送到服务器之前对其进行修改。在下面的例子中,我们将会在请求发送到服务器之前添加了一个 Header 头。同样的,你可以在请求发送之前对其进行任何更改。

// NewProxy takes target host and creates a reverse proxyfunc NewProxy(targetHost string) (*httputil.ReverseProxy, error) {

url, err := url.Parse(targetHost)

if err != nil {

return nil, err

}

proxy := httputil.NewSingleHostReverseProxy(url)

originalDirector := proxy.Director

proxy.Director = func(req *http.Request) {

originalDirector(req)

modifyRequest(req)

}

proxy.ModifyResponse = modifyResponse()

proxy.ErrorHandler = errorHandler()

return proxy, nil

}

func modifyRequest(req *http.Request) {

req.Header.Set(“X-Proxy”, “Simple-Reverse-Proxy”)

}

完整代码

package main

import (

“errors”

“fmt”

“log”

“net/http”

“net/http/httputil”

“net/url”

// NewProxy takes target host and creates a reverse proxyfunc NewProxy(targetHost string) (*httputil.ReverseProxy, error) {

url, err := url.Parse(targetHost)

if err != nil {

return nil, err

}

proxy := httputil.NewSingleHostReverseProxy(url)

originalDirector := proxy.Director

proxy.Director = func(req *http.Request) {

originalDirector(req)

modifyRequest(req)

}

proxy.ModifyResponse = modifyResponse()

proxy.ErrorHandler = errorHandler()

return proxy, nil

}

func modifyRequest(req *http.Request) {

req.Header.Set(“X-Proxy”, “Simple-Reverse-Proxy”)

}

func errorHandler() func(http.ResponseWriter, *http.Request, error) {

return func(w http.ResponseWriter, req *http.Request, err error) {

fmt.Printf(“Got error while modifying response: %v

”, err)

return

}

}

func modifyResponse() func(*http.Response) error {

return func(resp *http.Response) error {

return errors.New(“response body is invalid”)

}

}

// ProxyRequestHandler handles the http request using proxyfunc ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {

return func(w http.ResponseWriter, r *http.Request) {

proxy.ServeHTTP(w, r)

}

}

func main() {

// initialize a reverse proxy and pass the actual backend server url here

proxy, err := NewProxy(“http://my-api-server.com”)

if err != nil {

panic(err)

}

// handle all requests to your server using the proxy

http.HandleFunc(“/”, ProxyRequestHandler(proxy))

log.Fatal(http.ListenAndServe(“:8080”, nil))

}

反向代理非常强大,如文章之前所说,它有很多应用场景。你可以根据你的情况对其进行自定义。如果遇到任何问题,我非常乐意为你提供帮助。如果你觉得这篇文章有趣,请分享一下,让更多 gopher 可以阅读!非常感谢你的阅读。

转自:h1z3y3.me/posts/simple-and-powerful-reverse-proxy-in-golang/

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 服务器
    +关注

    关注

    14

    文章

    10467

    浏览量

    91890
  • 代理
    +关注

    关注

    1

    文章

    44

    浏览量

    11467

原文标题:Go 简单而强大的Reverse Proxy反向代理

文章出处:【微信号:gh_3980db2283cd,微信公众号:开关电源芯片】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    何在LTspice实现类似的开尔文源极连接

    Category: Software Product Number: LTSpice Software Version: 24.0.12 在 simplorermos模型均设置有开尔文源极端口,如下图所示: 请问如何在LTspice
    发表于 05-26 08:07

    何在 S32DS 上实现 CMSIS-DSP ?

    Hi, 有人可以告诉我如何在 S32DS 上实现 CMSIS-DSP 吗?我想在 S32K3 上使用 FFT。谢谢。
    发表于 05-21 08:15

    Nginx反向代理场景下的三类错误排查方法

    在生产环境,502、504 和 Connection Reset 是 Nginx 反向代理场景下最常见的三类错误。它们经常被笼统地归为"后端挂了",但实际上三种错误指向完全不同的故障类型。
    的头像 发表于 05-12 09:32 375次阅读

    2026年上海永铭电子代理商会议圆满落幕:确定的方向,有限的窗口,携手抢占未来赛道

    总在致辞中点明会议主题:确定的方向,有限的窗口。随后,会议深入探讨了如何在窗口期内完成产品布局,抢占AI、新能源汽车等赛道的先发优势,实现共赢增长。三大核心内容落
    的头像 发表于 03-07 14:55 624次阅读
    2026年上海永铭电子<b class='flag-5'>代理</b>商会议圆满落幕:确定的方向,有限的窗口,携手抢占未来赛道

    何在小尺寸陶瓷天线同时实现多频段覆盖?

    何在小尺寸陶瓷天线同时实现多频段覆盖智能手表、蓝牙耳机、物联网传感器……这些设备越来越小巧,功能却越来越多。以智能手表为例:蓝牙连接耳机(2.4GHz)、GPS定位(1.5GHz)、WiFi数据
    的头像 发表于 03-02 14:29 332次阅读
    如<b class='flag-5'>何在</b>小尺寸陶瓷天线<b class='flag-5'>中</b>同时<b class='flag-5'>实现</b>多频段覆盖?

    Nginx反向代理和负载均衡配置实战

    负载均衡则是反向代理的进阶玩法。当一台后端服务器扛不住流量的时候,就需要多台服务器一起分担压力。Nginx负责把请求分发到不同的服务器上,这就是负载均衡。
    的头像 发表于 01-23 13:44 1100次阅读

    何在Zephyr RTOS实现延时和计时函数

    多种延时与计时实现方案,满足不同应用场景的需求。那么,大家平时都是怎么在MCU程序实现计时函数、实现延时的呢?
    的头像 发表于 12-26 10:32 6408次阅读
    如<b class='flag-5'>何在</b>Zephyr RTOS<b class='flag-5'>中</b><b class='flag-5'>实现</b>延时和计时函数

    反向代理新玩法?ZeroNews黑科技解读。

    如果你是一名开发者或运维,对“反向代理”一定不会陌生。 Nginx、Caddy、Traefik……这些耳熟能详的工具,是我们的得力助手。 但它们都有一个前提: 你需要一台拥有公网IP的服务器。 今天
    的头像 发表于 11-05 14:51 672次阅读

    何在VS code配置Zephyr集成开发环境

    上一篇文章介绍了如何在VS code中使用瑞萨官方插件为RA芯片创建项目与项目调试,相信大家对RA在VS code的开发有了基础的了解。
    的头像 发表于 11-05 14:46 2013次阅读
    如<b class='flag-5'>何在</b>VS code<b class='flag-5'>中</b>配置Zephyr集成开发环境

    企业安全访问网关:ZeroNews反向代理

    花半天时间配置VPN账号。” 这些场景您是否遇到过? 传统的VPN(虚拟专用网)在为企业提供远程接入能力的同时,其 “全有或全无” 的粗放式网络接入模式,已成为企业安全体系的一个巨大裂缝。一旦接入,用户就如同进入了内网,访问行为
    的头像 发表于 10-14 10:50 533次阅读
    企业安全访问网关:ZeroNews<b class='flag-5'>反向</b><b class='flag-5'>代理</b>

    何在 buildroot 的 rootfs 显示当前目录?

    何在 buildroot 的 rootfs 显示当前目录?
    发表于 09-03 07:02

    【HZ-T536开发板免费体验】5、安装sqlite3和使用golang读写数据库

    如果想在嵌入式设备上实现简单的设备管理功能,需要数据库和服务后端程序。服务端程序,我更倾向使用golang实现。 安装sqlite3,使用ubuntu环境,可以直接用apt install安装程序
    发表于 08-26 00:04

    华为手机反向无线充电原理

    华为无线反向充电技术利用电磁感应实现电能共享,支持多设备兼容,效率高、稳定性强。
    的头像 发表于 08-10 08:29 8571次阅读
    华为手机<b class='flag-5'>反向</b>无线充电原理

    代理式AI与AI智能体在不同行业的实际应用

    代理式 AI 的时代已经到来。如今,代理式 AI 已经驱动应用迈向深度场景融合与规模化落地。这波演进浪潮标志着 AI 能力向自主执行的跃迁。本文将系统解析代理式 AI (Agentic AI
    的头像 发表于 07-28 14:28 1509次阅读

    何在多显卡环境下配置OLLAMA实现GPU负载均衡

    本文将带你深入了解如何在多显卡环境下配置OLLAMA,实现GPU负载均衡,并分享生产环境的最佳实践。无论你是刚接触GPU集群还是寻求性能优化的老手,这篇文章都能给你带来实用价值。
    的头像 发表于 07-24 14:12 5301次阅读