Use beetle to implement HTTP proxy service

Source: Internet
Author: User

Previously, beetle's applications were all based on custom messages. This component can only be used for this purpose. in fact, beetle is only a basic TCP component, which can be used to complete other protocol communication work. the following is a simple HTTP Proxy Server created by beetle. To verify the functionality of this proxy server, write thisArticleIt is also submitted through the HTTP Proxy Server. The following describes beetle to implement this function.

Beetle does not provide HTTP encapsulation. To analyze the HTTP protocol, a simple http protocol analyzer must be implemented. the component provides the Package base class and its extended eofdataofpackage and headsizeofpackage. HTTP is an end-based cooperator that can be derived directly from eofdataofpackage. the following is a simple implementation of the HTTP protocol analysis class:

Public class httppackage: beetle. eofdataofpackage {public httppackage (beetle. tcpchannel channel): Base (Channel) {} public static beetle. bytearraypool blockbytearraypool = new Beetle. bytearraypool (200, beetle. tcputils. receivebufferlength); protected override beetle. iMessage getmessage (string name) {return New httpmessage ();} private httpmessage httpmsg = NULL; private int mcontentlength = 0; Pub LIC override void import (byte [] data, int start, int count) {int rcount = 0; If (httpmsg = NULL) {httpmsg = new httpmessage (); int httpendindex = byteindexof (data, eofdata); If (httpendindex <0) Throw beetle. nettcpexception. readdataerror (null); rcount = httpendindex + 1; loadhttpinfo (encoding. ASCII. getstring (data, 0, rcount), httpmsg); onreceivemessage (httpmsg); If (! Httpmsg. hasbody &&! Httpmsg. isgzip) httpmsg = NULL;} If (rcount <count & mcontentlength> 0) {httpbodyblock block = new httpbodyblock (); block. data = blockbytearraypool. pop (); buffer. blockcopy (data, start + rcount, block. data. array, 0, Count-rcount); mcontentlength = mcontentlength-(count-rcount); block. data. setinfo (0, Count-rcount); onreceivemessage (Block); mcontentlength = mcontentlength-(count-rcoun T); If (mcontentlength = 0) httpmsg = NULL;} else if (rcount <count) {httpbodyblock block = new httpbodyblock (); block. data = blockbytearraypool. pop (); buffer. blockcopy (data, start + rcount, block. data. array, 0, Count-rcount); mcontentlength = mcontentlength-(count-rcount); block. data. setinfo (0, Count-rcount); onreceivemessage (Block) ;}} private void loadhttpinfo (string info, httpmess Age HTTP) {string [] properties = info. split (New char [] {'\ R',' \ n'}, stringsplitoptions. removeemptyentries); http. httpmethod = properties [0]; mcontentlength = 0; For (INT I = 1; I <properties. length; I ++) {string property = properties [I]; int Index = property. indexof (':'); httpmessage. header header = new httpmessage. header (); header. name = property. substring (0, index); header. value = Property. Substring (index + 1, (property. length-index-1); http. headers. add (header); If (header. name = "Content-Length") {mcontentlength = int. parse (header. value. trim (); http. hasbody = true;} If (header. name = "host") {string [] values = header. value. split (':'); http. host = values [0]. trim (); If (values. length> 1) HTTP. port = int. parse (Values [1]. trim ();} If (header. name = "proxy-connection "){ Header. name = "connection";} If (header. name = "content-encoding") {If (header. value. indexof ("gzip", stringcomparison. invariantcultureignorecase)> = 0) HTTP. isgzip = true ;}} if (! String. isnullorempty (HTTP. host) HTTP. httpmethod = http. httpmethod. replace ("http: //" + HTTP. host. trim (), "");} public override void messagewrite (beetle. iMessage MSG, beetle. bufferwriter writer) {MSG. save (writer); If (MSG is httpbodyblock) {blockbytearraypool. push (httpbodyblock) MSG ). data) ;}} Private Static byte [] meofdata = encoding. ASCII. getbytes ("\ r \ n"); protected override byte [] eofdata {get {return meofdata ;}}}

Message analysis is relatively simple. First, check whether there is any HTTP request or response information. If there is no response information, obtain the relevant HTTP information first. the content data is obtained based on contentlength, including the submitted data. however, some gzip requests do not contain contentlength. in general, an HTTP protocol analysis is complete.

After the protocol analysis is complete, the proxy interaction is partially implemented. When a request is accessed, a new destination connection is generated based on the current HTTP request information.

Private void onrequestreceive (beetle. packetrecievemessagerargs e) {sendtotarget (E. message); If (E. message is httppackage. httpmessage) {httppackage. httpmessage HTTP = (httppackage. httpmessage) E. message; If (mtargetchannel = NULL) {createtarget (HTTP) ;}} private void createtarget (httppackage. httpmessage HTTP) {try {system. net. IPaddress [] IPaddress = system. net. DNS. gethostaddresses (HTTP. host); beetle. tcpserver. createclientasync (IPaddress [0], HTTP. port, ontargetcreate);} catch (exception E _) {console. writeline (E _. message); dispose ();}}

Determine whether the target connection of the current connection exists. If the connection does not exist, create a connection. After the connection is created, the data forwarding of the two connections is interacted.

 private void ontargetreceive (beetle. packetrecievemessagerargs e) {If (E. message is httppackage. httpmessage) {httppackage. httpmessage HTTP = (httppackage. httpmessage) E. message; console. writeline ("{0} response to {1}", mtargetchannel. endpoint, mrequestchannel. endpoint); console. write (HTTP); responsehttps. add (HTTP); mrequestchannel. send (HTTP);} else {httppackage. httpbodyblock block = (httppackage. httpbodyblock) E. message; mrequestchannel. send (Block); console. writeline ("{0} response to {1}", mtargetchannel. endpoint, mrequestchannel. endpoint); console. writeline ("response datalength:" + block. data. count) ;}}

Now an HTTP Proxy server has been completed, which is just a common HTTP Proxy function and does not work for HTTPS. if you want to create a perfect HTTP proxy server, you must first have a detailed understanding of the HTTP protocol, do not release the connection, and recycle memory usage. this is just a simple example. the following shows the effect of www.163.com through this proxy service. If you want to use it to overturn the wall, it will not work. :) the HTTP protocol wall will certainly be blocked, if you want to overturn the wall, a client will be submitted to the proxy server after obtaining HTTP encryption locally, and the proxy server will decrypt and forward the data :)

Download completeCode:

Proxyserver.rar (210.98 KB)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.