go代理服务器代码

go代理服务器代码

最近用废弃的小笔记本搭了个centos服务器挂着,搭了ssh,tomcat,go环境,想搭个代理服务器访问路由,不想安装,想自己写一个,顺便复习一下go语言知识。

一开始,我网上搜了一下go语言写代理服务器的代理,搜索到一个:

来自:http://symphony.b3log.org/article/1357452978419

(原文地址:http://kejibo.com/golang-http-proxy-server 已失效)

package main

import (
    "http"
    "log"
    "os"
    "io/ioutil"
)

func handler(w http.ResponseWriter, r *http.Request) {
    resp, err := http.DefaultClient.Do(r)
    defer resp.Body.Close()
    if err != nil { panic(err) }
    for k, v := range resp.Header {
        for _, vv := range v {
            w.Header().Add(k, vv)
        }
    }
    for _, c := range resp.SetCookie {
        w.Header().Add("Set-Cookie", c.Raw)
    }
    w.WriteHeader(resp.StatusCode)
    result, err := ioutil.ReadAll(resp.Body)
    if err != nil && err != os.EOF { panic(err) }
    w.Write(result)
}

func main() {
    http.HandleFunc("/", handler)
    log.Println("Start serving on port 8888")
    http.ListenAndServe(":8888", nil)
    os.Exit(0)
}

写成文件上传到服务器,go build test.go 编译,发现resp.SetCookie根本没有这个方法,编译不通过,上面文章说它要最新的http源码并编译到go源码里,我都惊呆了,还要修改它的源码啊,我看了下自己的go语言版本,是1.4.2,是15年今年的了,他写的文章的时候是13年,呵呵了,我的比他的新多了,怎么可能会旧?!还有他说的编译源码,是多么复杂啊~

于是乎。机智的我,为了编译通过,活生生的把它注释了。

go build test.go

好了,编译通过,执行它

/.test

显示开启了,还是要证实一下,扫描一下端口,看了下确实开了。

好像完成了喔,于是去浏览器设置一下代理,打开baidu.com,他告诉我方法错误了,我查看了一下打印信息,发现

defer resp.Body.Close()

这行报这个错:

invalid memory address or nil pointer dereference

网上找了一下,原来是resp变量空指针错误。

我又尝试打印err信息:

http: Request.RequestURI can’t be set in client requests.

就是说,ttp.DefaultClient.Do(r)这个用法是不正确的,是不能这样设置的,于是我找了一个替代品:http.NewRequest,它的优点就是可以get也可以post,应该还有put等操作,没尝试。

于是这段handler function被我耐心的改成了这样:

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

    fmt.Println("url:",r.RequestURI)
    fmt.Println("method:",r.Method)
    fmt.Println("header:",r.Header)

    client0 := &http.Client{}
    req, _ := http.NewRequest(r.Method, r.RequestURI, r.Body)

    fmt.Printf("send:%+v\n", req)                                                         //看下发送的结构

    resp, err := client0.Do(req) //发送

    if err!=nil {
                fmt.Println("error:",err)
            }
    defer resp.Body.Close()

    for _, value := range resp.Request.Cookies() {
        w.Header().Add(value.Name,value.Value)
    }

    for k, v := range resp.Header {
                for _, vv := range v {
                    w.Header().Add(k, vv)
                }
            }
    w.WriteHeader(resp.StatusCode)

    result, err := ioutil.ReadAll(resp.Body)
    if (err != nil) {
        fmt.Println("error:",err)
    }
    fmt.Println("result:" ,result);

    _,err = w.Write(result)
    if (err != nil) {
        fmt.Println("error:",err)
    }

实际上我是在mac电脑上编辑的,用服务器上传在编译运行速度太慢了 = =、

看上去,代码好像写的很不错的样子。

运行起来,访问baidu死循环啦,我又改了几次,看了几次,还是这样,无奈的我只好测试其他网站,那个测试的网站是我的一个简单的jsp网页,就一个简单的列表,我一访问,竟然快速的出现了,竟然成功访问了,可是我没改到什么代码啊,我在认真的想了一想,应该是访问baidu的时候没有放请求头过去,导致它访问baidu.com的时候,源码里面的链接是post访问的,且都是baidu.com,为了证实我的猜想,我添加了请求头个cookie上去

......
    req, _ := http.NewRequest(r.Method, r.RequestURI, r.Body)
    for k, v := range req.Header {
        for _, vv := range v {
            r.Header.Add(k, vv)
        }
    }
    for _, value := range req.Cookies() {
        r.Header.Add(value.Name,value.Value)
    }
......

编译运行,浏览器重新刷新,竟然一下子就打了,我的猜想原来是正确的。

服务器基本完成,进入测试阶段,先百度一下,成功了,不过部分图片裂开了,在进入其他的,csdn可以访问,图片问题,sina正常,oschina正常,就是百度那个图片加载时裂了。读者有兴趣自行研究研究,在这,我只是先把简单的代理服务器帖上来,方便大家使用。

最后浏览了一下整改代理服务器的代码:

package main

import (
    "net/http"
    "log"
    "io/ioutil"
//  "io"
    "fmt"
)

func handler(w http.ResponseWriter, r *http.Request) {
//  http.DefaultClient.
//  w.Write([]byte("dddd"))

    fmt.Println("url:",r.RequestURI)
    fmt.Println("method:",r.Method)
    fmt.Println("header:",r.Header)

    client0 := &http.Client{}
    req, _ := http.NewRequest(r.Method, r.RequestURI, r.Body)
    for k, v := range req.Header {
        for _, vv := range v {
            r.Header.Add(k, vv)
        }
    }
    for _, value := range req.Cookies() {
        r.Header.Add(value.Name,value.Value)
    }

    fmt.Printf("send:%+v\n", req)                                                         //看下发送的结构

    resp, err := client0.Do(req) //发送

    if err!=nil {
                fmt.Println("error:",err)
            }
    defer resp.Body.Close()

    for _, value := range resp.Request.Cookies() {
        w.Header().Add(value.Name,value.Value)
    }

    for k, v := range resp.Header {
                for _, vv := range v {
                    w.Header().Add(k, vv)
                }
            }
    w.WriteHeader(resp.StatusCode)

    result, err := ioutil.ReadAll(resp.Body)
    if (err != nil) {
        fmt.Println("error:",err)
    }
    fmt.Println("result:" ,result);

    _,err = w.Write(result)
    if (err != nil) {
        fmt.Println("error:",err)
    }

}

func main() {
    http.HandleFunc("/", handler)
    log.Println("Start serving on port 8089")
     http.ListenAndServe(":8089", nil)
    log.Println("server start")
}

看看自己改的代码,和网上那个人得代码,原来相差那么多,看哭了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 21:49:54

go代理服务器代码的相关文章

网站安全攻击和防御中的屏蔽代理服务器

网站安全攻击和防御中的屏蔽代理服务器 网站安全一直是个重要话题,本人写了网络攻防的屏蔽代理服务器相关代码,分享下: 1. 写个网页request类: using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks;

FastRPC 3.2 发布,高性能 C++ 协程 RPC 框架

用过go erlang gevent的亲们应该都会知道协程在应用中带来的方便. 如果对协程不理解的同学,通过阅读下面例子可以快速了解我们框架的协程的意义,已了解的可以跳过这部分. 协程例子:假设我们要发个Get请求获取百度首页内容: php同步方式:$result = file_get_contents("http://www.baidu.com"), php果然是世界上最好的语言,多么简洁. 然后java和c++的同学开始不屑了: "呵呵, 同步,鄙视你不解释."

用户扫码微信二维码生成订单(三)

官方API:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1 首先要修改/lib/HttpService.cs 把Get和Post中的的设置代理服务器代码进行隐藏: 修改前: WebProxy proxy = new WebProxy();proxy.Address = new Uri(WxPayConfig.PROXY_URL);request.Proxy = proxy; 修改后: //WebProxy proxy =

软件工程师树莓派获取室内温湿度的坎坷之旅

背景 前几天公司接受到了一份来自阿里飞天园区,IOT部门的小礼物.由于上司比较忙,无暇去顾及. 当时尚未开封,我好奇是什么,于是就急忙忙的拆开,发现是Raspberry Pi 3(树莓派3).我觉得挺好玩的,就接过来了,于是上司就兴起,就让我拿这个小玩意去验证阿里物联网平台上的相关组件.于是,就有了这个软件工程师树莓派实现室内温湿度坎坷之旅! 以下是开箱的东西: 树莓派3(Raspberry Pi 3 Model B+) 树莓派3代B+板 树莓派USB电源适配器[email protected]

错误和问题解决的成本

问题描写叙述 错误 数据收集 根本原因 版本号   组件:数据修复           在一个实际成本组织中,(平均,先进先出,后进先出) 一个或更 多的下面情况可能发生: 1.导航到物料成本历史表单上的数量信息,与现有量表单的数量不匹配的记录 2. 一些物料前期已计成本的数量与前面的事务处理历史表单的数量不匹配 3. 全部的库存值报表与事务处理值报表不匹配 4. 存货层次成本更新表单的总数量与现有量数量表单不匹配(只在先进先出/后进先出) 5.这些症状的不论什么一个意味着 MMT-CQL不匹配

50行python代码实现个代理服务器(你懂的)

之前遇到一个场景是这样的: 我在自己的电脑上需要用mongodb图形客户端,但是mongodb的服务器地址没有对外网开放,只能通过先登录主机A,然后再从A连接mongodb服务器B. 本来想通过ssh端口转发的,但是我没有从机器A连接ssh到B的权限.于是就自己用python写一个. 原理很简单. 1.开一个socket server监听连接请求 2.每接受一个客户端的连接请求,就往要转发的地址建一条连接请求.即client->proxy->forward.proxy既是socket服务端(监

8 行 Node.js 代码实现代理服务器

接触 Node.js 已有多年,一直喜欢它的单线程模型和异步IO特性,以及 JavaScript 语言本身的灵活性.同时,JavaScript 前后端通吃,在全栈开发领域具有独特的优势.今天就来看看作为服务端语言的 JavaScript,完成一个简单的代理服务器功能是多么容易. 简单地说,代理服务器就是代理用户访问目标站点的中介服务器.作为前端开发人员,代理的常见用途是跨域访问后台 API.当然,还可以用来科学上网.今天要分享的代码,就是跟科学上网有关. 话不多说,先上 code: var ex

Python 50行代码实现代理服务器(加强版)

网上很多python 50行代码实现代理服务器,但是易出现异常,导致退出. 这里的代理服务器,是指二级代理服务器.比如:A可以访问B,B可以访问C,A不能直接访问C.这时,如果在B开一个二级代理,就可实现A访问C.现有的工具有CCProxy. 这里就是使用Python简单的实现一个二级代理. #coding=utf-8 import socket import select import sys import threading import time import logging import

使用代理服务器挖掘微信文章代码

使用python3.5对weixin.sogou.com中的微信文章进行文章的爬取,浏览器为火狐浏览器,代理服务器使用fiddler,代码如下 1 import re 2 import urllib.request 3 import time 4 import urllib.error 5 def use_proxy(proxy_addr,url): 6 try: 7 req=urllib.request.Request(url) 8 req.add_header('User-Agent','M