女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Golang實(shí)現(xiàn)一個(gè)簡(jiǎn)單的http代理

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

掃碼添加小助手

加入工程師交流群

本文詳細(xì)介紹了Golang 實(shí)現(xiàn) http 代理的實(shí)現(xiàn),在實(shí)際業(yè)務(wù)中有需求的同學(xué)可以學(xué)起來了!

代理是網(wǎng)絡(luò)中的一項(xiàng)重要的功能,其功能就是代理網(wǎng)絡(luò)用戶去取得網(wǎng)絡(luò)信息。形象的說:它是網(wǎng)絡(luò)信息的中轉(zhuǎn)站,對(duì)于客戶端來說,代理扮演的是服務(wù)器的角色,接收請(qǐng)求報(bào)文,返回響應(yīng)報(bào)文;對(duì)于 web 服務(wù)器來說,代理扮演的是客戶端的角色,發(fā)送請(qǐng)求報(bào)文,接收響應(yīng)報(bào)文。

代理具有多種類型,如果是根據(jù)網(wǎng)絡(luò)用戶劃分的話,可以劃分為正向代理和反向代理:

正向代理:將客戶端作為網(wǎng)絡(luò)用戶。客戶端訪問服務(wù)端時(shí),先訪問代理服務(wù)器,隨后代理服務(wù)器再訪問服務(wù)端。此過程需客戶端進(jìn)行代理配置,對(duì)服務(wù)端透明。

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

針對(duì)正向代理和反向代理,分別有不同的代理協(xié)議,即代理服務(wù)器和網(wǎng)絡(luò)用戶之間通信所使用的協(xié)議:

正向代理:

http

https

socks4

socks5

vpn:就功能而言,vpn 也可以被認(rèn)為是代理

反向代理:

tcp

udp

http

https

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

http 代理概述

http 代理是正向代理中較為簡(jiǎn)單的代理方式,它使用 http 協(xié)議作為客戶端和代理服務(wù)器的傳輸協(xié)議。

http 代理可以承載 http 協(xié)議,https 協(xié)議,ftp 協(xié)議等等。對(duì)于不同的協(xié)議,客戶端和代理服務(wù)器間的數(shù)據(jù)格式略有不同。

http 協(xié)議

我們先來看看 http 協(xié)議下客戶端發(fā)送給代理服務(wù)器的 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字段

其余保持原樣

為什么使用完整路徑?

為了識(shí)別目標(biāo)服務(wù)器。如果沒有完整路徑,且沒有 Host 字段的話,代理服務(wù)器將無(wú)法得知目標(biāo)服務(wù)器的地址。

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

為了兼容使用 HTTP/1.0 協(xié)議的過時(shí)的代理服務(wù)器。HTTP/1.1 才開始有長(zhǎng)連接功能,直接連接的情況下,客戶端發(fā)送的 HTTP Header 中如果有Connection: keep-alive字段,表示使用長(zhǎng)連接和服務(wù)端進(jìn)行 http 通信,但如果中間有過時(shí)的代理服務(wù)器,該代理服務(wù)器將無(wú)法與客戶端和服務(wù)端進(jìn)行長(zhǎng)連接,造成客戶端和服務(wù)端一直等待,白白浪費(fèi)時(shí)間。

因此使用Proxy-Connection字段代替Connection字段,如果代理服務(wù)器使用 HTTP/1.1 協(xié)議,能夠識(shí)別Proxy-Connection字段,則將該字段轉(zhuǎn)換成Connection再發(fā)送給服務(wù)端;如果不能識(shí)別,直接發(fā)送給服務(wù)端,因?yàn)榉?wù)端也無(wú)法識(shí)別,則使用短連接進(jìn)行通信。

http 代理 http 協(xié)議交互過程如圖:

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

http 代理 http 協(xié)議

https 協(xié)議

接下來我們來看看 https 協(xié)議下,客戶端發(fā)送給代理服務(wù)器的 HTTP Header:

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

如上,https 協(xié)議和 http 協(xié)議相比:

請(qǐng)求方法從GET變成CONNECT

url 沒有 protocol 字段

實(shí)際上,由于 https 下客戶端和服務(wù)端的通信除了開頭的協(xié)商以外都是密文,中間的代理服務(wù)器不再承擔(dān)修改 http 報(bào)文再轉(zhuǎn)發(fā)的功能,而是一開始就和客戶端協(xié)商好服務(wù)端的地址,隨后的 tcp 密文直接轉(zhuǎn)發(fā)即可。

http 代理 https 協(xié)議交互過程如圖:

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

代碼實(shí)現(xiàn)

首先,創(chuàng)建 tcp 服務(wù),并且對(duì)于每個(gè) tcp 請(qǐng)求,均調(diào)用 handle 函數(shù):

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

//死循環(huán),每當(dāng)遇到連接時(shí),調(diào)用handle
for{
client,err:=l.Accept()
iferr!=nil{
log.Panic(err)
}

gohandle(client)
}

然后將獲取的數(shù)據(jù)放入緩沖區(qū):

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

從緩沖區(qū)讀取 HTTP 請(qǐng)求方法,URL 等信息:

varmethod,URL,addressstring
//從客戶端數(shù)據(jù)讀入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 協(xié)議和 https 協(xié)議獲取地址的方式不同,分別處理:

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

用獲取到的地址向服務(wù)端發(fā)起請(qǐng)求。如果是 http 協(xié)議,將客戶端的請(qǐng)求直接轉(zhuǎn)發(fā)給服務(wù)端;如果是 https 協(xié)議,發(fā)送 http 響應(yīng):

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

")
}else{//如果使用http協(xié)議,需將從客戶端得到的http請(qǐng)求轉(zhuǎn)發(fā)給服務(wù)端
server.Write(b[:n])
}

最后,將所有客戶端的請(qǐng)求轉(zhuǎn)發(fā)至服務(wù)端,將所有服務(wù)端的響應(yīng)轉(zhuǎn)發(fā)給客戶端:

//將客戶端的請(qǐng)求轉(zhuǎn)發(fā)至服務(wù)端,將服務(wù)端的響應(yīng)轉(zhuǎn)發(fā)給客戶端。io.Copy 為阻塞函數(shù),文件描述符不關(guān)閉就不停止
goio.Copy(server,client)
io.Copy(client,server

完整的源代碼:

packagemain

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

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

//死循環(huán),每當(dāng)遇到連接時(shí),調(diào)用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())

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

varmethod,URL,addressstring
//從客戶端數(shù)據(jù)讀入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協(xié)議
ifmethod=="CONNECT"{
address=hostPortURL.Scheme+":"+hostPortURL.Opaque
}else{//否則為http協(xié)議
address=hostPortURL.Host
//如果host不帶端口,則默認(rèn)為80
ifstrings.Index(hostPortURL.Host,":")==-1{//host不帶端口,默認(rèn)80
address=hostPortURL.Host+":80"
}
}

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

")
}else{//如果使用http協(xié)議,需將從客戶端得到的http請(qǐng)求轉(zhuǎn)發(fā)給服務(wù)端
server.Write(b[:n])
}

//將客戶端的請(qǐng)求轉(zhuǎn)發(fā)至服務(wù)端,將服務(wù)端的響應(yīng)轉(zhuǎn)發(fā)給客戶端。io.Copy 為阻塞函數(shù),文件描述符不關(guān)閉就不停止
goio.Copy(server,client)
io.Copy(client,server)
}

添加代理,然后運(yùn)行:

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

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

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Web
    Web
    +關(guān)注

    關(guān)注

    2

    文章

    1287

    瀏覽量

    71385
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    13

    文章

    9791

    瀏覽量

    87929
  • 網(wǎng)絡(luò)
    +關(guān)注

    關(guān)注

    14

    文章

    7814

    瀏覽量

    90912
  • HTTP
    +關(guān)注

    關(guān)注

    0

    文章

    525

    瀏覽量

    33492
  • 客戶端
    +關(guān)注

    關(guān)注

    1

    文章

    301

    瀏覽量

    17089

原文標(biāo)題:Golang 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 http 代理

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    Golang怎么實(shí)現(xiàn)UTS隔離

    Golang實(shí)現(xiàn)UTS隔離
    發(fā)表于 08-23 14:44

    http代理的分類

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

    Golang爬蟲語(yǔ)言接入代理

    都是可以寫出個(gè)爬蟲系統(tǒng)的。無(wú)論用什么爬蟲語(yǔ)言框架,長(zhǎng)期使用個(gè)IP去采集數(shù)據(jù),肯定會(huì)收到限制。這種時(shí)候就需要使用爬蟲代理去解決問題。
    發(fā)表于 09-09 17:41

    HTTP反向代理服務(wù)器的編寫程序

    在 Node.js 上實(shí)現(xiàn)個(gè)簡(jiǎn)單HTTP 代理程序還是非常
    的頭像 發(fā)表于 10-06 10:00 ?4420次閱讀
    <b class='flag-5'>HTTP</b>反向<b class='flag-5'>代理</b>服務(wù)器的編寫程序

    如何在Golang實(shí)現(xiàn)反向代理

    【導(dǎo)讀】在本文中,我們將了解反向代理,它的應(yīng)用場(chǎng)景以及如何在 Golang實(shí)現(xiàn)它。 反向代理是位于 Web 服務(wù)器前面并將客戶端(例如 Web 瀏覽器)的請(qǐng)求轉(zhuǎn)發(fā)到 Web 服務(wù)器
    的頭像 發(fā)表于 08-23 10:22 ?2378次閱讀

    http代理概述及代碼實(shí)現(xiàn)方法

    本文詳細(xì)介紹了Golang 實(shí)現(xiàn) http 代理實(shí)現(xiàn),在實(shí)際業(yè)務(wù)中有需求的同學(xué)可以學(xué)起來了!
    的頭像 發(fā)表于 05-14 15:02 ?4531次閱讀

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

    API鏈接,就可以跑起來了。 以下是個(gè)示例代碼,只是個(gè)基礎(chǔ)的演示,具體的代碼還是要根據(jù)你業(yè)務(wù)的實(shí)際情況去寫的。 示例代碼中的HTTP
    的頭像 發(fā)表于 08-04 15:40 ?1240次閱讀

    java中怎么使用HTTP代理

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

    python中怎么使用HTTP代理

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

    PHP中怎么使用HTTP代理

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

    go語(yǔ)言中怎么使用HTTP代理

    go語(yǔ)言中怎么使用HTTP代理
    的頭像 發(fā)表于 09-01 14:41 ?2673次閱讀

    http代理的作用如下所示

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

    解析Golang定時(shí)任務(wù)庫(kù)gron設(shè)計(jì)和原理

    正巧,最近看到了 gron 這個(gè)開源項(xiàng)目,它是用 Golang 實(shí)現(xiàn)個(gè)并發(fā)安全的定時(shí)任務(wù)庫(kù)。實(shí)現(xiàn)非常簡(jiǎn)
    的頭像 發(fā)表于 12-15 13:57 ?1686次閱讀

    個(gè)快速應(yīng)用程序開發(fā)(RAD)工具(Golang版)

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

    Golang配置代理方法

    由于些客觀原因的存在,我們開發(fā) Golang 項(xiàng)目的過程總會(huì)碰到無(wú)法下載某些依賴包的問題。這不是個(gè)小問題,因?yàn)槟愕墓ぷ鲿?huì)被打斷,即便你使用各種神通解決了問題,很可能這時(shí)你的線程已經(jīng)
    的頭像 發(fā)表于 11-11 11:17 ?1028次閱讀
    <b class='flag-5'>Golang</b>配置<b class='flag-5'>代理</b>方法