Update vendor dir and Godeps.json with new Godep

This commit is contained in:
saadali
2016-05-11 16:59:55 -07:00
parent b83af3d481
commit c708e2cc82
2053 changed files with 955 additions and 140589 deletions

View File

@@ -1,29 +0,0 @@
# Simple HTTP Proxy
`goproxy-basic` starts an HTTP proxy on :8080. It only handles explicit CONNECT
requests.
Start it in one shell:
```sh
goproxy-basic -v
```
Fetch goproxy homepage in another:
```sh
http_proxy=http://127.0.0.1:8080 wget -O - \
http://ripper234.com/p/introducing-goproxy-light-http-proxy/
```
The homepage HTML content should be displayed in the console. The proxy should
have logged the request being processed:
```sh
2015/04/09 18:19:17 [001] INFO: Got request /p/introducing-goproxy-light-http-proxy/ ripper234.com GET http://ripper234.com/p/introducing-goproxy-light-http-proxy/
2015/04/09 18:19:17 [001] INFO: Sending request GET http://ripper234.com/p/introducing-goproxy-light-http-proxy/
2015/04/09 18:19:18 [001] INFO: Received response 200 OK
2015/04/09 18:19:18 [001] INFO: Copying response to client 200 OK [200]
2015/04/09 18:19:18 [001] INFO: Copied 44333 bytes to client error=<nil>
```

View File

@@ -1,17 +0,0 @@
package main
import (
"github.com/elazarl/goproxy"
"log"
"flag"
"net/http"
)
func main() {
verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
addr := flag.String("addr", ":8080", "proxy listen address")
flag.Parse()
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = *verbose
log.Fatal(http.ListenAndServe(*addr, proxy))
}

View File

@@ -1,56 +0,0 @@
package main
import (
"bufio"
"flag"
"log"
"net"
"net/http"
"regexp"
"github.com/elazarl/goproxy"
)
func orPanic(err error) {
if err != nil {
panic(err)
}
}
func main() {
proxy := goproxy.NewProxyHttpServer()
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*baidu.com$"))).
HandleConnect(goproxy.AlwaysReject)
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*$"))).
HandleConnect(goproxy.AlwaysMitm)
// enable curl -p for all hosts on port 80
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*:80$"))).
HijackConnect(func(req *http.Request, client net.Conn, ctx *goproxy.ProxyCtx) {
defer func() {
if e := recover(); e != nil {
ctx.Logf("error connecting to remote: %v", e)
client.Write([]byte("HTTP/1.1 500 Cannot reach destination\r\n\r\n"))
}
client.Close()
}()
clientBuf := bufio.NewReadWriter(bufio.NewReader(client), bufio.NewWriter(client))
remote, err := net.Dial("tcp", req.URL.Host)
orPanic(err)
remoteBuf := bufio.NewReadWriter(bufio.NewReader(remote), bufio.NewWriter(remote))
for {
req, err := http.ReadRequest(clientBuf.Reader)
orPanic(err)
orPanic(req.Write(remoteBuf))
orPanic(remoteBuf.Flush())
resp, err := http.ReadResponse(remoteBuf.Reader, req)
orPanic(err)
orPanic(resp.Write(clientBuf.Writer))
orPanic(clientBuf.Flush())
}
})
verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
addr := flag.String("addr", ":8080", "proxy listen address")
flag.Parse()
proxy.Verbose = *verbose
log.Fatal(http.ListenAndServe(*addr, proxy))
}

View File

@@ -1,30 +0,0 @@
# Trace HTTP Requests and Responses
`goproxy-httpdump` starts an HTTP proxy on :8080. It handles explicit CONNECT
requests and traces them in a "db" directory created in the proxy working
directory. Each request type and headers are logged in a "log" file, while
their bodies are dumped in files prefixed with the request session identifier.
Additionally, the example demonstrates how to:
- Log information asynchronously (see HttpLogger)
- Allow the proxy to be stopped manually while ensuring all pending requests
have been processed (in this case, logged).
Start it in one shell:
```sh
goproxy-httpdump
```
Fetch goproxy homepage in another:
```sh
http_proxy=http://127.0.0.1:8080 wget -O - \
http://ripper234.com/p/introducing-goproxy-light-http-proxy/
```
A "db" directory should have appeared where you started the proxy, containing
two files:
- log: the request/response traces
- 1\_resp: the first response body

View File

@@ -1,285 +0,0 @@
package main
import (
"errors"
"flag"
"fmt"
"io"
"log"
"net"
"net/http"
"net/http/httputil"
"os"
"os/signal"
"path"
"sync"
"time"
"github.com/elazarl/goproxy"
"github.com/elazarl/goproxy/transport"
)
type FileStream struct {
path string
f *os.File
}
func NewFileStream(path string) *FileStream {
return &FileStream{path, nil}
}
func (fs *FileStream) Write(b []byte) (nr int, err error) {
if fs.f == nil {
fs.f, err = os.Create(fs.path)
if err != nil {
return 0, err
}
}
return fs.f.Write(b)
}
func (fs *FileStream) Close() error {
fmt.Println("Close", fs.path)
if fs.f == nil {
return errors.New("FileStream was never written into")
}
return fs.f.Close()
}
type Meta struct {
req *http.Request
resp *http.Response
err error
t time.Time
sess int64
bodyPath string
from string
}
func fprintf(nr *int64, err *error, w io.Writer, pat string, a ...interface{}) {
if *err != nil {
return
}
var n int
n, *err = fmt.Fprintf(w, pat, a...)
*nr += int64(n)
}
func write(nr *int64, err *error, w io.Writer, b []byte) {
if *err != nil {
return
}
var n int
n, *err = w.Write(b)
*nr += int64(n)
}
func (m *Meta) WriteTo(w io.Writer) (nr int64, err error) {
if m.req != nil {
fprintf(&nr, &err, w, "Type: request\r\n")
} else if m.resp != nil {
fprintf(&nr, &err, w, "Type: response\r\n")
}
fprintf(&nr, &err, w, "ReceivedAt: %v\r\n", m.t)
fprintf(&nr, &err, w, "Session: %d\r\n", m.sess)
fprintf(&nr, &err, w, "From: %v\r\n", m.from)
if m.err != nil {
// note the empty response
fprintf(&nr, &err, w, "Error: %v\r\n\r\n\r\n\r\n", m.err)
} else if m.req != nil {
fprintf(&nr, &err, w, "\r\n")
buf, err2 := httputil.DumpRequest(m.req, false)
if err2 != nil {
return nr, err2
}
write(&nr, &err, w, buf)
} else if m.resp != nil {
fprintf(&nr, &err, w, "\r\n")
buf, err2 := httputil.DumpResponse(m.resp, false)
if err2 != nil {
return nr, err2
}
write(&nr, &err, w, buf)
}
return
}
// HttpLogger is an asynchronous HTTP request/response logger. It traces
// requests and responses headers in a "log" file in logger directory and dumps
// their bodies in files prefixed with the session identifiers.
// Close it to ensure pending items are correctly logged.
type HttpLogger struct {
path string
c chan *Meta
errch chan error
}
func NewLogger(basepath string) (*HttpLogger, error) {
f, err := os.Create(path.Join(basepath, "log"))
if err != nil {
return nil, err
}
logger := &HttpLogger{basepath, make(chan *Meta), make(chan error)}
go func() {
for m := range logger.c {
if _, err := m.WriteTo(f); err != nil {
log.Println("Can't write meta", err)
}
}
logger.errch <- f.Close()
}()
return logger, nil
}
func (logger *HttpLogger) LogResp(resp *http.Response, ctx *goproxy.ProxyCtx) {
body := path.Join(logger.path, fmt.Sprintf("%d_resp", ctx.Session))
from := ""
if ctx.UserData != nil {
from = ctx.UserData.(*transport.RoundTripDetails).TCPAddr.String()
}
if resp == nil {
resp = emptyResp
} else {
resp.Body = NewTeeReadCloser(resp.Body, NewFileStream(body))
}
logger.LogMeta(&Meta{
resp: resp,
err: ctx.Error,
t: time.Now(),
sess: ctx.Session,
from: from})
}
var emptyResp = &http.Response{}
var emptyReq = &http.Request{}
func (logger *HttpLogger) LogReq(req *http.Request, ctx *goproxy.ProxyCtx) {
body := path.Join(logger.path, fmt.Sprintf("%d_req", ctx.Session))
if req == nil {
req = emptyReq
} else {
req.Body = NewTeeReadCloser(req.Body, NewFileStream(body))
}
logger.LogMeta(&Meta{
req: req,
err: ctx.Error,
t: time.Now(),
sess: ctx.Session,
from: req.RemoteAddr})
}
func (logger *HttpLogger) LogMeta(m *Meta) {
logger.c <- m
}
func (logger *HttpLogger) Close() error {
close(logger.c)
return <-logger.errch
}
// TeeReadCloser extends io.TeeReader by allowing reader and writer to be
// closed.
type TeeReadCloser struct {
r io.Reader
w io.WriteCloser
c io.Closer
}
func NewTeeReadCloser(r io.ReadCloser, w io.WriteCloser) io.ReadCloser {
return &TeeReadCloser{io.TeeReader(r, w), w, r}
}
func (t *TeeReadCloser) Read(b []byte) (int, error) {
return t.r.Read(b)
}
// Close attempts to close the reader and write. It returns an error if both
// failed to Close.
func (t *TeeReadCloser) Close() error {
err1 := t.c.Close()
err2 := t.w.Close()
if err1 != nil {
return err1
}
return err2
}
// stoppableListener serves stoppableConn and tracks their lifetime to notify
// when it is safe to terminate the application.
type stoppableListener struct {
net.Listener
sync.WaitGroup
}
type stoppableConn struct {
net.Conn
wg *sync.WaitGroup
}
func newStoppableListener(l net.Listener) *stoppableListener {
return &stoppableListener{l, sync.WaitGroup{}}
}
func (sl *stoppableListener) Accept() (net.Conn, error) {
c, err := sl.Listener.Accept()
if err != nil {
return c, err
}
sl.Add(1)
return &stoppableConn{c, &sl.WaitGroup}, nil
}
func (sc *stoppableConn) Close() error {
sc.wg.Done()
return sc.Conn.Close()
}
func main() {
verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
addr := flag.String("l", ":8080", "on which address should the proxy listen")
flag.Parse()
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = *verbose
if err := os.MkdirAll("db", 0755); err != nil {
log.Fatal("Can't create dir", err)
}
logger, err := NewLogger("db")
if err != nil {
log.Fatal("can't open log file", err)
}
tr := transport.Transport{Proxy: transport.ProxyFromEnvironment}
// For every incoming request, override the RoundTripper to extract
// connection information. Store it is session context log it after
// handling the response.
proxy.OnRequest().DoFunc(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
ctx.RoundTripper = goproxy.RoundTripperFunc(func(req *http.Request, ctx *goproxy.ProxyCtx) (resp *http.Response, err error) {
ctx.UserData, resp, err = tr.DetailedRoundTrip(req)
return
})
logger.LogReq(req, ctx)
return req, nil
})
proxy.OnResponse().DoFunc(func(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
logger.LogResp(resp, ctx)
return resp
})
l, err := net.Listen("tcp", *addr)
if err != nil {
log.Fatal("listen:", err)
}
sl := newStoppableListener(l)
ch := make(chan os.Signal)
signal.Notify(ch, os.Interrupt)
go func() {
<-ch
log.Println("Got SIGINT exiting")
sl.Add(1)
sl.Close()
logger.Close()
sl.Done()
}()
log.Println("Starting Proxy")
http.Serve(sl, proxy)
sl.Wait()
log.Println("All connections closed - exit")
}

View File

@@ -1,31 +0,0 @@
# Content Analysis
`goproxy-jquery-version` starts an HTTP proxy on :8080. It checks HTML
responses, looks for scripts referencing jQuery library and emits warnings if
different versions of the library are being used for a given host.
Start it in one shell:
```sh
goproxy-jquery-version
```
Fetch goproxy homepage in another:
```sh
http_proxy=http://127.0.0.1:8080 wget -O - \
http://ripper234.com/p/introducing-goproxy-light-http-proxy/
```
Goproxy homepage uses jQuery and a mix of plugins. First the proxy reports the
first use of jQuery it detects for the domain. Then, because the regular
expression matching the jQuery sources is imprecise, it reports a mismatch with
a plugin reference:
```sh
2015/04/11 11:23:02 [001] WARN: ripper234.com uses //ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js
2015/04/11 11:23:02 [001] WARN: In http://ripper234.com/p/introducing-goproxy-light-http-proxy/, \
Contradicting jqueries //ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js \
http://ripper234.wpengine.netdna-cdn.com/wp-content/plugins/wp-ajax-edit-comments/js/jquery.colorbox.min.js?ver=5.0.36
```

View File

@@ -1,8 +0,0 @@
<!doctype html>
<html>
<head>
<script src="jquery.1.4.js"></script>
</head>
<body/>
</html>

View File

@@ -1,8 +0,0 @@
<!doctype html>
<html>
<head>
<script src="jquery.1.3.js"></script>
</head>
<body/>
</html>

View File

@@ -1,233 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>jQuery: The Write Less, Do More, JavaScript Library</title>
<link rel="stylesheet" href="http://static.jquery.com/files/rocker/css/reset.css" type="text/css" />
<link rel="stylesheet" href="http://static.jquery.com/files/rocker/css/screen.css" type="text/css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>!window.jQuery && document.write('<script src="http://code.jquery.com/jquery-1.4.2.min.js"><\/script>');</script>
<script src="http://static.jquery.com/files/rocker/scripts/custom.js"></script>
<link rel="alternate" type="application/rss+xml" title="jQuery Blog" href="http://jquery.com/blog/feed/" />
<link rel="shortcut icon" href="http://static.jquery.com/favicon.ico" type="image/x-icon"/>
</head>
<body>
<div id="jq-siteContain">
<div id="jq-header">
<a id="jq-siteLogo" href="http://jquery.com" title="jQuery Home"><img src="http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif" width="215" height="53" alt="jQuery: Write Less, Do More." /></a>
<div id="jq-primaryNavigation">
<ul>
<li class="jq-jquery jq-current"><a href="http://jquery.com/" title="jQuery Home">jQuery</a></li>
<li class="jq-ui"><a href="http://jqueryui.com/" title="jQuery UI">UI</a></li>
<li class="jq-mobile"><a href="http://jquerymobile.com/" title="jQuery Mobile">Mobile</a></li>
<li class="jq-plugins"><a href="http://plugins.jquery.com/" title="jQuery Plugins">Plugins</a></li>
<li class="jq-meetup"><a href="http://meetups.jquery.com/" title="jQuery Meetups">Meetups</a></li>
<li class="jq-forum"><a href="http://forum.jquery.com/" title="jQuery Forum">Forum</a></li>
<li class="jq-blog"><a href="http://blog.jquery.com/" title="jQuery Blog">Blog</a></li>
<li class="jq-about"><a href="http://jquery.org/about" title="About jQuery">About</a></li>
<li class="jq-donate"><a href="http://jquery.org/donate" title="Donate to jQuery">Donate</a></li>
</ul>
</div><!-- /#primaryNavigation -->
<div id="jq-secondaryNavigation">
<ul>
<li class="jq-download jq-first"><a href="http://docs.jquery.com/Downloading_jQuery">Download</a></li>
<li class="jq-documentation"><a href="http://docs.jquery.com">Documentation</a></li>
<li class="jq-tutorials"><a href="http://docs.jquery.com/Tutorials">Tutorials</a></li>
<li class="jq-bugTracker"><a href="http://dev.jquery.com/">Bug Tracker</a></li>
<li class="jq-discussion jq-last"><a href="http://docs.jquery.com/Discussion">Discussion</a></li>
</ul>
</div><!-- /#secondaryNavigation -->
</div><!-- /#header -->
<div id="jq-content" class="jq-clearfix">
<div id="jq-intro" class="jq-clearfix">
<h2><span class="jq-jquery"><span>jQuery</span></span> is a new kind of JavaScript Library.</h2>
<p>jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. <strong>jQuery is designed to change the way that you write JavaScript.</strong></p>
<ul class="jq-checkpoints jq-clearfix">
<li><a href="http://docs.jquery.com/Tutorials" title="Lightweight Footprint" class="jq-thickbox">Lightweight Footprint</a>
<div class="jq-checkpointSubhead">
<p>About 31KB in size <em>(Minified and Gzipped)</em></p>
</div>
</li>
<li><a href="http://docs.jquery.com/Tutorials" title="CSS3 Compliant" class="jq-thickbox">CSS3 Compliant</a>
<div class="jq-checkpointSubhead">
<p>Supports CSS 1-3 selectors and more!</p>
</div>
</li>
<li><a href="http://docs.jquery.com/Tutorials" title="Cross-browser" class="jq-thickbox">Cross-browser</a>
<div class="jq-checkpointSubhead">
<p>IE 6.0+, FF 3.6+, Safari 5.0+, Opera, Chrome</p>
</div>
</li>
</ul>
</div><!-- /#intro -->
<div id="jq-download">
<h2>Grab the latest version!</h2>
<form action="" method="get">
<fieldset>
<legend>Choose your compression level:</legend>
<div id="jq-compression" class="jq-clearfix">
<input type="radio" name="name" value="http://code.jquery.com/jquery-1.7.2.min.js" id="jq-production" checked="checked" />
<a class="jq-radioToggle name jq-checked" href="http://code.jquery.com/jquery-1.7.2.min.js">jquery-1.7.2.min.js</a>
<label for="jq-production">Production <em>(<strong>32KB</strong>, Minified and Gzipped)</em></label>
<input type="radio" name="name" value="http://code.jquery.com/jquery-1.7.2.js" id="jq-development" />
<a class="jq-radioToggle name" href="http://code.jquery.com/jquery-1.7.2.js">jquery-1.7.2.js</a>
<label for="jq-development">Development <em>(<strong>247KB</strong>, Uncompressed Code)</em></label>
</div>
<button type="submit" name="downloadBtn" id="jq-downloadBtn"><span>Download</span></button>
<p class="jq-version"><strong>Current Release:</strong> v1.7.2</p>
</fieldset>
</form>
<script>
jQuery("#jq-download form").submit(function(){
window.location = jQuery(this).find("input:checked").val();
return false;
});
</script>
</div><!-- /#download -->
<div id="jq-whosUsing">
<h2 class="jq-whosUsing">Who's using jQuery?</h2>
<ul class="jq-whosUsing">
<li><a href="http://www.google.com" class="jq-google" title="Google">Google</a></li>
<li><a href="http://www.dell.com" class="jq-dell" title="Dell">Dell</a></li>
<li><a href="http://www.bankofamerica.com" class="jq-boa" title="Bank of America">Bank of America</a></li>
<li><a href="http://www.mlb.com" class="jq-mlb" title="Major League Baseball">Major League Baseball</a></li>
<li><a href="http://www.digg.com" class="jq-digg" title="Digg">Digg</a></li>
<li><a href="http://www.nbc.com" class="jq-nbc" title="NBC">NBC</a></li>
<li><a href="http://www.cbs.com" class="jq-cbs" title="CBS News">CBS News</a></li>
<li><a href="http://www.netflix.com" class="jq-netflix" title="Netflix">Netflix</a></li>
<li><a href="http://www.technorati.com" class="jq-technorati" title="Technorati">Technorati</a></li>
<li><a href="http://www.mozilla.org" class="jq-mozilla" title="Mozilla">Mozilla</a></li>
<li><a href="http://www.wordpress.org" class="jq-wordpress" title="Wordpress">Wordpress</a></li>
<li><a href="http://www.drupal.org" class="jq-drupal" title="Drupal">Drupal</a></li>
</ul>
</div><!-- /#jq-whosUsing -->
<div id="jq-learnjQuery" class="jq-clearfix">
<div id="jq-learnNow">
<h2>Learn <span class="jq-jquery"><span>jQuery</span></span> Now!</h2>
<p>What does jQuery code look like? Here's the quick and dirty:</p>
<div class="jq-codeDemo jq-clearfix">
<pre><code>$("p.neat").addClass("ohmy").show("slow");</code></pre>
<a href="http://docs.jquery.com/Tutorials" class="jq-runCode">Run Code</a>
<p class="neat"><strong>Congratulations!</strong> You just ran a snippet of jQuery code. Wasn't that easy? There's lots of example code throughout the <strong><a href="http://docs.jquery.com/">documentation</a></strong> on this site. Be sure to give all the code a test run to see what happens.</p>
</div>
</div><!-- /#learnNow -->
<div id="jq-resources" class="clearfix">
<h2>jQuery Resources</h2>
<div class="jq-gettingStarted">
<h3>Getting Started With jQuery</h3>
<ul>
<li><a href="http://docs.jquery.com/How_jQuery_Works">How jQuery Works</a></li>
<li><a href="http://docs.jquery.com/Tutorials">Tutorials</a></li>
<li><a href="http://docs.jquery.com/Using_jQuery_with_Other_Libraries">Using jQuery with other libraries</a></li>
<li><a href="http://docs.jquery.com/">jQuery Documentation</a></li>
</ul>
</div>
<div class="jq-devResources">
<h3>Developer Resources</h3>
<ul>
<li><a href="http://docs.jquery.com/Discussion">Mailing List</a></li>
<li><a href="http://docs.jquery.com/Downloading_jQuery">Source code / Git</a></li>
<li><a href="http://docs.jquery.com/Plugins/Authoring">Plugin Authoring</a></li>
<li><a href="http://dev.jquery.com/newticket/">Submit a New Bug Report</a></li>
</ul>
</div>
</div><!-- /#resources -->
</div><!-- /#learnjQuery -->
<div id="jq-books" style="width:auto; float: none">
<h2>Books About jQuery</h2>
<ul>
<li class="jq-clearfix" style="width:270px;float:left;clear:none;">
<a href="http://link.packtpub.com/S3Fr9Q" class="jq-bookImg"><img src="http://learningjquery.kswedberg.netdna-cdn.com/wp-content/themes/ljq/images/ljq3rded.jpg" alt="Learning jQuery Third Edition" width="55" height="70" /></a>
<h3><a href="http://link.packtpub.com/S3Fr9Q">Learning jQuery Third Edition</a></h3>
<div class="jq-author">Karl Swedberg and <br />Jonathan Chaffer</div>
<a href="http://link.packtpub.com/S3Fr9Q" class="jq-buyNow">Buy Now</a>
</li>
<li class="jq-clearfix" style="width:270px;float:left;clear:none;">
<a href="http://www.packtpub.com/jquery-1-4-animation-techniques-beginners-guide/book/mid/1803111nkj15" class="jq-bookImg"><img src="http://static.jquery.com/books/jquery-animation-beginners-guide.jpg" alt="jQuery 1.4 Animation Techniques: Beginners Guide" width="55" height="70" /></a>
<h3><a href="http://www.packtpub.com/jquery-1-4-animation-techniques-beginners-guide/book/mid/1803111nkj15">jQuery 1.4 Animation Techniques: Beginners Guide</a></h3>
<div class="jq-author">Dan Wellman</div>
<a href="http://www.packtpub.com/jquery-1-4-animation-techniques-beginners-guide/book/mid/1803111nkj15" class="jq-buyNow">Buy Now</a>
</li>
<li class="jq-clearfix" style="width:270px;float:left;clear:none;">
<a href="http://www.packtpub.com/jquery-plugin-development-beginners-guide/book/mid/1911104odmdz" class="jq-bookImg"><img src="http://static.jquery.com/books/jquery-plugin-developers-guide_thumb.jpg" alt="jQuery Plugin Development Beginner's Guide" width="55" height="70" /></a>
<h3><a href="http://www.packtpub.com/jquery-plugin-development-beginners-guide/book/mid/1911104odmdz">jQuery Plugin Development Beginner's Guide</a></h3>
<div class="jq-author">Guilio Bai</div>
<a href="http://www.packtpub.com/jquery-plugin-development-beginners-guide/book/mid/1911104odmdz" class="jq-buyNow">Buy Now</a>
</li>
<li class="jq-clearfix" style="width:270px;float:left;clear:left;">
<a href="http://www.manning.com/affiliate/idevaffiliate.php?id=648_176" class="jq-bookImg"><img src="http://static.jquery.com/books/jquery-in-action-2ed_thumb.jpg" alt="jQuery in Action" width="55" height="70" /></a>
<h3><a href="http://www.manning.com/affiliate/idevaffiliate.php?id=648_176">jQuery in Action</a></h3>
<div class="jq-author">Bear Bibeault
<br />and Yehuda Katz</div>
<a href="http://www.manning.com/affiliate/idevaffiliate.php?id=648_176" class="jq-buyNow">Buy Now</a>
</li>
<li class="jq-clearfix" style="width:270px;float:left;clear:none;">
<a class="jq-bookImg" href="http://jqueryenlightenment.com/"><img src="http://static.jquery.com/books/jquery-enlightenment_thumb.jpg" alt="jQuery Enlightenment" width="55" height="70" /></a>
<h3><a href="http://jqueryenlightenment.com/">jQuery Enlightenment</a></h3>
<div class="jq-author">Cody Lindley</div>
<a href="http://jqueryenlightenment.com/" class="jq-buyNow">Buy Now</a>
</li>
</ul>
</div><!-- /#news -->
</div><!-- /#content -->
<div id="jq-footer" class="jq-clearfix">
<div id="jq-credits">
<p id="jq-copyright">&copy; 2010 <a href="http://jquery.org/">The jQuery Project</a></p>
<p id="jq-hosting">Sponsored by <a href="http://mediatemple.net" class="jq-mediaTemple">Media Temple</a> and <a href="http://jquery.org/sponsors">others</a>.</p>
</div>
<div id="jq-footerNavigation">
<ul>
<li class="jq-download jq-first"><a href="http://docs.jquery.com/Downloading_jQuery">Download</a></li>
<li class="jq-documentation"><a href="http://docs.jquery.com">Documentation</a></li>
<li class="jq-tutorials"><a href="http://docs.jquery.com/Tutorials">Tutorials</a></li>
<li class="jq-bugTracker"><a href="http://dev.jquery.com/">Bug Tracker</a></li>
<li class="jq-discussion jq-last"><a href="http://docs.jquery.com/Discussion">Discussion</a></li>
</ul>
</div><!-- /#secondaryNavigation -->
</div><!-- /#footer -->
</div><!-- /#siteContain -->
<script src="http://static.jquery.com/donate/donate.js" type="text/javascript"></script>
<script type="text/javascript">
var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-1076265-1']); _gaq.push(['_trackPageview']); _gaq.push(['_setDomainName', '.jquery.com']);
(function() {var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);})();
</script>
</body>
</html>

View File

@@ -1,64 +0,0 @@
package main
import (
"github.com/elazarl/goproxy"
"github.com/elazarl/goproxy/ext/html"
"log"
"net/http"
"regexp"
)
var (
// who said we can't parse HTML with regexp?
scriptMatcher = regexp.MustCompile(`(?i:<script\s+)`)
srcAttrMatcher = regexp.MustCompile(`^(?i:[^>]*\ssrc=["']([^"']*)["'])`)
)
// findScripts returns all sources of HTML script tags found in input text.
func findScriptSrc(html string) []string {
srcs := make([]string, 0)
matches := scriptMatcher.FindAllStringIndex(html, -1)
for _, match := range matches {
// -1 to capture the whitespace at the end of the script tag
srcMatch := srcAttrMatcher.FindStringSubmatch(html[match[1]-1:])
if srcMatch != nil {
srcs = append(srcs, srcMatch[1])
}
}
return srcs
}
// NewJQueryVersionProxy creates a proxy checking responses HTML content, looks
// for scripts referencing jQuery library and emits warnings if different
// versions of the library are being used for a given host.
func NewJqueryVersionProxy() *goproxy.ProxyHttpServer {
proxy := goproxy.NewProxyHttpServer()
m := make(map[string]string)
jqueryMatcher := regexp.MustCompile(`(?i:jquery\.)`)
proxy.OnResponse(goproxy_html.IsHtml).Do(goproxy_html.HandleString(
func(s string, ctx *goproxy.ProxyCtx) string {
for _, src := range findScriptSrc(s) {
if !jqueryMatcher.MatchString(src) {
continue
}
prev, ok := m[ctx.Req.Host]
if ok {
if prev != src {
ctx.Warnf("In %v, Contradicting jqueries %v %v",
ctx.Req.URL, prev, src)
break
}
} else {
ctx.Warnf("%s uses jquery %s", ctx.Req.Host, src)
m[ctx.Req.Host] = src
}
}
return s
}))
return proxy
}
func main() {
proxy := NewJqueryVersionProxy()
log.Fatal(http.ListenAndServe(":8080", proxy))
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +0,0 @@
# Request Filtering
`goproxy-no-reddit-at-work` starts an HTTP proxy on :8080. It denies requests
to "www.reddit.com" made between 8am to 5pm inclusive, local time.
Start it in one shell:
```sh
$ goproxy-no-reddit-at-work
```
Fetch reddit in another:
```sh
$ http_proxy=http://127.0.0.1:8080 wget -O - http://www.reddit.com
--2015-04-11 16:59:01-- http://www.reddit.com/
Connecting to 127.0.0.1:8080... connected.
Proxy request sent, awaiting response... 403 Forbidden
2015-04-11 16:59:01 ERROR 403: Forbidden.
```

View File

@@ -1,25 +0,0 @@
package main
import (
"github.com/elazarl/goproxy"
"log"
"net/http"
"time"
)
func main() {
proxy := goproxy.NewProxyHttpServer()
proxy.OnRequest(goproxy.DstHostIs("www.reddit.com")).DoFunc(
func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
h, _, _ := time.Now().Clock()
if h >= 8 && h <= 17 {
return r, goproxy.NewResponse(r,
goproxy.ContentTypeText, http.StatusForbidden,
"Don't waste your time!")
} else {
ctx.Warnf("clock: %d, you can waste your time...", h)
}
return r, nil
})
log.Fatalln(http.ListenAndServe(":8080", proxy))
}

View File

@@ -1,25 +0,0 @@
package main
import (
"github.com/elazarl/goproxy"
"log"
"flag"
"net"
"net/http"
)
func main() {
verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
addr := flag.String("addr", ":8080", "proxy listen address")
flag.Parse()
proxy := goproxy.NewProxyHttpServer()
proxy.Tr.Dial = func(network, addr string) (c net.Conn, err error) {
c, err = net.Dial(network, addr)
if c, ok := c.(*net.TCPConn); err != nil && ok {
c.SetKeepAlive(true)
}
return
}
proxy.Verbose = *verbose
log.Fatal(http.ListenAndServe(*addr, proxy))
}

View File

@@ -1,24 +0,0 @@
package main
import (
"github.com/elazarl/goproxy"
"log"
"flag"
"net/http"
)
func main() {
verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
addr := flag.String("addr", ":8080", "proxy listen address")
flag.Parse()
proxy := goproxy.NewProxyHttpServer()
proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)
proxy.OnRequest().DoFunc(func (req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
if req.URL.Scheme == "https" {
req.URL.Scheme = "http"
}
return req, nil
})
proxy.Verbose = *verbose
log.Fatal(http.ListenAndServe(*addr, proxy))
}

View File

@@ -1,43 +0,0 @@
# Gather Browsing Statistics
`goproxy-stats` starts an HTTP proxy on :8080, counts the bytes received for
web resources and prints the cumulative sum per URL every 20 seconds.
Start it in one shell:
```sh
goproxy-stats
```
Fetch goproxy homepage in another:
```sh
mkdir tmp
cd tmp
http_proxy=http://127.0.0.1:8080 wget -r -l 1 -H \
http://ripper234.com/p/introducing-goproxy-light-http-proxy/
```
Stop it after a moment. `goproxy-stats` should eventually print:
```sh
listening on :8080
statistics
http://www.telerik.com/fiddler -> 84335
http://msmvps.com/robots.txt -> 157
http://eli.thegreenplace.net/robots.txt -> 294
http://www.phdcomics.com/robots.txt -> 211
http://resharper.blogspot.com/robots.txt -> 221
http://idanz.blogli.co.il/robots.txt -> 271
http://ripper234.com/p/introducing-goproxy-light-http-proxy/ -> 44407
http://live.gnome.org/robots.txt -> 298
http://ponetium.wordpress.com/robots.txt -> 178
http://pilaheleg.blogli.co.il/robots.txt -> 321
http://pilaheleg.wordpress.com/robots.txt -> 178
http://blogli.co.il/ -> 9165
http://nimrod-code.org/robots.txt -> 289
http://www.joelonsoftware.com/robots.txt -> 1245
http://top-performance.blogspot.com/robots.txt -> 227
http://ooc-lang.org/robots.txt -> 345
http://blogs.jetbrains.com/robots.txt -> 293
```

View File

@@ -1,66 +0,0 @@
package main
import (
"fmt"
"github.com/elazarl/goproxy"
"github.com/elazarl/goproxy/ext/html"
"io"
"log"
. "net/http"
"time"
)
type Count struct {
Id string
Count int64
}
type CountReadCloser struct {
Id string
R io.ReadCloser
ch chan<- Count
nr int64
}
func (c *CountReadCloser) Read(b []byte) (n int, err error) {
n, err = c.R.Read(b)
c.nr += int64(n)
return
}
func (c CountReadCloser) Close() error {
c.ch <- Count{c.Id, c.nr}
return c.R.Close()
}
func main() {
proxy := goproxy.NewProxyHttpServer()
timer := make(chan bool)
ch := make(chan Count, 10)
go func() {
for {
time.Sleep(20 * time.Second)
timer <- true
}
}()
go func() {
m := make(map[string]int64)
for {
select {
case c := <-ch:
m[c.Id] = m[c.Id] + c.Count
case <-timer:
fmt.Printf("statistics\n")
for k, v := range m {
fmt.Printf("%s -> %d\n", k, v)
}
}
}
}()
// IsWebRelatedText filters on html/javascript/css resources
proxy.OnResponse(goproxy_html.IsWebRelatedText).DoFunc(func(resp *Response, ctx *goproxy.ProxyCtx) *Response {
resp.Body = &CountReadCloser{ctx.Req.URL.String(), resp.Body, ch, 0}
return resp
})
fmt.Printf("listening on :8080\n")
log.Fatal(ListenAndServe(":8080", proxy))
}

View File

@@ -1,17 +0,0 @@
# Transparent Proxy
This transparent example in goproxy is meant to show how to transparenty proxy and hijack all http and https connections while doing a man-in-the-middle to the TLS session. It requires that goproxy sees all the packets traversing out to the internet. Linux iptables rules deal with changing the source/destination IPs to act transparently, but you do need to setup your network configuration so that goproxy is a mandatory stop on the outgoing route. Primarily you can do this by placing the proxy inline. goproxy does not have any WCCP support itself; patches welcome.
## Why not explicit?
Transparent proxies are more difficult to maintain and setup from a server side, but they require no configuration on the client(s) which could be in unmanaged systems or systems that don't support a proxy configuration. See the [eavesdropper example](https://github.com/elazarl/goproxy/blob/master/examples/goproxy-eavesdropper/main.go) if you want to see an explicit proxy example.
## Potential Issues
Support for very old clients using HTTPS will fail. Clients need to send the SNI value in the TLS ClientHello which most modern clients do these days, but old clients will break.
If you're routing table allows for it, an explicit http request to goproxy will cause it to fail in an endless loop since it will try to request resources from itself repeatedly. This could be solved in the goproxy code by looking up the hostnames, but it adds a delay that is much easier/faster to handle on the routing side.
## Routing Rules
Example routing rules are included in [proxy.sh](https://github.com/elazarl/goproxy/blob/master/examples/goproxy-transparent/proxy.sh) but are best when setup using your distribution's configuration.

View File

@@ -1,29 +0,0 @@
#!/bin/sh
# goproxy IP
GOPROXY_SERVER="10.10.10.1"
# goproxy port
GOPROXY_PORT="3129"
GOPROXY_PORT_TLS="3128"
# DO NOT MODIFY BELOW
# Load IPTABLES modules for NAT and IP conntrack support
modprobe ip_conntrack
modprobe ip_conntrack_ftp
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter
# Clean old firewall
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
# Write new rules
iptables -t nat -A PREROUTING -s $GOPROXY_SERVER -p tcp --dport $GOPROXY_PORT -j ACCEPT
iptables -t nat -A PREROUTING -s $GOPROXY_SERVER -p tcp --dport $GOPROXY_PORT_TLS -j ACCEPT
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination $GOPROXY_SERVER:$GOPROXY_PORT
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination $GOPROXY_SERVER:$GOPROXY_PORT_TLS
# The following line supports using goproxy as an explicit proxy in addition
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination $GOPROXY_SERVER:$GOPROXY_PORT
iptables -t nat -A POSTROUTING -j MASQUERADE
iptables -t mangle -A PREROUTING -p tcp --dport $GOPROXY_PORT -j DROP
iptables -t mangle -A PREROUTING -p tcp --dport $GOPROXY_PORT_TLS -j DROP

View File

@@ -1,148 +0,0 @@
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"log"
"net"
"net/http"
"net/url"
"regexp"
"github.com/elazarl/goproxy"
"github.com/inconshreveable/go-vhost"
)
func orPanic(err error) {
if err != nil {
panic(err)
}
}
func main() {
verbose := flag.Bool("v", true, "should every proxy request be logged to stdout")
http_addr := flag.String("httpaddr", ":3129", "proxy http listen address")
https_addr := flag.String("httpsaddr", ":3128", "proxy https listen address")
flag.Parse()
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = *verbose
if proxy.Verbose {
log.Printf("Server starting up! - configured to listen on http interface %s and https interface %s", *http_addr, *https_addr)
}
proxy.NonproxyHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if req.Host == "" {
fmt.Fprintln(w, "Cannot handle requests without Host header, e.g., HTTP 1.0")
return
}
req.URL.Scheme = "http"
req.URL.Host = req.Host
proxy.ServeHTTP(w, req)
})
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*$"))).
HandleConnect(goproxy.AlwaysMitm)
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*:80$"))).
HijackConnect(func(req *http.Request, client net.Conn, ctx *goproxy.ProxyCtx) {
defer func() {
if e := recover(); e != nil {
ctx.Logf("error connecting to remote: %v", e)
client.Write([]byte("HTTP/1.1 500 Cannot reach destination\r\n\r\n"))
}
client.Close()
}()
clientBuf := bufio.NewReadWriter(bufio.NewReader(client), bufio.NewWriter(client))
remote, err := connectDial(proxy, "tcp", req.URL.Host)
orPanic(err)
remoteBuf := bufio.NewReadWriter(bufio.NewReader(remote), bufio.NewWriter(remote))
for {
req, err := http.ReadRequest(clientBuf.Reader)
orPanic(err)
orPanic(req.Write(remoteBuf))
orPanic(remoteBuf.Flush())
resp, err := http.ReadResponse(remoteBuf.Reader, req)
orPanic(err)
orPanic(resp.Write(clientBuf.Writer))
orPanic(clientBuf.Flush())
}
})
go func() {
log.Fatalln(http.ListenAndServe(*http_addr, proxy))
}()
// listen to the TLS ClientHello but make it a CONNECT request instead
ln, err := net.Listen("tcp", *https_addr)
if err != nil {
log.Fatalf("Error listening for https connections - %v", err)
}
for {
c, err := ln.Accept()
if err != nil {
log.Printf("Error accepting new connection - %v", err)
continue
}
go func(c net.Conn) {
tlsConn, err := vhost.TLS(c)
if err != nil {
log.Printf("Error accepting new connection - %v", err)
}
if tlsConn.Host() == "" {
log.Printf("Cannot support non-SNI enabled clients")
return
}
connectReq := &http.Request{
Method: "CONNECT",
URL: &url.URL{
Opaque: tlsConn.Host(),
Host: net.JoinHostPort(tlsConn.Host(), "443"),
},
Host: tlsConn.Host(),
Header: make(http.Header),
}
resp := dumbResponseWriter{tlsConn}
proxy.ServeHTTP(resp, connectReq)
}(c)
}
}
// copied/converted from https.go
func dial(proxy *goproxy.ProxyHttpServer, network, addr string) (c net.Conn, err error) {
if proxy.Tr.Dial != nil {
return proxy.Tr.Dial(network, addr)
}
return net.Dial(network, addr)
}
// copied/converted from https.go
func connectDial(proxy *goproxy.ProxyHttpServer, network, addr string) (c net.Conn, err error) {
if proxy.ConnectDial == nil {
return dial(proxy, network, addr)
}
return proxy.ConnectDial(network, addr)
}
type dumbResponseWriter struct {
net.Conn
}
func (dumb dumbResponseWriter) Header() http.Header {
panic("Header() should not be called on this ResponseWriter")
}
func (dumb dumbResponseWriter) Write(buf []byte) (int, error) {
if bytes.Equal(buf, []byte("HTTP/1.0 200 OK\r\n\r\n")) {
return len(buf), nil // throw away the HTTP OK response from the faux CONNECT request
}
return dumb.Conn.Write(buf)
}
func (dumb dumbResponseWriter) WriteHeader(code int) {
panic("WriteHeader() should not be called on this ResponseWriter")
}
func (dumb dumbResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
return dumb, bufio.NewReadWriter(bufio.NewReader(dumb), bufio.NewWriter(dumb)), nil
}

View File

@@ -1,26 +0,0 @@
package main
import (
"github.com/elazarl/goproxy"
"github.com/elazarl/goproxy/ext/image"
"image"
"log"
"net/http"
)
func main() {
proxy := goproxy.NewProxyHttpServer()
proxy.OnResponse().Do(goproxy_image.HandleImage(func(img image.Image, ctx *goproxy.ProxyCtx) image.Image {
dx, dy := img.Bounds().Dx(), img.Bounds().Dy()
nimg := image.NewRGBA(img.Bounds())
for i := 0; i < dx; i++ {
for j := 0; j <= dy; j++ {
nimg.Set(i, j, img.At(i, dy-j-1))
}
}
return nimg
}))
proxy.Verbose = true
log.Fatal(http.ListenAndServe(":8080", proxy))
}

View File

@@ -1,91 +0,0 @@
// This example would minify standalone Javascript files (identified by their content type)
// using the command line utility YUI compressor http://yui.github.io/yuicompressor/
// Example usage:
//
// ./yui -java /usr/local/bin/java -yuicompressor ~/Downloads/yuicompressor-2.4.8.jar
// $ curl -vx localhost:8080 http://golang.org/lib/godoc/godocs.js
// (function(){function g(){var u=$("#search");if(u.length===0){return}function t(){if(....
// $ curl http://golang.org/lib/godoc/godocs.js | head -n 3
// // Copyright 2012 The Go Authors. All rights reserved.
// // Use of this source code is governed by a BSD-style
// // license that can be found in the LICENSE file.
package main
import (
"flag"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"path"
"strings"
"github.com/elazarl/goproxy"
)
func main() {
verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
addr := flag.String("addr", ":8080", "proxy listen address")
java := flag.String("javapath", "java", "where the Java executable is located")
yuicompressor := flag.String("yuicompressor", "", "where the yuicompressor is located, assumed to be in CWD")
yuicompressordir := flag.String("yuicompressordir", ".", "a folder to search yuicompressor in, will be ignored if yuicompressor is set")
flag.Parse()
if *yuicompressor == "" {
files, err := ioutil.ReadDir(*yuicompressordir)
if err != nil {
log.Fatal("Cannot find yuicompressor jar")
}
for _, file := range files {
if strings.HasPrefix(file.Name(), "yuicompressor") && strings.HasSuffix(file.Name(), ".jar") {
c := path.Join(*yuicompressordir, file.Name())
yuicompressor = &c
break
}
}
}
if *yuicompressor == "" {
log.Fatal("Can't find yuicompressor jar, searched yuicompressor*.jar in dir ", *yuicompressordir)
}
if _, err := os.Stat(*yuicompressor); os.IsNotExist(err) {
log.Fatal("Can't find yuicompressor jar specified ", *yuicompressor)
}
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = *verbose
proxy.OnResponse().DoFunc(func(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
contentType := resp.Header.Get("Content-Type")
if contentType == "application/javascript" || contentType == "application/x-javascript" {
// in real code, response should be streamed as well
var err error
cmd := exec.Command(*java, "-jar", *yuicompressor, "--type", "js")
cmd.Stdin = resp.Body
resp.Body, err = cmd.StdoutPipe()
if err != nil {
ctx.Warnf("Cannot minify content in %v: %v", ctx.Req.URL, err)
return goproxy.TextResponse(ctx.Req, "Error getting stdout pipe")
}
stderr, err := cmd.StderrPipe()
if err != nil {
ctx.Logf("Error obtaining stderr from yuicompress: %s", err)
return goproxy.TextResponse(ctx.Req, "Error getting stderr pipe")
}
if err := cmd.Start(); err != nil {
ctx.Warnf("Cannot minify content in %v: %v", ctx.Req.URL, err)
}
go func() {
defer stderr.Close()
const kb = 1024
msg, err := ioutil.ReadAll(&io.LimitedReader{stderr, 50 * kb})
if len(msg) != 0 {
ctx.Logf("Error executing yuicompress: %s", string(msg))
}
if err != nil {
ctx.Logf("Error reading stderr from yuicompress: %s", string(msg))
}
}()
}
return resp
})
log.Fatal(http.ListenAndServe(*addr, proxy))
}

View File

@@ -1,76 +0,0 @@
package auth
import (
"bytes"
"encoding/base64"
"io/ioutil"
"net/http"
"strings"
"github.com/elazarl/goproxy"
)
var unauthorizedMsg = []byte("407 Proxy Authentication Required")
func BasicUnauthorized(req *http.Request, realm string) *http.Response {
// TODO(elazar): verify realm is well formed
return &http.Response{
StatusCode: 407,
ProtoMajor: 1,
ProtoMinor: 1,
Request: req,
Header: http.Header{"Proxy-Authenticate": []string{"Basic realm=" + realm}},
Body: ioutil.NopCloser(bytes.NewBuffer(unauthorizedMsg)),
ContentLength: int64(len(unauthorizedMsg)),
}
}
var proxyAuthorizatonHeader = "Proxy-Authorization"
func auth(req *http.Request, f func(user, passwd string) bool) bool {
authheader := strings.SplitN(req.Header.Get(proxyAuthorizatonHeader), " ", 2)
req.Header.Del(proxyAuthorizatonHeader)
if len(authheader) != 2 || authheader[0] != "Basic" {
return false
}
userpassraw, err := base64.StdEncoding.DecodeString(authheader[1])
if err != nil {
return false
}
userpass := strings.SplitN(string(userpassraw), ":", 2)
if len(userpass) != 2 {
return false
}
return f(userpass[0], userpass[1])
}
// Basic returns a basic HTTP authentication handler for requests
//
// You probably want to use auth.ProxyBasic(proxy) to enable authentication for all proxy activities
func Basic(realm string, f func(user, passwd string) bool) goproxy.ReqHandler {
return goproxy.FuncReqHandler(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
if !auth(req, f) {
return nil, BasicUnauthorized(req, realm)
}
return req, nil
})
}
// BasicConnect returns a basic HTTP authentication handler for CONNECT requests
//
// You probably want to use auth.ProxyBasic(proxy) to enable authentication for all proxy activities
func BasicConnect(realm string, f func(user, passwd string) bool) goproxy.HttpsHandler {
return goproxy.FuncHttpsHandler(func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
if !auth(ctx.Req, f) {
ctx.Resp = BasicUnauthorized(ctx.Req, realm)
return goproxy.RejectConnect, host
}
return goproxy.OkConnect, host
})
}
// ProxyBasic will force HTTP authentication before any request to the proxy is processed
func ProxyBasic(proxy *goproxy.ProxyHttpServer, realm string, f func(user, passwd string) bool) {
proxy.OnRequest().Do(Basic(realm, f))
proxy.OnRequest().HandleConnect(BasicConnect(realm, f))
}

View File

@@ -1,585 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="he">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1255">
<meta http-equiv="Content-Language" content="he"/>
<!--meta http-equiv="Content-Type" content="text/html; charset=utf-8" /-->
<META NAME="Keywords" CONTENT="àåðéáøñéèä, äåøàä îøçå÷, ÷åøñéí, Distance Learning, E-Learning, University, Education, Open, Courseware, Israel, Higher Education, Satellite, Telecourses, Courses, educational technology, computer-mediated, studies">
<meta http-equiv="Content-Style-Type" content="text/css">
<title>ãó äáéú ùì ùä&quot;í</title>
<link rel="alternate" href="rss/rss.xml" type="application/rss+xml" title="çãùåú åòãëåðéí îùä&quot;í, äîøëæ ìùéìåá èëðåìåâéåú áäåøàä îøçå÷ áàåðéáøñéèä äôúåçä"/>
<link rel="stylesheet" type="text/css" href="design/common.css">
<link rel="stylesheet" type="text/css" href="design/news.css">
<script language="javascript" type="text/javascript" src="js_scripts/shoham_common.js"></script>
<script language="JavaScript" src="include/email_unobfuscator.js" type="text/javascript"></script>
<script type="text/javascript" src="/js_scripts/toolbox.js"></script>
<script type="text/javascript">
var semester='2012b'; // current semester
var hebrewSemester;
//js for the flash movie:
function getSemester(){
return semester;
//return '2009a';
}
setSemester(semester);
switchLinkSemester(semester);
createSuggestionScript();
switchCoursesSuggestionSource(semester);
addLoadEvent(function() {
// ADD JAVASCRIPT EVENTS/FUNCTIONS ETC. YOU WANT TO BE CALLED ONLOAD HERE AND ONLY HERE
showHideMessage();
//addIt();
//setAddThis();
} )
var tBox = new QQtoolBox();
</script>
<!--script language="javascript" src="js_scripts/flash2.js"></script-->
<link rel="stylesheet" href="suggestion/suggestion.css" media="screen" type="text/css">
</head>
<body>
<div id="container">
<div id="header">
<div id="header_right">
<a href="/" target="_self" title="ùä&quot;í"><img src="graphics_nhp/shoam_logo_s.jpg" border="0" alt="ùä&quot;í" target="_self"></a>
</div>
<div id="header_left">
<div id="header_left_op">
<a href="http://www.openu.ac.il/" target="_self" title="àåôð'è"><img src="graphics_nhp/openu.gif" border="0" alt="àåôð'è"></a>
</div>
<!--div id="search"-->
<!-- search_hp.html (START) -->
<!--script language="javascript" src="opusSearch.js" type="text/javascript"></script-->
<div id="search">
<form name="form" action="http://www.google.co.il/search" id="simpleSearch" target="" method="get">
<input type="text" id="as_q" name="as_q" onFocus="this.select()" value="çôùå áàúø æä åáàúøé ä÷åøñéí">
<input type="hidden" id="hl" name="hl" value="iw">
<input type="hidden" id="as_sitesearch" name="as_sitesearch" value="telem.openu.ac.il">
<!--a id="button" title="çéôåù áâåâì" href="javascript:simpleSearch();"><span>&nbsp;çôù</span></a-->
<a id="button" title="çéôåù áâåâì" onclick="form.submit()"><span>&nbsp;çôù</span></a>
</form>
<div id="header_eng"><span class="eng"><a href="http://www-e.openu.ac.il/geninfor/shoham.html" target="_self" title="shoham english site">English</a></span></div>
</div>
<!-- search_hp.html (END) -->
<!--/div-->
</div>
<!--end of header-->
</div>
<div id="content">
<div id="text">
<div id="right">
<div id="top_right">
<div id="top_right_text">
<h1>ëðéñä ìàúøé ä÷åøñéí</h1>
<!-- suggestion.htm (START) -->
<meta http-equiv="Content-Type" content="text/html; charset=windows-1255">
<meta http-equiv="Content-Language" content="he"/>
<link rel="stylesheet" href="suggestion/suggestion.css" media="screen" type="text/css">
<style type="text/css">
/* script suggestion CSS START */
/* uri: don't touch this section unless your name is "Uri Shefi" */
#suggestion_box{
/*dawidth: 245px; */ /* causes some courses to disapear */
border:solid 0px;
font-size: 15px;
}
#course_suggestion{ /* input */
direction: rtl;
font-family: Arial, Verdana, Tahoma;
font-size: 12px;
border: 1px solid #CCCCCC;
width: 170px;
height:15px;
}
.autocomplete{
/* right: 178px; */
width: 280px;
}
/* script suggestion CSS END */
.suggestion_button{
border: 0px solid #CCCCCC;
vertical-align:middle;
cursor: pointer;
/*
width:23px;
height:19px;
*/
padding-bottom:2px;
/*cursor: hand;*/
}
#current_semester{
font-family: Arial, Verdana, Tahoma;
font-size: 15px;
text-transform: uppercase;
width: 122px;
}
#autoComplteMessageLayer{
}
#summerLink, #summerLink a{
color: red;
display: none;
font-weight: bold;
font-size: 15px;
text-decoration: underline;
cursor: hand;
}
</style>
<div id="switch_semester_box">
<span id="koteret">ñîñèø</span>
<select id="current_semester" onChange="refreshSemester(this.options[this.selectedIndex].value);">
<option value="2012b">2012 á (àáéá)</option>
<option value="2012a">2012 à (ñúéå)</option>
<option value="2011c">2011 â (÷éõ)</option>
<option value="2011b">2011 á (àáéá)</option>
<option value="2011a">2011 à (ñúéå)</option>
<option value="2010c">2010 â (÷éõ)</option>
<option value="2010b">2010 á (àáéá)</option>
<option value="2010a">2010 à (ñúéå)</option>
<option value="2009c">2009 â (÷éõ)</option>
<option value="2009b">2009 á (àáéá)</option>
<option value="2009a">2009 à (ñúéå)</option>
<option value="2008c">2008 â (÷éõ)</option>
<option value="2008b">2008 á (àáéá)</option>
<option value="2008a">2008 à (ñúéå)</option>
<option value="2007c">2007 â (÷éõ)</option>
<option value="2007b">2007 á (àáéá)</option>
<option value="2007a">2007 à (ñúéå)</option>
<option value="2006c">2006 â (÷éõ)</option>
<option value="2006b">2006 á (àáéá)</option>
<option value="2006a">2006 à (ñúéå)</option>
<option value="2005c">2005 â (÷éõ)</option>
<option value="2005b">2005 á (àáéá)</option>
<option value="2005a">2005 à (ñúéå)</option>
</select>
</div>
<!-- SEGGUESTION BOX (START) -->
<div style="text-align: right; color:#404040" id="suggestion_box">
ùí ÷åøñ àå îñôø ÷åøñ <div id="suggestion_course_display"></div><br/>
<input type="text" id="course_suggestion" value="øùéîú ä÷åøñéí äîåöòéí áñîñèø äðáçø" maxlength="60" title="øùéîú ä÷åøñéí äîåöòéí áñîñèø æä"><img src="graphics_nhp/mgIcon2.jpg" onclick="evalChoice();" class="suggestion_button" alt="ìàúø ä÷åøñ" />
<!--div id="autoComplteMessageLayer"></div-->
<!--<span id='summerLink' onClick="refreshSemester('2011c');">ìñîñèø ÷éõ 2011â ìçõ ëàï</span>-->
<span id='summerLink'><a href="courses_lists/courses_2011c.html">ìñîñèø ÷éõ 2011â ìçõ ëàï</a></span>
</div>
<!-- SEGGUESTION BOX (END) -->
<div id="fulllist">
<a href="courses_lists/courses_2009a.html" id="courses_full_link" target="_self"> ìøùéîú àúøé ä÷åøñéí åäîçì÷åú</a> <div id="courses_full_link_display"></div>
</div>
<!-- suggestion.htm (END) -->
</div>
<!--end of top_right-->
</div>
<div id="bottom_right">
<div id="bottom_right_text">
<h1>öååúé äåøàä</h1>
<div class="linklist_a">
<a href="content/help_staff.html" target="_self" class="linklist_item_a" title="úîéëä åòæøä">úîéëä åòæøä</a><br>
<a href="content/training.html" target="_self" class="linklist_item_a" title="äãøëåú ìñâì ääåøàä">äãøëåú ìñâì ääåøàä </a>&nbsp;<img src="graphics_nhp/star_bg_gray.gif" border="0" alt="">&nbsp;<span class="new">çãù</span><br>
<a href="http://telem.openu.ac.il/segel/" target="_self" class="linklist_item_a" title="àúø öååúé äåøàä">àúø öååúé äåøàä</a><br>
<a href="http://telem.openu.ac.il/content/virtual_shoham.html" target="_self" class="linklist_item_a" title="ëéúä åéøèåàìéú">ëéúä åéøèåàìéú</a><br>
<a href="http://telem.openu.ac.il/content/matalot_staff.html" target="_self" class="linklist_item_a" title="îòøëú äîèìåú">îòøëú äîèìåú</a><br>
<a href="http://telem.openu.ac.il/tikshuv_prize/" target="_blank" class="linklist_item_a" title="úçøåú îú÷ùá îöèééï">úçøåú îú÷ùá îöèééï</a><br>
<a href="http://telem.openu.ac.il/content/hp_search.html" target="_blank" class="linklist_item_a" title="çéôåù áàúøé ä÷åøñéí">çéôåù áàúøé ä÷åøñéí</a><br>
<!--a href="http://telem.openu.ac.il/courses/resources/private/oracle_Brochure.pdf" target="_blank" class="linklist_item_a" title="äòìàú çåáøú ä÷åøñ ìàúø ">äòìàú çåáøú ä÷åøñ</a>&nbsp;&nbsp;(<a href="https://sheilta.apps.openu.ac.il/pls/myopr/BOOKLET.FIRST" target="_blank" title="ëðéñä ìîåøùéí">ëðéñä ìîåøùéí</a>)<!--&nbsp;&nbsp;&nbsp;<img src="graphics_nhp/star_bg_gray.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>--><br-->
<a href="http://www.openu.ac.il/surveys/teaching_reports.html" target="_blank" class="linklist_item_a" title="ãåçåú ñ÷ø äåøàä">ãåçåú ñ÷ø äåøàä</a>&nbsp;&nbsp;(<img border="0" src="graphics_nhp/content_img/lockg.gif" title="ëðéñä ìáòìé äøùàåú áìáã îúåê äàå&quot;ô" alt="ëðéñä ìáòìé äøùàåú áìáã îúåê äàå&quot;ô" />)
<!--&nbsp;&nbsp;&nbsp;<img src="graphics_nhp/star_bg_gray.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>--><br>
<a href="https://sso.apps.openu.ac.il/login?T_PLACE=https://sheilta.apps.openu.ac.il/pls/myopr/PELE.FIRST" target="_blank" class="linklist_item_a" title="ôåøèì îðçéí">ôåøèì îðçéí </a>&nbsp;
(<img border="0" src="graphics_nhp/content_img/lockg.gif" title="ëðéñä ìáòìé äøùàåú áìáã îúåê äàå&quot;ô" alt="ëðéñä ìáòìé äøùàåú áìáã îúåê äàå&quot;ô" />)
<!--&nbsp;&nbsp;<img src="graphics_nhp/star_bg_gray.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>--><br>
<a href="http://opal.openu.ac.il" title="ëðéñä ìñáéáú äìîéãä äçãùä" target="_blank" class="new">îòøëú àåÉôÌÈì</a><!--&nbsp;<img src="graphics_nhp/star_bg_gray.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>--><br>
<a href="http://opal.openu.ac.il/course/view.php?id=107" title=" " target="_blank">ðéäåì àúøé ÷åøñéí - îãøéê ìîøëæéí</a>&nbsp;(<img border="0" src="graphics_nhp/content_img/lockg.gif" title="ëðéñä ìáòìé äøùàåú áìáã îúåê äàå&quot;ô" alt="ëðéñä ìáòìé äøùàåú áìáã îúåê äàå&quot;ô" />)
<img src="graphics_nhp/star_bg_gray.gif" border="0" alt=""><span class="new">çãù</span><br>
<br>
</div>
<h1>ñèåãðèéí</h1>
<div class="linklist_a">
<a href="/content/help_students.html" target="_self" class="linklist_item_a" title="úîéëä åòæøä">úîéëä åòæøä</a><br>
<a href="https://sheilta.apps.openu.ac.il/pls/dmyopt2/user_form.first?p_from=http://telem.openu.ac.il/hp_files/html_files/user_info.html" target="_blank" class="linklist_item_a" title="òãëåï ôøèéí àéùééí">òãëåï ôøèéí àéùééí</a><br>
<a href="http://www.openu.ac.il/sheilta/" target="_blank" class="linklist_item_a" title="ùàéìú'à">ùàéìú&quot;à</a><br>
<a href="https://sheilta.apps.openu.ac.il/pls/dmyopt2/LUACH_SHANA.first?p_time=" target="_blank" class="linklist_item_a" title="ìåç æîðéí îô'ä">ìåç æîðéí - îô&quot;ä</a><br>
<a href="/content/matalot_stud.html" target="_self" class="linklist_item_a" title="îòøëú äîèìåú">îòøëú äîèìåú</a><br>
<a href="/content/ofek.html" target="_self" class="linklist_item_a" title="àåô÷">àåô÷ - ùéòåøéí áåéãéàå</a>&nbsp;&nbsp;&nbsp;&nbsp;<!--img src="graphics_nhp/star_bg_gray.gif" border="0" alt="">&nbsp;<span class="new">çãù</span--><br>
<a href="http://telem.openu.ac.il/content/elluminate_support.html" target="_self" class="linklist_item_a" title=" ëéúä åéøèåàìéú (Elluminate)"> ëéúä åéøèåàìéú (Elluminate) </a><br>
<!--<a href="http://telem.openu.ac.il/content/GoToMeeting.html" target="_self" class="linklist_item_a" title=" ëéúä åéøèåàìéú (GoToMeeting)"> ëéúä åéøèåàìéú (GoToMeeting) </a><br>-->
<a href="/content/courseware.html" target="_self" class="linklist_item_a" title="îàâø äìåîãåú åäú÷ìéèåøéí">îàâø äìåîãåú åäú÷ìéèåøéí</a><br>
<a href="http://telem.openu.ac.il/academic-paper/index.htm" target="_blank" class="linklist_item_a" title="ëúéáú òáåãä ñîéðøéåðéú">ëúéáú òáåãä ñîéðøéåðéú (ìåîãä)</a><br>
<a href="http://estudy.openu.ac.il/opus/bin/en.jsp?enPage=AnnotationsPage&enDispWho=Annotations&enZone=Annotations" target="_blank" class="linklist_item_a" title="ëðéñä ìôð÷ñ äàéùé">ôð÷ñ àéùé</a><br>
<a href="http://www.openu.ac.il/new-student/" target="_blank" class="linklist_item_a" title="àúø äñèåãðè">äîãøéê ìñèåãðè äçãù</a>
<br>
</div>
<!--<div id="mashov_gen">
<div class="mashov"><a href="http://forum.openu.ac.il/opus/bin/en.jsp?enZone=Forum117583" target="_blank" title="îùåá ìùä&quot;í">ôåøåí îùåá - çåå ãòúëí òì àúøé ä÷åøñéí, äìåîãåú, åé÷é... </a></div>
</div>-->
</div>
<!--end of bootom_right-->
</div>
<!--end of right-->
</div>
<div id="left">
<div id="flash_zone" title="Falsh Movie" astyle="background:url(graphics_nhp/flash.jpg) 100 0 no-repeat;">
<!-- <script type="text/javascript" src="js_scripts/flash.js"></script>
--><!--must be after the last </boject> -->
<img src="graphics_nhp/flash.jpg" border="0" alt="rss" valign="left" align="abstop">
</div>
<div id="message" class="messageHidden">
<!--ôúéçú ñîñèø-->
<!--spring-->
<div class="tm">
<div class="img">
<IMG alt="" src="graphics_nhp/message_gifs/icon_spring.gif" border=0></div>
<strong>&nbsp;&nbsp;àúøé 2012á ðôúçå ìñèåãðèéí. öååú ùä"í îàçì ìëí ñîñèø îåöìç.</strong>
<span class="date">(4.3.12)</span>
</div>
</div>
<!--center><img src="content/happy_holiday.gif" style="padding: 3px; margin: 3px;"></center-->
<div id="links_zone">
<div id="links_right">
<h1>
<span class="news">çãùåú åòãëåðéí</span>
<span class="rss">
<span class="rss_text"><a href="content/rss_help.html" target="_blank" title="òæøä"><span id="rss_gif">?</span>rss&nbsp;</a><img src="graphics_nhp/rss.jpg" border="0" alt="rss" valign="left" align="abstop"></span></span>
</h1>
<div id="rss_list">
<ul class='newsBriefList'>
<li class='newsBriefItem'><a href='http://shohamnews.blogspot.com/2012/03/html5.html' target='_blank'>HTML5</a>
<div class='newsBriefDate'>2012-03-21 12:45:00</div>
</li>
<li class='newsBriefItem'><a href='http://shohamnews.blogspot.com/2012/03/2012.html' target='_blank'>÷åì ÷åøà ìäâùú äöòåú ìëðñ îéè&quot;ì äòùéøé 2012</a>
<div class='newsBriefDate'>2012-03-07 12:52:00</div>
</li>
<li class='newsBriefItem'><a href='http://shohamnews.blogspot.com/2012/03/19312.html' target='_blank'>äæîðä ìäøöàä áñîéðø äîç÷ø ùì äîç÷ø ìç÷ø çãùðåú åùä&quot;í - 19.3.12</a>
<div class='newsBriefDate'>2012-03-07 09:03:00</div>
</li>
<li class='newsBriefItem'><a href='http://peer-news.blogspot.com/2012/01/blog-post_18.html' target='_blank'>ñôø ÷åìé ðåñó á÷åøñ â&#39;ðåñééã: &quot;äùîãú äòîéí äàéðãéàðéí ùì àîøé÷ä äñôøãéú</a>
<div class='newsBriefDate'>2012-01-18 14:41:00</div>
</li>
<li class='newsBriefItem'><a href='http://peer-news.blogspot.com/2012/01/blog-post.html' target='_blank'>ñôø ÷åìé çãù á÷åøñ â&#39;ðåñééã: &quot;áéï âæòðåú ìâ&#39;ðåñééã áòú äîåãøðéú</a>
<div class='newsBriefDate'>2012-01-18 14:31:00</div>
</li>
<li class='newsBriefItem'><a href='http://peer-news.blogspot.com/2012/01/10934.html' target='_blank'>ëøê ðåñó á÷åøñ &quot;áèäåáï - îåøã åøåîðèé÷ï&quot; (10934)</a>
<div class='newsBriefDate'>2012-01-15 14:21:00</div>
</li>
</ul>
</div>
<div id="allnews">
<div id="allnews_link">
<a href="content/news.html"> ìøùéîä äîìàä</a>
<!--a href="/content/news.html" target="_blank" title="ìøùéîú äòéãëåðéí äîìàä"-->
</div>
</div>
</div>
<div id="links_mid">
<h1>ôòéìåéåú äîøëæ</h1>
<div class="linklist">
<a href="/content/about_shoham.html" target="_self" class="linklist_item" title="àåãåú ùä&quot;í">àåãåú ùä&quot;í</a><br>
<a href="http://telem.openu.ac.il/content/about_shoham.html#organizational_structure" target="_self" class="linklist_item" title="îáðä àøâåðé">îáðä àøâåðé</a><!--&nbsp;<img src="graphics_nhp/star_bg_gray.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>--> <br>
<a href="/content/distance_edu.html" target="_self" class="linklist_item" title="äåøàä åìîéãä îøçå÷">äåøàä åìîéãä îøçå÷</a><br>
<a href="/content/courses_sites.html" target="_self" class="linklist_item" title="àúøé ä÷åøñéí">àúøé ä÷åøñéí</a><br>
<a href="http://telem.openu.ac.il/content/moodle_move.html" target="_self" class="linklist_item" title="ñáéáú ìîéãä çãùä áàå&quot;ô Moodle">ñáéáú ìîéãä çãùä áàå&quot;ô Moodle</a>&nbsp;<img src="graphics_nhp/star.gif" border="0" alt=""><br>
<a href="/content/vid_learning.html" target="_self" class="linklist_item" title=" åéãàå áäåøàä ñéðëøåðéú ">åéãàå åäåøàä ñéðëøåðéú</a> <img src="graphics_nhp/star.gif" border="0" alt="">&nbsp;<span class="new">çãù</span><br>
<a href="/content/virtual_class.html" target="_self" class="linklist_item" title=" ëéúä åéøèåàìéú - ìîéãä îäáéú ">ëéúä åéøèåàìéú - ìîéãä îäáéú</a> <!--<img src="graphics_nhp/star.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>--><br>
<!--<a href="http://telem.openu.ac.il/content/elluminate.html" target="_self" class="linklist_item" title="ëéúä åéøèåàìéú - ðéñåé Elluminate">ëéúä åéøèåàìéú - ðéñåé Elluminate</a> -->
<a href="http://telem.openu.ac.il/content/video_classes.html" target="_self" class="linklist_item" title=" öéìåí îôâùé äðçéä áëéúåú">öéìåí îôâùé äðçéä áëéúåú</a><!-- <img src="graphics_nhp/star.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>--><br>
<a href="/content/digital.html" target="_self" class="linklist_item" title="çåîøé ìîéãä àéðèøà÷èéáééí">çåîøé ìîéãä àéðèøà÷èéáééí</a> <!--<img src="graphics_nhp/star.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>--><br>
<a href="/content/pedagogical_dev.html" target="_self" class="linklist_item" title="ôéúåç ôãâåâé, äèîòä åäãøëä">ôéúåç ôãâåâé, äèîòä åäãøëä</a><br>
<a href="/content/tools.html" target="_self" class="linklist_item" title="ëìéí ìàéøâåï åðéäåì äìîéãä">ëìéí ìàéøâåï åðéäåì äìîéãä</a><br>
<!--<a href="/content/future_project.html" target="_self" class="linklist_item" title="ðéñåééí åôøåé÷èéí îéåçãéí"> ðéñåééí åôøåé÷èéí îéåçãéí</a> &nbsp;--><!--<img src="graphics_nhp/star.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>-->
<a href="http://telem.openu.ac.il/content/sadan.html" target="_self" class="linklist_item" title="ñã&quot;ï - ñôøéí ãéâéèàìééí ðééãéí">ñôøéí ãéâéèàìééí ðééãéí</a>&nbsp;<img src="graphics_nhp/star.gif" border="0" alt="">&nbsp;<span class="new">çãù</span><br>
<a href="http://telem.openu.ac.il/content/audio_books.html" target="_self" class="linklist_item" title="ñôøéí ÷åìééí &ndash; òøåõ ìîéãä ðåñó">ñôøéí ÷åìééí òøåõ ìîéãä ðåñó</a> <!--&nbsp;<img src="graphics_nhp/star.gif" border="0" alt="">&nbsp;<span class="new"> çãù --><br>
<a href="/content/cooperative_learning.html" target="_self" class="linklist_item" title="ìîéãä ùéúåôéú">ìîéãä ùéúåôéú</a><br>
<a href="http://wiki-openu.openu.ac.il/courses/wikiop" target="_blank" class="linklist_item" title="åé÷éàåô"><img src="graphics_nhp/wiki.gif" border="0" alt="åé÷éàåô">&nbsp;åé÷éàåô</a><br>
</div>
<br>
<div class="linklist_em">
<a href="http://telem.openu.ac.il/hp_files/paper/archive/index.html" target="_self" class="linklist_item" title="öìéì î÷ååï">öìéì î÷ååï - òìåï ùä&quot;í</a><!-- <img src="graphics_nhp/star.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>--><br>
<a href="http://www.shoham-at-ou.blogspot.com/" target="_blank" class="linklist_item" title="áìåâ ùä&quot;í">áìåâ ùä&quot;í</a><br>
<img src="graphics_nhp/twitter_icon_small.gif" border="0" alt="èååéèø" align="absbottom">&nbsp; <a href="http://twitter.com/shoham1" target="_blank" class="linklist_item" title="twitter">ò÷áå àçøéðå á-twitter </a><!--img src="graphics_nhp/star_bg_gray.gif" border="0" alt="">&nbsp;<span class="new">çãù</span--><br>
<a href="content/articles.html" target="_self" class="linklist_item" title="îàîøéí åîöâåú îëðñéí">îç÷øé äòøëä, îàîøéí åîöâåú</a><!-- <img src="graphics_nhp/star_bg_gray.gif" border="0" alt="">&nbsp;<span class="new">çãù</span>--><br>
<a href="content/lectures.html" target="_self" class="linklist_item" title="éîé òéåï">éîé òéåï áèëðåìåâéåú ìîéãä</a><!-- <img src="graphics_nhp/star.gif" border="0" alt="">&nbsp;<span class="new">çãù</span><br>-->
</div>
</div>
<div id="links_left">
<!--div class="linklist" id="linklist"-->
<!--a href="http://telem.openu.ac.il/content/contact_us.html" class="linklist_item" title="öåø ÷ùø">öåø ÷ùø</a><br-->
<!--a href="http://www-e.openu.ac.il/geninfor/136.html" target="_self" class="linklist_item" title="english">English</a><br><br-->
<!--a href="http://ocw.openu.ac.il/" target="_blank" class="linklist_item_gif" title="ôà'ø"><img src="graphics_nhp/ocw.gif" border="0" alt="ôà'ø"></a><br-->
<!--/div-->
<h1>çåîøé ìéîåã ôúåçéí</h1>
<img src="graphics_nhp/logos8.jpg" width="170" border="1" usemap="#Map">
<map name="Map">
<area shape="rect" coords="2,68,81,106" href="http://goo.gl/4BPH" target="_blank" title="ñôøé äàå&quot;ô áâøñä àì÷èøåðéú">
<area shape="rect" coords="89,68,167,108" href="http://www.youtube.com/user/openofek" target="_blank" title="òøåõ YouTub ùì äàå&quot;ô">
<area shape="rect" coords="90,112,168,154" href="http://www.kotar.co.il/" target="_blank" title="ñôøé äàå&quot;ô áñôøéä äî÷ååðú ùì îè&quot;ç">
<area shape="rect" coords="13,2,155,61" href="http://ocw.openu.ac.il/" target="_blank" alt="ñôøéí åçåîøé ìéîåã ôúåçéí ìëì" title="ñôøéí åçåîøé ìéîåã ôúåçéí ìëì">
<area shape="rect" coords="2,113,81,154" onclick="tBox.objVisibility('iconmenu');" target="_blank" title="ñôøé äàå&quot;ô áâøñä ÷åìéú">
</map>
<div id="iconmenu" style="display: none; border: 1px solid gray; background-color: white; padding-right:2px; font-size:1.3em; color:#336699; padding-right:2px; ">
<a href="http://goo.gl/kBQ1F" title="äøöàåú" target="_blank" class="linklist_item">äøöàåú</a><br>
<a href="http://goo.gl/dywt" title="ñôøéí ÷åìééí" target="_blank"class="linklist_item">ñôøéí ÷åìééí</a>
<div style="color: blue; cursor: pointer; text-align: center;" onclick="tBox.objVisibility('iconmenu', 0);">[x] ñâåø</div>
</div>
<br><br>
<div class="linklist_em">
<a href="/content/opensources.html" target="_self" class="linklist_item" title="ìôéøåè àåãåú äòøåöéí äôúåçéí"> ìôéøåè àåãåú äòøåöéí äôúåçéí </a><!--img src="graphics_nhp/star.gif" border="0" alt="">&nbsp;<span class="new">çãù</span--><br>
</div>
<!--<div class="linklist_em">
<a href="http://ocw.openu.ac.il/" target="_blank" class="linklist_item_gif" title="ôà'ø"><img src="graphics_nhp/ocw_s1_gray.gif" border="0" alt='ôà"ø - ôúéçú àåöøåú øåç'></a><br>
<a href="http://www.kotar.co.il/" target="_blank" class="linklist_item" title='ñôøé äàå"ô áëåúø îè"ç'> ñôøé äàå"ô áëåúø îè"ç</a><br>
<a href="http://goo.gl/4BPH" target="_blank" class="linklist_item" title='ñôøé äàå"ô google books'> ñôøé äàå"ô google books </a> <br>
<a href="http://www.youtube.com/user/openofek" target="_blank" class="linklist_item" title=' YouTube òøåõ äàå"ô'><img src="graphics_nhp/youtube_small.gif" alt="youtube" width="40" height="17" border="0" align="absbottom">&nbsp; òøåõ äàå"ô</a>
<a href="http://www.icast.co.il/default.aspx?p=default&c_list=1&c=82" target="_blank" class="linklist_item" title='òøåõ äàå"ô á- iCast'>òøåõ äàå"ô á- iCast &nbsp;<!--img src="graphics_nhp/icast_logo.png" border="0" alt="youtube" align="absbottom"></a><br>-->
<!--<a href="http://ocw.openu.ac.il/newsletter/01.html" target="_blank" class="linklist_item" title='àåöøåú - òìåï ôà"ø'> àåöøåú - òìåï ôà"ø </a> <br> -->
<!--a href="content/presentations.html" target="_self" class="linklist_item" title="îöâåú áëðñéí">îöâåú áëðñéí</a><br>
</div>-->
<br>
<h1>÷éùåøéí</h1>
<div class="linklist" id="links">
<a href="http://www.openu.ac.il/Library/" target="_blank" class="linklist_item" title="ñôøéä åîàâøé îéãò">ñôøéä åîàâøé îéãò</a><br>
<a href="http://www.openu.ac.il/innovation/" target="_blank" class="linklist_item" title="äîøëæ ìç÷ø çãùðåú áèëðåìåâéåú ìîéãä">äîøëæ ìç÷ø çãùðåú áèëðåìåâéåú ìîéãä</a><br>
<a href="http://meital.iucc.ac.il/" target="_blank" class="linklist_item" title="îøëæ éãò èëðåìåâéåú ìîéãä ">îéè&quot;ì</a><br>
<!--<a href="http://wiki-openu.openu.ac.il/courses/wikiop" target="_blank" class="linklist_item" title=""><img src="graphics_nhp/oui_books_icon.jpg" alt="ñôøéí ãéâéèìéí" width="23" height="13" border="0">&nbsp;äñôøéí äãéâéèìéí áôééñáå÷</a><br>-->
</div>
<!-- share this button (start)
<span class='st_sharethis' displayText='ShareThis' style="width: 100px; height: 100px;"></span>
<script type="text/javascript">var switchTo5x=false;</script><script type="text/javascript" src="http://w.sharethis.com/button/buttons.js"></script><script type="text/javascript">stLight.options({publisher:'c009e98c-ad2e-4156-afda-95a59aca520c'});</script>
share this button (end) -->
<!-- AddToAny BEGIN -->
<a class="a2a_dd" href="http://www.addtoany.com/share_save"><img src="http://static.addtoany.com/buttons/share_save_171_16.png" width="171" height="16" border="0" alt="Share"/></a>
<script type="text/javascript">
var a2a_config = a2a_config || {};
a2a_config.onclick = 1;
a2a_config.locale = "he";
a2a_config.num_services = 4;
</script>
<script type="text/javascript" src="http://static.addtoany.com/menu/page.js"></script>
<!-- AddToAny END -->
<!-- google +1 (START) -->
<script type="text/javascript" src="http://apis.google.com/js/plusone.js">
{lang: 'iw'}
</script>
<g:plusone size="small"></g:plusone>
<!-- google +1 (START) -->
</div>
<!--end of links_zone-->
</div>
<!--end of left-->
</div>
<!--end of text-->
</div>
<div id="close">
</div>
<!--end of content-->
</div>
<div id="footer">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1255" />
<meta http-equiv="Content-Language" content="he" />
<div id="footer1">
<a href="http://telem.openu.ac.il/content/about_shoham.html" id="abouts" title="àåãåú" target="_blank">àåãåú</a><!--&nbsp;|-->
<a href="http://telem.openu.ac.il/content/contact_us.html" id="conts" title="öåø ÷ùø" target="_blank">öåø ÷ùø</a><!--&nbsp;|-->
<a href="/" id="hps" title="ãó äáéú" target="_self">ãó äáéú</a><!--&nbsp;|-->
<a href="http://www.openu.ac.il/" id="opnets" title="àåôð'è" target="_self"><img src="http://telem.openu.ac.il/graphics_nhp/openu_icon.gif" border="0" alt="àåôðè" /></a><!--&nbsp;|-->
</div>
<div id="footer2">
<table id="copyRight" style="display: none;" align="center" width="180" cellspacing="0" cellpadding="1" border="0" bgcolor="#000000">
<tr>
<td>
<table cellspacing="0" cellpadding="3" border="0" width="100%">
<tr>
<td bgcolor="#FFFFFF">
<span id="open" style="cursor: pointer;" onclick="showHideLayer('copyRight', '', '');">[ñâåø]</span>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<center><b>ùéîåù îñçøé áçåîø äëìåì áàúøéí àìä àñåø áäçìè, àìà áøùåú îôåøùú åáëúá îîãåø æëåéåú éåöøéí ùì äàå'ô <BR /></b>
</center>
</td>
</tr>
</table>
</td>
</tr>
</table>
Copyright &copy;,The Open University of Israel 1997-2012 <b style="cursor: pointer;" onclick="showHideLayer('copyRight', '', '');">all rights reserved<br />
ëì äæëåéåú ùîåøåú </b>&copy; ìàåðéáøñéèä äôúåçä. úùò"á - 2012
</div>
<!--include virtual="/include/general/footer_source_popup_shoham_logical.htm" -->
<!--include virtual="/include/general/footer_code_popup_shoham_logical.html" -->
<!-- GOOGLE ANALYTICS (TELEM ONLY) START -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-4646503-5");
//pageTracker._initData();
pageTracker._trackPageview();
</script>
<!-- GOOGLE ANALYTICS (TELEM ONLY) END -->
</div>
<!--end of container-->
</div>
</body>
</html>

View File

@@ -1 +0,0 @@
<EFBFBD><EFBFBD>

View File

@@ -1,104 +0,0 @@
// extension to goproxy that will allow you to easily filter web browser related content.
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")
// HandleString will receive a function that filters a string, and will convert the
// request body to a utf8 string, according to the charset specified in the Content-Type
// header.
// guessing Html charset encoding from the <META> tags is not yet implemented.
func HandleString(f func(s string, ctx *goproxy.ProxyCtx) string) goproxy.RespHandler {
return HandleStringReader(func(r io.Reader, ctx *goproxy.ProxyCtx) io.Reader {
b, err := ioutil.ReadAll(r)
if err != nil {
ctx.Warnf("Cannot read string from resp body: %v", err)
return r
}
return bytes.NewBufferString(f(string(b), ctx))
})
}
// Will receive an input stream which would convert the response to utf-8
// The given function must close the reader r, in order to close the response body.
func HandleStringReader(f func(r io.Reader, ctx *goproxy.ProxyCtx) io.Reader) goproxy.RespHandler {
return goproxy.FuncRespHandler(func(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
if ctx.Error != nil {
return nil
}
charsetName := ctx.Charset()
if charsetName == "" {
charsetName = "utf-8"
}
if strings.ToLower(charsetName) != "utf-8" {
r, err := charset.NewReader(charsetName, resp.Body)
if err != nil {
ctx.Warnf("Cannot convert from %v to utf-8: %v", charsetName, err)
return resp
}
tr, err := charset.TranslatorTo(charsetName)
if err != nil {
ctx.Warnf("Can't translate to %v from utf-8: %v", charsetName, err)
return resp
}
if err != nil {
ctx.Warnf("Cannot translate to %v: %v", charsetName, err)
return resp
}
newr := charset.NewTranslatingReader(f(r, ctx), tr)
resp.Body = &readFirstCloseBoth{ioutil.NopCloser(newr), resp.Body}
} else {
//no translation is needed, already at utf-8
resp.Body = &readFirstCloseBoth{ioutil.NopCloser(f(resp.Body, ctx)), resp.Body}
}
return resp
})
}
type readFirstCloseBoth struct {
r io.ReadCloser
c io.Closer
}
func (rfcb *readFirstCloseBoth) Read(b []byte) (nr int, err error) {
return rfcb.r.Read(b)
}
func (rfcb *readFirstCloseBoth) Close() error {
err1 := rfcb.r.Close()
err2 := rfcb.c.Close()
if err1 != nil && err2 != nil {
return errors.New(err1.Error() + ", " + err2.Error())
}
if err1 != nil {
return err1
}
return err2
}

View File

@@ -1,78 +0,0 @@
package goproxy_image
import (
"bytes"
"image"
_ "image/gif"
"image/jpeg"
"image/png"
"io/ioutil"
"net/http"
. "github.com/elazarl/goproxy"
"github.com/elazarl/goproxy/regretable"
)
var RespIsImage = ContentTypeIs("image/gif",
"image/jpeg",
"image/pjpeg",
"application/octet-stream",
"image/png")
// "image/tiff" tiff support is in external package, and rarely used, so we omitted it
func HandleImage(f func(img image.Image, ctx *ProxyCtx) image.Image) RespHandler {
return FuncRespHandler(func(resp *http.Response, ctx *ProxyCtx) *http.Response {
if !RespIsImage.HandleResp(resp, ctx) {
return resp
}
if resp.StatusCode != 200 {
// we might get 304 - not modified response without data
return resp
}
contentType := resp.Header.Get("Content-Type")
const kb = 1024
regret := regretable.NewRegretableReaderCloserSize(resp.Body, 16*kb)
resp.Body = regret
img, imgType, err := image.Decode(resp.Body)
if err != nil {
regret.Regret()
ctx.Warnf("%s: %s", ctx.Req.Method+" "+ctx.Req.URL.String()+" Image from "+ctx.Req.RequestURI+"content type"+
contentType+"cannot be decoded returning original image", err)
return resp
}
result := f(img, ctx)
buf := bytes.NewBuffer([]byte{})
switch contentType {
// No gif image encoder in go - convert to png
case "image/gif", "image/png":
if err := png.Encode(buf, result); err != nil {
ctx.Warnf("Cannot encode image, returning orig %v %v", ctx.Req.URL.String(), err)
return resp
}
resp.Header.Set("Content-Type", "image/png")
case "image/jpeg", "image/pjpeg":
if err := jpeg.Encode(buf, result, nil); err != nil {
ctx.Warnf("Cannot encode image, returning orig %v %v", ctx.Req.URL.String(), err)
return resp
}
case "application/octet-stream":
switch imgType {
case "jpeg":
if err := jpeg.Encode(buf, result, nil); err != nil {
ctx.Warnf("Cannot encode image as jpeg, returning orig %v %v", ctx.Req.URL.String(), err)
return resp
}
case "png", "gif":
if err := png.Encode(buf, result); err != nil {
ctx.Warnf("Cannot encode image as png, returning orig %v %v", ctx.Req.URL.String(), err)
return resp
}
}
default:
panic("unhandlable type" + contentType)
}
resp.Body = ioutil.NopCloser(buf)
return resp
})
}

View File

@@ -1,97 +0,0 @@
package regretable
import (
"io"
)
// A RegretableReader will allow you to read from a reader, and then
// to "regret" reading it, and push back everything you've read.
// For example,
// rb := NewRegretableReader(bytes.NewBuffer([]byte{1,2,3}))
// var b = make([]byte,1)
// rb.Read(b) // b[0] = 1
// rb.Regret()
// ioutil.ReadAll(rb.Read) // returns []byte{1,2,3},nil
type RegretableReader struct {
reader io.Reader
overflow bool
r, w int
buf []byte
}
var defaultBufferSize = 500
// Same as RegretableReader, but allows closing the underlying reader
type RegretableReaderCloser struct {
RegretableReader
c io.Closer
}
// Closes the underlying readCloser, you cannot regret after closing the stream
func (rbc *RegretableReaderCloser) Close() error {
return rbc.c.Close()
}
// initialize a RegretableReaderCloser with underlying readCloser rc
func NewRegretableReaderCloser(rc io.ReadCloser) *RegretableReaderCloser {
return &RegretableReaderCloser{*NewRegretableReader(rc), rc}
}
// initialize a RegretableReaderCloser with underlying readCloser rc
func NewRegretableReaderCloserSize(rc io.ReadCloser, size int) *RegretableReaderCloser {
return &RegretableReaderCloser{*NewRegretableReaderSize(rc, size), rc}
}
// The next read from the RegretableReader will be as if the underlying reader
// was never read (or from the last point forget is called).
func (rb *RegretableReader) Regret() {
if rb.overflow {
panic("regretting after overflow makes no sense")
}
rb.r = 0
}
// Will "forget" everything read so far.
// rb := NewRegretableReader(bytes.NewBuffer([]byte{1,2,3}))
// var b = make([]byte,1)
// rb.Read(b) // b[0] = 1
// rb.Forget()
// rb.Read(b) // b[0] = 2
// rb.Regret()
// ioutil.ReadAll(rb.Read) // returns []byte{2,3},nil
func (rb *RegretableReader) Forget() {
if rb.overflow {
panic("forgetting after overflow makes no sense")
}
rb.r = 0
rb.w = 0
}
// initialize a RegretableReader with underlying reader r, whose buffer is size bytes long
func NewRegretableReaderSize(r io.Reader, size int) *RegretableReader {
return &RegretableReader{reader: r, buf: make([]byte, size) }
}
// initialize a RegretableReader with underlying reader r
func NewRegretableReader(r io.Reader) *RegretableReader {
return NewRegretableReaderSize(r, defaultBufferSize)
}
// reads from the underlying reader. Will buffer all input until Regret is called.
func (rb *RegretableReader) Read(p []byte) (n int, err error) {
if rb.overflow {
return rb.reader.Read(p)
}
if rb.r < rb.w {
n = copy(p, rb.buf[rb.r:rb.w])
rb.r += n
return
}
n, err = rb.reader.Read(p)
bn := copy(rb.buf[rb.w:], p[:n])
rb.w, rb.r = rb.w + bn, rb.w + n
if bn < n {
rb.overflow = true
}
return
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,19 +0,0 @@
package transport
import "net/http"
type RoundTripper interface {
// RoundTrip executes a single HTTP transaction, returning
// the Response for the request req. RoundTrip should not
// attempt to interpret the response. In particular,
// RoundTrip must return err == nil if it obtained a response,
// regardless of the response's HTTP status code. A non-nil
// err should be reserved for failure to obtain a response.
// Similarly, RoundTrip should not attempt to handle
// higher-level protocol details such as redirects,
// authentication, or cookies.
//
// RoundTrip should not modify the request, except for
// consuming the Body. The request's URL and Header fields
// are guaranteed to be initialized.
RoundTrip(*http.Request) (*http.Response, error)
DetailedRoundTrip(*http.Request) (*RoundTripDetails, *http.Response, error)
}

View File

@@ -1,789 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// HTTP client implementation. See RFC 2616.
//
// This is the low-level Transport implementation of RoundTripper.
// The high-level interface is in client.go.
// This file is DEPRECATED and keep solely for backward compatibility.
package transport
import (
"net/http"
"bufio"
"compress/gzip"
"crypto/tls"
"encoding/base64"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/url"
"os"
"strings"
"sync"
)
// DefaultTransport is the default implementation of Transport and is
// used by DefaultClient. It establishes a new network connection for
// each call to Do and uses HTTP proxies as directed by the
// $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy)
// environment variables.
var DefaultTransport RoundTripper = &Transport{Proxy: ProxyFromEnvironment}
// DefaultMaxIdleConnsPerHost is the default value of Transport's
// MaxIdleConnsPerHost.
const DefaultMaxIdleConnsPerHost = 2
// Transport is an implementation of RoundTripper that supports http,
// https, and http proxies (for either http or https with CONNECT).
// Transport can also cache connections for future re-use.
type Transport struct {
lk sync.Mutex
idleConn map[string][]*persistConn
altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
// TODO: tunable on global max cached connections
// TODO: tunable on timeout on cached connections
// TODO: optional pipelining
// Proxy specifies a function to return a proxy for a given
// Request. If the function returns a non-nil error, the
// request is aborted with the provided error.
// If Proxy is nil or returns a nil *URL, no proxy is used.
Proxy func(*http.Request) (*url.URL, error)
// Dial specifies the dial function for creating TCP
// connections.
// If Dial is nil, net.Dial is used.
Dial func(net, addr string) (c net.Conn, err error)
// TLSClientConfig specifies the TLS configuration to use with
// tls.Client. If nil, the default configuration is used.
TLSClientConfig *tls.Config
DisableKeepAlives bool
DisableCompression bool
// MaxIdleConnsPerHost, if non-zero, controls the maximum idle
// (keep-alive) to keep to keep per-host. If zero,
// DefaultMaxIdleConnsPerHost is used.
MaxIdleConnsPerHost int
}
// ProxyFromEnvironment returns the URL of the proxy to use for a
// given request, as indicated by the environment variables
// $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy).
// An error is returned if the proxy environment is invalid.
// A nil URL and nil error are returned if no proxy is defined in the
// environment, or a proxy should not be used for the given request.
func ProxyFromEnvironment(req *http.Request) (*url.URL, error) {
proxy := getenvEitherCase("HTTP_PROXY")
if proxy == "" {
return nil, nil
}
if !useProxy(canonicalAddr(req.URL)) {
return nil, nil
}
proxyURL, err := url.Parse(proxy)
if err != nil || proxyURL.Scheme == "" {
if u, err := url.Parse("http://" + proxy); err == nil {
proxyURL = u
err = nil
}
}
if err != nil {
return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
}
return proxyURL, nil
}
// ProxyURL returns a proxy function (for use in a Transport)
// that always returns the same URL.
func ProxyURL(fixedURL *url.URL) func(*http.Request) (*url.URL, error) {
return func(*http.Request) (*url.URL, error) {
return fixedURL, nil
}
}
// transportRequest is a wrapper around a *Request that adds
// optional extra headers to write.
type transportRequest struct {
*http.Request // original request, not to be mutated
extra http.Header // extra headers to write, or nil
}
func (tr *transportRequest) extraHeaders() http.Header {
if tr.extra == nil {
tr.extra = make(http.Header)
}
return tr.extra
}
type RoundTripDetails struct {
Host string
TCPAddr *net.TCPAddr
IsProxy bool
Error error
}
func (t *Transport) DetailedRoundTrip(req *http.Request) (details *RoundTripDetails, resp *http.Response, err error) {
if req.URL == nil {
return nil, nil, errors.New("http: nil Request.URL")
}
if req.Header == nil {
return nil, nil, errors.New("http: nil Request.Header")
}
if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
t.lk.Lock()
var rt RoundTripper
if t.altProto != nil {
rt = t.altProto[req.URL.Scheme]
}
t.lk.Unlock()
if rt == nil {
return nil, nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
}
return rt.DetailedRoundTrip(req)
}
treq := &transportRequest{Request: req}
cm, err := t.connectMethodForRequest(treq)
if err != nil {
return nil, nil, err
}
// Get the cached or newly-created connection to either the
// host (for http or https), the http proxy, or the http proxy
// pre-CONNECTed to https server. In any case, we'll be ready
// to send it requests.
pconn, err := t.getConn(cm)
if err != nil {
return nil, nil, err
}
resp, err = pconn.roundTrip(treq)
return &RoundTripDetails{pconn.host, pconn.ip, pconn.isProxy, err}, resp, err
}
// RoundTrip implements the RoundTripper interface.
func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
_, resp, err = t.DetailedRoundTrip(req)
return
}
// RegisterProtocol registers a new protocol with scheme.
// The Transport will pass requests using the given scheme to rt.
// It is rt's responsibility to simulate HTTP request semantics.
//
// RegisterProtocol can be used by other packages to provide
// implementations of protocol schemes like "ftp" or "file".
func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
if scheme == "http" || scheme == "https" {
panic("protocol " + scheme + " already registered")
}
t.lk.Lock()
defer t.lk.Unlock()
if t.altProto == nil {
t.altProto = make(map[string]RoundTripper)
}
if _, exists := t.altProto[scheme]; exists {
panic("protocol " + scheme + " already registered")
}
t.altProto[scheme] = rt
}
// CloseIdleConnections closes any connections which were previously
// connected from previous requests but are now sitting idle in
// a "keep-alive" state. It does not interrupt any connections currently
// in use.
func (t *Transport) CloseIdleConnections() {
t.lk.Lock()
defer t.lk.Unlock()
if t.idleConn == nil {
return
}
for _, conns := range t.idleConn {
for _, pconn := range conns {
pconn.close()
}
}
t.idleConn = make(map[string][]*persistConn)
}
//
// Private implementation past this point.
//
func getenvEitherCase(k string) string {
if v := os.Getenv(strings.ToUpper(k)); v != "" {
return v
}
return os.Getenv(strings.ToLower(k))
}
func (t *Transport) connectMethodForRequest(treq *transportRequest) (*connectMethod, error) {
cm := &connectMethod{
targetScheme: treq.URL.Scheme,
targetAddr: canonicalAddr(treq.URL),
}
if t.Proxy != nil {
var err error
cm.proxyURL, err = t.Proxy(treq.Request)
if err != nil {
return nil, err
}
}
return cm, nil
}
// proxyAuth returns the Proxy-Authorization header to set
// on requests, if applicable.
func (cm *connectMethod) proxyAuth() string {
if cm.proxyURL == nil {
return ""
}
if u := cm.proxyURL.User; u != nil {
return "Basic " + base64.URLEncoding.EncodeToString([]byte(u.String()))
}
return ""
}
// putIdleConn adds pconn to the list of idle persistent connections awaiting
// a new request.
// If pconn is no longer needed or not in a good state, putIdleConn
// returns false.
func (t *Transport) putIdleConn(pconn *persistConn) bool {
t.lk.Lock()
defer t.lk.Unlock()
if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
pconn.close()
return false
}
if pconn.isBroken() {
return false
}
key := pconn.cacheKey
max := t.MaxIdleConnsPerHost
if max == 0 {
max = DefaultMaxIdleConnsPerHost
}
if len(t.idleConn[key]) >= max {
pconn.close()
return false
}
t.idleConn[key] = append(t.idleConn[key], pconn)
return true
}
func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
t.lk.Lock()
defer t.lk.Unlock()
if t.idleConn == nil {
t.idleConn = make(map[string][]*persistConn)
}
key := cm.String()
for {
pconns, ok := t.idleConn[key]
if !ok {
return nil
}
if len(pconns) == 1 {
pconn = pconns[0]
delete(t.idleConn, key)
} else {
// 2 or more cached connections; pop last
// TODO: queue?
pconn = pconns[len(pconns)-1]
t.idleConn[key] = pconns[0 : len(pconns)-1]
}
if !pconn.isBroken() {
return
}
}
return
}
func (t *Transport) dial(network, addr string) (c net.Conn, raddr string, ip *net.TCPAddr, err error) {
if t.Dial != nil {
ip, err = net.ResolveTCPAddr("tcp", addr)
if err!=nil {
return
}
c, err = t.Dial(network, addr)
raddr = addr
return
}
addri, err := net.ResolveTCPAddr("tcp", addr)
if err!=nil {
return
}
c, err = net.DialTCP("tcp", nil, addri)
raddr = addr
ip = addri
return
}
// getConn dials and creates a new persistConn to the target as
// specified in the connectMethod. This includes doing a proxy CONNECT
// and/or setting up TLS. If this doesn't return an error, the persistConn
// is ready to write requests to.
func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
if pc := t.getIdleConn(cm); pc != nil {
return pc, nil
}
conn, raddr, ip, err := t.dial("tcp", cm.addr())
if err != nil {
if cm.proxyURL != nil {
err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err)
}
return nil, err
}
pa := cm.proxyAuth()
pconn := &persistConn{
t: t,
cacheKey: cm.String(),
conn: conn,
reqch: make(chan requestAndChan, 50),
host: raddr,
ip: ip,
}
switch {
case cm.proxyURL == nil:
// Do nothing.
case cm.targetScheme == "http":
pconn.isProxy = true
if pa != "" {
pconn.mutateHeaderFunc = func(h http.Header) {
h.Set("Proxy-Authorization", pa)
}
}
case cm.targetScheme == "https":
connectReq := &http.Request{
Method: "CONNECT",
URL: &url.URL{Opaque: cm.targetAddr},
Host: cm.targetAddr,
Header: make(http.Header),
}
if pa != "" {
connectReq.Header.Set("Proxy-Authorization", pa)
}
connectReq.Write(conn)
// Read response.
// Okay to use and discard buffered reader here, because
// TLS server will not speak until spoken to.
br := bufio.NewReader(conn)
resp, err := http.ReadResponse(br, connectReq)
if err != nil {
conn.Close()
return nil, err
}
if resp.StatusCode != 200 {
f := strings.SplitN(resp.Status, " ", 2)
conn.Close()
return nil, errors.New(f[1])
}
}
if cm.targetScheme == "https" {
// Initiate TLS and check remote host name against certificate.
conn = tls.Client(conn, t.TLSClientConfig)
if err = conn.(*tls.Conn).Handshake(); err != nil {
return nil, err
}
if t.TLSClientConfig == nil || !t.TLSClientConfig.InsecureSkipVerify {
if err = conn.(*tls.Conn).VerifyHostname(cm.tlsHost()); err != nil {
return nil, err
}
}
pconn.conn = conn
}
pconn.br = bufio.NewReader(pconn.conn)
pconn.bw = bufio.NewWriter(pconn.conn)
go pconn.readLoop()
return pconn, nil
}
// useProxy returns true if requests to addr should use a proxy,
// according to the NO_PROXY or no_proxy environment variable.
// addr is always a canonicalAddr with a host and port.
func useProxy(addr string) bool {
if len(addr) == 0 {
return true
}
host, _, err := net.SplitHostPort(addr)
if err != nil {
return false
}
if host == "localhost" {
return false
}
if ip := net.ParseIP(host); ip != nil {
if ip.IsLoopback() {
return false
}
}
no_proxy := getenvEitherCase("NO_PROXY")
if no_proxy == "*" {
return false
}
addr = strings.ToLower(strings.TrimSpace(addr))
if hasPort(addr) {
addr = addr[:strings.LastIndex(addr, ":")]
}
for _, p := range strings.Split(no_proxy, ",") {
p = strings.ToLower(strings.TrimSpace(p))
if len(p) == 0 {
continue
}
if hasPort(p) {
p = p[:strings.LastIndex(p, ":")]
}
if addr == p || (p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:])) {
return false
}
}
return true
}
// connectMethod is the map key (in its String form) for keeping persistent
// TCP connections alive for subsequent HTTP requests.
//
// A connect method may be of the following types:
//
// Cache key form Description
// ----------------- -------------------------
// ||http|foo.com http directly to server, no proxy
// ||https|foo.com https directly to server, no proxy
// http://proxy.com|https|foo.com http to proxy, then CONNECT to foo.com
// http://proxy.com|http http to proxy, http to anywhere after that
//
// Note: no support to https to the proxy yet.
//
type connectMethod struct {
proxyURL *url.URL // nil for no proxy, else full proxy URL
targetScheme string // "http" or "https"
targetAddr string // Not used if proxy + http targetScheme (4th example in table)
}
func (ck *connectMethod) String() string {
proxyStr := ""
if ck.proxyURL != nil {
proxyStr = ck.proxyURL.String()
}
return strings.Join([]string{proxyStr, ck.targetScheme, ck.targetAddr}, "|")
}
// addr returns the first hop "host:port" to which we need to TCP connect.
func (cm *connectMethod) addr() string {
if cm.proxyURL != nil {
return canonicalAddr(cm.proxyURL)
}
return cm.targetAddr
}
// tlsHost returns the host name to match against the peer's
// TLS certificate.
func (cm *connectMethod) tlsHost() string {
h := cm.targetAddr
if hasPort(h) {
h = h[:strings.LastIndex(h, ":")]
}
return h
}
// persistConn wraps a connection, usually a persistent one
// (but may be used for non-keep-alive requests as well)
type persistConn struct {
t *Transport
cacheKey string // its connectMethod.String()
conn net.Conn
br *bufio.Reader // from conn
bw *bufio.Writer // to conn
reqch chan requestAndChan // written by roundTrip(); read by readLoop()
isProxy bool
// mutateHeaderFunc is an optional func to modify extra
// headers on each outbound request before it's written. (the
// original Request given to RoundTrip is not modified)
mutateHeaderFunc func(http.Header)
lk sync.Mutex // guards numExpectedResponses and broken
numExpectedResponses int
broken bool // an error has happened on this connection; marked broken so it's not reused.
host string
ip *net.TCPAddr
}
func (pc *persistConn) isBroken() bool {
pc.lk.Lock()
defer pc.lk.Unlock()
return pc.broken
}
var remoteSideClosedFunc func(error) bool // or nil to use default
func remoteSideClosed(err error) bool {
if err == io.EOF {
return true
}
if remoteSideClosedFunc != nil {
return remoteSideClosedFunc(err)
}
return false
}
func (pc *persistConn) readLoop() {
alive := true
var lastbody io.ReadCloser // last response body, if any, read on this connection
for alive {
pb, err := pc.br.Peek(1)
pc.lk.Lock()
if pc.numExpectedResponses == 0 {
pc.closeLocked()
pc.lk.Unlock()
if len(pb) > 0 {
log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
string(pb), err)
}
return
}
pc.lk.Unlock()
rc := <-pc.reqch
// Advance past the previous response's body, if the
// caller hasn't done so.
if lastbody != nil {
lastbody.Close() // assumed idempotent
lastbody = nil
}
resp, err := http.ReadResponse(pc.br, rc.req)
if err != nil {
pc.close()
} else {
hasBody := rc.req.Method != "HEAD" && resp.ContentLength != 0
if rc.addedGzip && hasBody && resp.Header.Get("Content-Encoding") == "gzip" {
resp.Header.Del("Content-Encoding")
resp.Header.Del("Content-Length")
resp.ContentLength = -1
gzReader, zerr := gzip.NewReader(resp.Body)
if zerr != nil {
pc.close()
err = zerr
} else {
resp.Body = &readFirstCloseBoth{&discardOnCloseReadCloser{gzReader}, resp.Body}
}
}
resp.Body = &bodyEOFSignal{body: resp.Body}
}
if err != nil || resp.Close || rc.req.Close {
alive = false
}
hasBody := resp != nil && resp.ContentLength != 0
var waitForBodyRead chan bool
if alive {
if hasBody {
lastbody = resp.Body
waitForBodyRead = make(chan bool)
resp.Body.(*bodyEOFSignal).fn = func() {
if !pc.t.putIdleConn(pc) {
alive = false
}
waitForBodyRead <- true
}
} else {
// When there's no response body, we immediately
// reuse the TCP connection (putIdleConn), but
// we need to prevent ClientConn.Read from
// closing the Response.Body on the next
// loop, otherwise it might close the body
// before the client code has had a chance to
// read it (even though it'll just be 0, EOF).
lastbody = nil
if !pc.t.putIdleConn(pc) {
alive = false
}
}
}
rc.ch <- responseAndError{resp, err}
// Wait for the just-returned response body to be fully consumed
// before we race and peek on the underlying bufio reader.
if waitForBodyRead != nil {
<-waitForBodyRead
}
}
}
type responseAndError struct {
res *http.Response
err error
}
type requestAndChan struct {
req *http.Request
ch chan responseAndError
// did the Transport (as opposed to the client code) add an
// Accept-Encoding gzip header? only if it we set it do
// we transparently decode the gzip.
addedGzip bool
}
func (pc *persistConn) roundTrip(req *transportRequest) (resp *http.Response, err error) {
if pc.mutateHeaderFunc != nil {
panic("mutateHeaderFunc not supported in modified Transport")
pc.mutateHeaderFunc(req.extraHeaders())
}
// Ask for a compressed version if the caller didn't set their
// own value for Accept-Encoding. We only attempted to
// uncompress the gzip stream if we were the layer that
// requested it.
requestedGzip := false
if !pc.t.DisableCompression && req.Header.Get("Accept-Encoding") == "" {
// Request gzip only, not deflate. Deflate is ambiguous and
// not as universally supported anyway.
// See: http://www.gzip.org/zlib/zlib_faq.html#faq38
requestedGzip = true
req.extraHeaders().Set("Accept-Encoding", "gzip")
}
pc.lk.Lock()
pc.numExpectedResponses++
pc.lk.Unlock()
// orig: err = req.Request.write(pc.bw, pc.isProxy, req.extra)
if pc.isProxy {
err = req.Request.WriteProxy(pc.bw)
} else {
err = req.Request.Write(pc.bw)
}
if err != nil {
pc.close()
return
}
pc.bw.Flush()
ch := make(chan responseAndError, 1)
pc.reqch <- requestAndChan{req.Request, ch, requestedGzip}
re := <-ch
pc.lk.Lock()
pc.numExpectedResponses--
pc.lk.Unlock()
return re.res, re.err
}
func (pc *persistConn) close() {
pc.lk.Lock()
defer pc.lk.Unlock()
pc.closeLocked()
}
func (pc *persistConn) closeLocked() {
pc.broken = true
pc.conn.Close()
pc.mutateHeaderFunc = nil
}
var portMap = map[string]string{
"http": "80",
"https": "443",
}
// canonicalAddr returns url.Host but always with a ":port" suffix
func canonicalAddr(url *url.URL) string {
addr := url.Host
if !hasPort(addr) {
return addr + ":" + portMap[url.Scheme]
}
return addr
}
func responseIsKeepAlive(res *http.Response) bool {
// TODO: implement. for now just always shutting down the connection.
return false
}
// bodyEOFSignal wraps a ReadCloser but runs fn (if non-nil) at most
// once, right before the final Read() or Close() call returns, but after
// EOF has been seen.
type bodyEOFSignal struct {
body io.ReadCloser
fn func()
isClosed bool
}
func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
n, err = es.body.Read(p)
if es.isClosed && n > 0 {
panic("http: unexpected bodyEOFSignal Read after Close; see issue 1725")
}
if err == io.EOF && es.fn != nil {
es.fn()
es.fn = nil
}
return
}
func (es *bodyEOFSignal) Close() (err error) {
if es.isClosed {
return nil
}
es.isClosed = true
err = es.body.Close()
if err == nil && es.fn != nil {
es.fn()
es.fn = nil
}
return
}
type readFirstCloseBoth struct {
io.ReadCloser
io.Closer
}
func (r *readFirstCloseBoth) Close() error {
if err := r.ReadCloser.Close(); err != nil {
r.Closer.Close()
return err
}
if err := r.Closer.Close(); err != nil {
return err
}
return nil
}
// discardOnCloseReadCloser consumes all its input on Close.
type discardOnCloseReadCloser struct {
io.ReadCloser
}
func (d *discardOnCloseReadCloser) Close() error {
io.Copy(ioutil.Discard, d.ReadCloser) // ignore errors; likely invalid or already closed
return d.ReadCloser.Close()
}

View File

@@ -1,15 +0,0 @@
package transport
import (
"fmt"
"strings"
)
type badStringError struct {
what string
str string
}
func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }