91在线观看视频-91在线观看视频-91在线观看免费视频-91在线观看免费-欧美第二页-欧美第1页

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Golang實現一個簡單的http代理

馬哥Linux運維 ? 來源:CSDN技術社區 ? 2023-04-10 11:29 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

本文詳細介紹了Golang 實現 http 代理的實現,在實際業務中有需求的同學可以學起來了!

代理是網絡中的一項重要的功能,其功能就是代理網絡用戶去取得網絡信息。形象的說:它是網絡信息的中轉站,對于客戶端來說,代理扮演的是服務器的角色,接收請求報文,返回響應報文;對于 web 服務器來說,代理扮演的是客戶端的角色,發送請求報文,接收響應報文。

代理具有多種類型,如果是根據網絡用戶劃分的話,可以劃分為正向代理和反向代理:

正向代理:將客戶端作為網絡用戶。客戶端訪問服務端時,先訪問代理服務器,隨后代理服務器再訪問服務端。此過程需客戶端進行代理配置,對服務端透明。

反向代理:將服務端作為網絡用戶。訪問過程與正向代理相同,不過此過程對客戶端透明,需服務端進行代理配置(也可不配置)。

針對正向代理和反向代理,分別有不同的代理協議,即代理服務器和網絡用戶之間通信所使用的協議:

正向代理:

http

https

socks4

socks5

vpn:就功能而言,vpn 也可以被認為是代理

反向代理:

tcp

udp

http

https

接下來我們就說說 http 代理。

http 代理概述

http 代理是正向代理中較為簡單的代理方式,它使用 http 協議作為客戶端和代理服務器的傳輸協議。

http 代理可以承載 http 協議,https 協議,ftp 協議等等。對于不同的協議,客戶端和代理服務器間的數據格式略有不同。

http 協議

我們先來看看 http 協議下客戶端發送給代理服務器的 HTTP Header:

//直接連接
GET/HTTP/1.1
Host:staight.github.io
Connection:keep-alive

//http代理
GEThttp://staight.github.io/HTTP/1.1
Host:staight.github.io
Proxy-Connection:keep-alive

可以看到,http 代理比起直接連接:

url 變成完整路徑,/->http://staight.github.io/

Connection字段變成Proxy-Connection字段

其余保持原樣

為什么使用完整路徑?

為了識別目標服務器。如果沒有完整路徑,且沒有 Host 字段的話,代理服務器將無法得知目標服務器的地址。

為什么使用 Proxy-Connection 字段代替 Connection 字段?

為了兼容使用 HTTP/1.0 協議的過時的代理服務器。HTTP/1.1 才開始有長連接功能,直接連接的情況下,客戶端發送的 HTTP Header 中如果有Connection: keep-alive字段,表示使用長連接和服務端進行 http 通信,但如果中間有過時的代理服務器,該代理服務器將無法與客戶端和服務端進行長連接,造成客戶端和服務端一直等待,白白浪費時間。

因此使用Proxy-Connection字段代替Connection字段,如果代理服務器使用 HTTP/1.1 協議,能夠識別Proxy-Connection字段,則將該字段轉換成Connection再發送給服務端;如果不能識別,直接發送給服務端,因為服務端也無法識別,則使用短連接進行通信。

http 代理 http 協議交互過程如圖:

6306faa6-d6f2-11ed-bfe3-dac502259ad0.png

http 代理 http 協議

https 協議

接下來我們來看看 https 協議下,客戶端發送給代理服務器的 HTTP Header:

CONNECTstaight.github.io:443HTTP/1.1
Host:staight.github.io:443
Proxy-Connection:keep-alive

如上,https 協議和 http 協議相比:

請求方法從GET變成CONNECT

url 沒有 protocol 字段

實際上,由于 https 下客戶端和服務端的通信除了開頭的協商以外都是密文,中間的代理服務器不再承擔修改 http 報文再轉發的功能,而是一開始就和客戶端協商好服務端的地址,隨后的 tcp 密文直接轉發即可。

http 代理 https 協議交互過程如圖:

6314f73c-d6f2-11ed-bfe3-dac502259ad0.png

代碼實現

首先,創建 tcp 服務,并且對于每個 tcp 請求,均調用 handle 函數:

//tcp連接,監聽8080端口
l,err:=net.Listen("tcp",":8080")
iferr!=nil{
log.Panic(err)
}

//死循環,每當遇到連接時,調用handle
for{
client,err:=l.Accept()
iferr!=nil{
log.Panic(err)
}

gohandle(client)
}

然后將獲取的數據放入緩沖區:

//用來存放客戶端數據的緩沖區
varb[1024]byte
//從客戶端獲取數據
n,err:=client.Read(b[:])
iferr!=nil{
log.Println(err)
return
}

從緩沖區讀取 HTTP 請求方法,URL 等信息:

varmethod,URL,addressstring
//從客戶端數據讀入method,url
fmt.Sscanf(string(b[:bytes.IndexByte(b[:],'
')]),"%s%s",&method,&URL)
hostPortURL,err:=url.Parse(URL)
iferr!=nil{
log.Println(err)
return
}

http 協議和 https 協議獲取地址的方式不同,分別處理:

//如果方法是CONNECT,則為https協議
ifmethod=="CONNECT"{
address=hostPortURL.Scheme+":"+hostPortURL.Opaque
}else{//否則為http協議
address=hostPortURL.Host
//如果host不帶端口,則默認為80
ifstrings.Index(hostPortURL.Host,":")==-1{//host不帶端口,默認80
address=hostPortURL.Host+":80"
}
}

用獲取到的地址向服務端發起請求。如果是 http 協議,將客戶端的請求直接轉發給服務端;如果是 https 協議,發送 http 響應:

//獲得了請求的host和port,向服務端發起tcp連接
server,err:=net.Dial("tcp",address)
iferr!=nil{
log.Println(err)
return
}
//如果使用https協議,需先向客戶端表示連接建立完畢
ifmethod=="CONNECT"{
fmt.Fprint(client,"HTTP/1.1200Connectionestablished

")
}else{//如果使用http協議,需將從客戶端得到的http請求轉發給服務端
server.Write(b[:n])
}

最后,將所有客戶端的請求轉發至服務端,將所有服務端的響應轉發給客戶端:

//將客戶端的請求轉發至服務端,將服務端的響應轉發給客戶端。io.Copy 為阻塞函數,文件描述符不關閉就不停止
goio.Copy(server,client)
io.Copy(client,server

完整的源代碼:

packagemain

import(
"bytes"
"fmt"
"io"
"log"
"net"
"net/url"
"strings"
)

funcmain(){
//tcp連接,監聽8080端口
l,err:=net.Listen("tcp",":8080")
iferr!=nil{
log.Panic(err)
}

//死循環,每當遇到連接時,調用handle
for{
client,err:=l.Accept()
iferr!=nil{
log.Panic(err)
}

gohandle(client)
}
}

funchandle(clientnet.Conn){
ifclient==nil{
return
}
deferclient.Close()

log.Printf("remoteaddr:%v
",client.RemoteAddr())

//用來存放客戶端數據的緩沖區
varb[1024]byte
//從客戶端獲取數據
n,err:=client.Read(b[:])
iferr!=nil{
log.Println(err)
return
}

varmethod,URL,addressstring
//從客戶端數據讀入method,url
fmt.Sscanf(string(b[:bytes.IndexByte(b[:],'
')]),"%s%s",&method,&URL)
hostPortURL,err:=url.Parse(URL)
iferr!=nil{
log.Println(err)
return
}

//如果方法是CONNECT,則為https協議
ifmethod=="CONNECT"{
address=hostPortURL.Scheme+":"+hostPortURL.Opaque
}else{//否則為http協議
address=hostPortURL.Host
//如果host不帶端口,則默認為80
ifstrings.Index(hostPortURL.Host,":")==-1{//host不帶端口,默認80
address=hostPortURL.Host+":80"
}
}

//獲得了請求的host和port,向服務端發起tcp連接
server,err:=net.Dial("tcp",address)
iferr!=nil{
log.Println(err)
return
}
//如果使用https協議,需先向客戶端表示連接建立完畢
ifmethod=="CONNECT"{
fmt.Fprint(client,"HTTP/1.1200Connectionestablished

")
}else{//如果使用http協議,需將從客戶端得到的http請求轉發給服務端
server.Write(b[:n])
}

//將客戶端的請求轉發至服務端,將服務端的響應轉發給客戶端。io.Copy 為阻塞函數,文件描述符不關閉就不停止
goio.Copy(server,client)
io.Copy(client,server)
}

添加代理,然后運行:

6321e8ac-d6f2-11ed-bfe3-dac502259ad0.png

632cae22-d6f2-11ed-bfe3-dac502259ad0.png

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Web
    Web
    +關注

    關注

    2

    文章

    1287

    瀏覽量

    71436
  • 服務器
    +關注

    關注

    13

    文章

    9795

    瀏覽量

    87993
  • 網絡
    +關注

    關注

    14

    文章

    7815

    瀏覽量

    90963
  • HTTP
    +關注

    關注

    0

    文章

    525

    瀏覽量

    33519
  • 客戶端
    +關注

    關注

    1

    文章

    301

    瀏覽量

    17094

原文標題:Golang 實現一個簡單的 http 代理

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    Golang怎么實現UTS隔離

    Golang實現UTS隔離
    發表于 08-23 14:44

    http代理的分類

    有著不同的安全性,下面就隨著億牛云代理的腳步起看看HTTP代理是怎么按安全性分類的吧。透明代理(簡單
    發表于 12-20 17:25

    Golang爬蟲語言接入代理

    都是可以寫出爬蟲系統的。無論用什么爬蟲語言框架,長期使用IP去采集數據,肯定會收到限制。這種時候就需要使用爬蟲代理去解決問題。
    發表于 09-09 17:41

    HTTP反向代理服務器的編寫程序

    在 Node.js 上實現簡單HTTP 代理程序還是非常
    的頭像 發表于 10-06 10:00 ?4422次閱讀
    <b class='flag-5'>HTTP</b>反向<b class='flag-5'>代理</b>服務器的編寫程序

    如何在Golang實現反向代理

    【導讀】在本文中,我們將了解反向代理,它的應用場景以及如何在 Golang實現它。 反向代理是位于 Web 服務器前面并將客戶端(例如 Web 瀏覽器)的請求轉發到 Web 服務器
    的頭像 發表于 08-23 10:22 ?2386次閱讀

    http代理概述及代碼實現方法

    本文詳細介紹了Golang 實現 http 代理實現,在實際業務中有需求的同學可以學起來了!
    的頭像 發表于 05-14 15:02 ?4541次閱讀

    python代碼中使用HTTP代理IP,demo注釋清晰

    API鏈接,就可以跑起來了。 以下是示例代碼,只是基礎的演示,具體的代碼還是要根據你業務的實際情況去寫的。 示例代碼中的HTTP
    的頭像 發表于 08-04 15:40 ?1245次閱讀

    java中怎么使用HTTP代理

    java中怎么使用HTTP代理,華益云python爬蟲ip
    的頭像 發表于 09-01 14:31 ?1926次閱讀

    python中怎么使用HTTP代理

    python中怎么使用HTTP代理,華益云高匿爬蟲代理ip
    的頭像 發表于 09-01 14:36 ?1855次閱讀

    PHP中怎么使用HTTP代理

    PHP中怎么使用HTTP代理,華益云高匿爬蟲代理ip
    的頭像 發表于 09-01 14:38 ?1975次閱讀

    go語言中怎么使用HTTP代理

    go語言中怎么使用HTTP代理。
    的頭像 發表于 09-01 14:41 ?2678次閱讀

    http代理的作用如下所示

    經常使用網絡的人可能會常常聽到這樣的一個詞:http代理。那么它真正的作用很多人都是模棱兩可的,在這里給大家普及下在我們大部分人的網絡活動中,ht
    發表于 09-15 13:00 ?621次閱讀

    解析Golang定時任務庫gron設計和原理

    正巧,最近看到了 gron 這個開源項目,它是用 Golang 實現并發安全的定時任務庫。實現非常
    的頭像 發表于 12-15 13:57 ?1694次閱讀

    快速應用程序開發(RAD)工具(Golang版)

    SNMPAgent Builder(Golang版)是快速應用程序開發(RAD)工具,用于基于Golang 的 SNMP代理開發。提供了
    的頭像 發表于 04-13 09:30 ?1825次閱讀

    Golang配置代理方法

    由于些客觀原因的存在,我們開發 Golang 項目的過程總會碰到無法下載某些依賴包的問題。這不是小問題,因為你的工作會被打斷,即便你使用各種神通解決了問題,很可能這時你的線程已經
    的頭像 發表于 11-11 11:17 ?1037次閱讀
    <b class='flag-5'>Golang</b>配置<b class='flag-5'>代理</b>方法
    主站蜘蛛池模板: 高清国产美女在线观看 | 日本三级日本三级日本三级极 | 午夜免费观看福利片一区二区三区 | 中国成人免费视频 | 月夜免费观看高清在线完整 | bt在线www天堂资源网 | 国产亚洲精品在天天在线麻豆 | 8050午夜| 中文字幕有码在线视频 | 亚色影视 | 日本高清黄色 | 国产精品天天看大片特色视频 | 三级五月天 | 中文字幕亚洲一区二区三区 | 精品视频卡1卡2卡3 精品视频免费看 | 在线看片一区 | 国产精品久久久久久久人热 | 欧美不卡一区 | 日本毛片大全 | 2021久久精品国产99国产 | 天堂中文在线最新版地址 | 67xxxxxx日本| 欧美一级特黄aaa大片 | 国产性老妇女做爰在线 | 亚洲先锋资源 | 亚洲在线a | 免费日本视频 | 日本三级在线播放线观看2021 | 久久香蕉国产线看观看亚洲片 | 欧美美女被日 | 加勒比在线视频 | 综合色中色| 黄 色 免 费 网站在线观看 | 黄色视屏免费在线观看 | 亚洲精品精品一区 | 国产高清色播视频免费看 | 成人午夜小视频手机在线看 | 日本一区二区高清免费不卡 | 亚洲伊人天堂 | 日韩基地1024首页 | 美女午夜影院 |