Exemple #1
0
func TestContentType(t *testing.T) {
	client, proxy, l := oneShotProxy(t)
	defer l.Close()

	proxy.OnResponse(goproxy.ContentTypeIs("image/png")).DoFunc(func(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
		resp.Header.Set("X-Shmoopi", "1")
		return resp
	})

	for _, file := range []string{"test_data/panda.png", "test_data/football.png"} {
		if resp, err := client.Get(localFile(file)); err != nil || resp.Header.Get("X-Shmoopi") != "1" {
			if err == nil {
				t.Error("pngs should have X-Shmoopi header = 1, actually", resp.Header.Get("X-Shmoopi"))
			} else {
				t.Error("error reading png", err)
			}
		}
	}

	file := "baby.jpg"
	if resp, err := client.Get(localFile(file)); err != nil || resp.Header.Get("X-Shmoopi") != "" {
		if err == nil {
			t.Error("Non png images should NOT have X-Shmoopi header at all", resp.Header.Get("X-Shmoopi"))
		} else {
			t.Error("error reading png", err)
		}
	}
}
Exemple #2
0
package goproxy_html

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"strings"

	"code.google.com/p/go-charset/charset"
	_ "code.google.com/p/go-charset/data"
	"github.com/elazarl/goproxy"
)

var IsHtml goproxy.RespCondition = goproxy.ContentTypeIs("text/html")

var IsCss goproxy.RespCondition = goproxy.ContentTypeIs("text/css")

var IsJavaScript goproxy.RespCondition = goproxy.ContentTypeIs("text/javascript",
	"application/javascript")

var IsJson goproxy.RespCondition = goproxy.ContentTypeIs("text/json")

var IsXml goproxy.RespCondition = goproxy.ContentTypeIs("text/xml")

var IsWebRelatedText goproxy.RespCondition = goproxy.ContentTypeIs("text/html",
	"text/css",
	"text/javascript", "application/javascript",
	"text/xml",
	"text/json")
Exemple #3
0
func main() {
	proxy := goproxy.NewProxyHttpServer()

	proxy.OnRequest().DoFunc(func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
		r.Header.Add("Accept-Encoding", "sdch")

		if len(dictName) > 0 {
			rawId, err := hex.DecodeString(dictName)
			if err != nil {
				log.Println(err)
				return r, nil
			}
			uaId := base64.URLEncoding.EncodeToString(rawId[:6])
			r.Header.Set("Avail-Dictionary", uaId)
		}
		return r, nil
	})

	proxy.OnResponse().DoFunc(func(r *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
		dictUrl := r.Header.Get("Get-Dictionary")
		if dictUrl == "" {
			return r
		}

		dictName := path.Base(dictUrl)
		_, err := os.Stat(path.Join("dicts", dictName))
		if err != nil {
			if os.IsNotExist(err) {
				u, err := url.Parse(dictUrl)
				if err != nil {
					log.Println(err)
					return r
				}
				if u.Scheme == "" {
					dictUrl = "http://" + r.Request.Host + dictUrl
				}
				downloadDict(dictUrl)
			}
			return r
		}

		return r
	})

	proxy.OnResponse(goproxy.ContentTypeIs("sdch")).DoFunc(func(r *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
		var origBody bytes.Buffer
		tr := bufio.NewReader(io.TeeReader(r.Body, &origBody))

		serverId, err := tr.ReadString(byte(0))
		if err != nil {
			log.Println(err)
			r.Body = ioutil.NopCloser(io.MultiReader(&origBody, r.Body))
			return r
		}
		// Chop off the last 0x00
		serverId = serverId[:len(serverId)-1]
		rawServerId, err := base64.URLEncoding.DecodeString(serverId)
		if err != nil {
			log.Println(err)
			r.Body = ioutil.NopCloser(io.MultiReader(&origBody, r.Body))
			return r
		}
		ourDict, err := hex.DecodeString(dictName)
		if err != nil {
			log.Println(err)
			r.Body = ioutil.NopCloser(io.MultiReader(&origBody, r.Body))
			return r
		}
		if bytes.Compare(rawServerId, ourDict[6:12]) != 0 {
			r.Body = ioutil.NopCloser(io.MultiReader(&origBody, r.Body))
			return r
		}

		cmd := exec.Command("vcdiff", "patch", "-dictionary", path.Join("dicts/", dictName), "-stats")
		var out bytes.Buffer
		cmd.Stdout = &out
		cmd.Stdin = tr

		var stderr bytes.Buffer
		cmd.Stderr = &stderr

		if err := cmd.Run(); err != nil {
			log.Println(err)
		}

		log.Println("[VCDIFF]", stderr.String())

		// TODO: send original content type in headers
		r.Header.Set("Content-Type", "text/html")
		r.Body = ioutil.NopCloser(&out)
		return r
	})

	proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)

	os.Mkdir("dicts", 0755)
	dir, err := os.Open("dicts")
	if err != nil {
		log.Fatal(err)
	}
	fis, err := dir.Readdir(-1)
	if err != nil {
		log.Fatal(err)
	}
	if len(fis) > 0 {
		last := fis[0]
		for _, fi := range fis[1:] {
			if fi.ModTime().After(last.ModTime()) {
				os.Remove(path.Join("dicts", last.Name()))
				last = fi
			}
		}
		dictName = last.Name()
	}

	log.Println("Let's go!")
	log.Fatal(http.ListenAndServe(":8081", proxy))
}
Exemple #4
0
func main() {
	proxy := goproxy.NewProxyHttpServer()

	db, err := sql.Open("sqlite3", "memory")
	if err != nil {
		log.Fatal(err)
	}

	if err = db.Ping(); err != nil {
		log.Fatal(err)
	}

	_, err = db.Exec(`CREATE TABLE IF NOT EXISTS chunks (
		content BLOB,
		hash BLOB UNIQUE ON CONFLICT REPLACE,
		count INTEGER
	);`)
	if err != nil {
		log.Fatal(err)
	}

	bh := &bodyHandler{
		db: db,
	}

	matchPath := regexp.MustCompile("reddit.com")
	proxy.OnResponse(
		goproxy.ContentTypeIs("text/html"),
		goproxy.ReqHostMatches(matchPath),
	).DoFunc(bh.handle)
	proxy.OnResponse(
		goproxy.ReqHostMatches(matchPath),
	).DoFunc(func(r *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
		r.Header.Set("X-Sdch-Encoding", "0")
		return r
	})
	proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)

	err = os.Mkdir(DICT_PATH, 0755)
	if err != nil && !os.IsExist(err) {
		log.Fatal(err)
	}

	err = os.Mkdir(DICT_HDR_PATH, 0755)
	if err != nil && !os.IsExist(err) {
		log.Fatal(err)
	}

	dir, err := os.Open(DICT_PATH)
	if err != nil {
		log.Fatal(err)
	}
	fis, err := dir.Readdir(-1)
	if err != nil {
		log.Fatal(err)
	}

	if len(fis) > 0 {
		current := fis[0]
		for _, fi := range fis[1:] {
			if fi.ModTime().After(current.ModTime()) {
				err := os.Remove(path.Join(DICT_PATH, fi.Name()))
				if err != nil {
					log.Fatal(err)
				}
				err = os.Remove(path.Join(DICT_HDR_PATH, fi.Name()))
				if err != nil {
					log.Fatal(err)
				}
				current = fi
			}
		}
		bh.SetDictName(path.Join(DICT_PATH, current.Name()))
		bh.SetDictHdrName(path.Join(DICT_HDR_PATH, current.Name()))
	}

	proxy.OnRequest().DoFunc(func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
		if !strings.HasPrefix(r.URL.Path, "/_dictionary") {
			return r, nil
		}

		dictQuery := strings.Replace(r.URL.Path, "/_dictionary/", "", 1)
		parts := strings.Split(dictQuery, "/")
		if len(parts) != 2 {
			log.Println("Wrong query:", dictQuery)
			resp := goproxy.NewResponse(r, "text/plain", http.StatusNotFound, http.StatusText(http.StatusNotFound))
			return nil, resp
		}

		dictName := parts[1]

		if dictName != path.Base(bh.DictName()) {
			log.Println(err)
			resp := goproxy.NewResponse(r, "text/plain", http.StatusNotFound, http.StatusText(http.StatusNotFound))
			return nil, resp
		}

		dict, modTime, err := bh.makeSdchDict()
		if err != nil {
			log.Println(err)
			resp := goproxy.NewResponse(r, "text/plain", http.StatusNotFound, http.StatusText(http.StatusNotFound))
			return nil, resp
		}

		size, err1 := dict.Seek(0, os.SEEK_END)
		_, err2 := dict.Seek(0, os.SEEK_SET)
		if err1 != nil || err2 != nil {
			log.Println(err, err2)
			resp := goproxy.NewResponse(r, "text/plain", http.StatusNotFound, http.StatusText(http.StatusNotFound))
			return nil, resp
		}

		resp := &http.Response{}
		resp.Request = r
		resp.TransferEncoding = r.TransferEncoding
		resp.Header = make(http.Header)
		resp.Header.Add("Content-Type", "application/x-sdch-dictionary")
		resp.Header.Add("Content-Length", strconv.Itoa(int(size)))
		resp.Header.Add("X-Sdch-Encode", "0")
		resp.Header.Add("Date", time.Now().Format(time.RFC1123))
		resp.Header.Add("Expires", time.Now().Add(1*time.Hour).Format(time.RFC1123))
		resp.Header.Add("Last-Modified", modTime.Format(time.RFC1123))

		resp.StatusCode = 200
		resp.ContentLength = size
		resp.Body = ioutil.NopCloser(dict)

		log.Println("Sending back dict")
		return nil, resp
	})

	log.Println("Let's go !")
	log.Fatal(http.ListenAndServe(":8080", proxy))
}