Esempio n. 1
0
func main() {
	manager, err := golongpoll.StartLongpoll(golongpoll.Options{
		LoggingEnabled: true,
		// NOTE: if not defined here, other options have reasonable defaults,
		// so no need specifying options you don't care about
	})
	if err != nil {
		log.Fatalf("Failed to create manager: %q", err)
	}
	// pump out random events
	go generateRandomEvents(manager)
	// Serve our basic example driver webpage
	http.HandleFunc("/basic", BasicExampleHomepage)

	// Serve our event subscription web handler
	http.HandleFunc("/basic/events", manager.SubscriptionHandler)

	fmt.Println("Serving webpage at http://127.0.0.1:8081/basic")
	http.ListenAndServe("127.0.0.1:8081", nil)

	// We'll never get here as long as http.ListenAndServe starts successfully
	// because it runs until you kill the program (like pressing Control-C)
	// Buf if you make a stoppable http server, or want to shut down the
	// internal longpoll manager for other reasons, you can do so via
	// Shutdown:
	manager.Shutdown() // Stops the internal goroutine that provides subscription behavior
	// Again, calling shutdown is a bit silly here since the goroutines will
	// exit on main() exit.  But I wanted to show you that it is possible.
}
Esempio n. 2
0
func main() {
	manager, err := golongpoll.StartLongpoll(golongpoll.Options{
		LoggingEnabled:                 true,
		MaxLongpollTimeoutSeconds:      120,
		MaxEventBufferSize:             100,
		EventTimeToLiveSeconds:         60 * 2, // Event's stick around for 2 minutes
		DeleteEventAfterFirstRetrieval: false,
	})
	if err != nil {
		log.Fatalf("Failed to create manager: %q", err)
	}
	// Serve our example driver webpage
	http.HandleFunc("/advanced", AdvancedExampleHomepage)
	// Serve handler that generates events
	http.HandleFunc("/advanced/user/action", getUserActionHandler(manager))
	// Serve handler that subscribes to events.
	http.HandleFunc("/advanced/events", getEventSubscriptionHandler(manager))
	// Start webserver
	fmt.Println("Serving webpage at http://127.0.0.1:8081/advanced")
	http.ListenAndServe("127.0.0.1:8081", nil)

	// We'll never get here as long as http.ListenAndServe starts successfully
	// because it runs until you kill the program (like pressing Control-C)
	// Buf if you make a stoppable http server, or want to shut down the
	// internal longpoll manager for other reasons, you can do so via
	// Shutdown:
	manager.Shutdown() // Stops the internal goroutine that provides subscription behavior
	// Again, calling shutdown is a bit silly here since the goroutines will
	// exit on main() exit.  But I wanted to show you that it is possible.
}
Esempio n. 3
0
func CreateProxy(whiteList, blackList []*regexp.Regexp, verbose bool,
	whiteListUpdates, blackListUpdates chan string) (*goproxy.ProxyHttpServer, error) {
	// Start longpoll subscription manager
	longpollManager, lpErr := golongpoll.StartLongpoll(
		golongpoll.Options{
			LoggingEnabled:                 false,
			MaxLongpollTimeoutSeconds:      120,
			MaxEventBufferSize:             1000,
			EventTimeToLiveSeconds:         240,
			DeleteEventAfterFirstRetrieval: false,
		})
	if lpErr != nil {
		log.Fatalf("Error creating longpoll manager: %v", lpErr)
	}
	// Create and start control server for controlling proxy behavior
	ctlServer := controls.NewControlServer(vars.ProxyControlPort, longpollManager.SubscriptionHandler, whiteListUpdates, blackListUpdates)
	ctlServer.Serve()

	// Manually allowed/blocked sites:
	manualWhiteList := make(map[string]bool)
	manualBlackList := make(map[string]bool)

	// Create and start our content blocking proxy:
	proxy := goproxy.NewProxyHttpServer()
	proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)
	proxy.OnRequest().DoFunc(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
		// Prevent upgrades to https so we can easily see everything as plain
		if req.URL.Scheme == "https" {
			req.URL.Scheme = "http"
		}
		urlString := req.URL.String()

		// Check for any updates to our whitelist/blacklist values
		checkWhiteBlackListUpdates(manualWhiteList, manualBlackList,
			whiteListUpdates, blackListUpdates)

		// Now apply whitelist/blacklist rules:
		for _, w := range whiteList {
			if w.MatchString(urlString) {
				// whitelisted by rules, but was this specific URL blacklisted
				// by user?
				if _, ok := manualBlackList[strings.TrimSpace(urlString)]; ok {
					// stop trying to find whitelist matches
					log.Printf("user-DENIED whitelisting:  %s\n", req.URL)
					break
				} else {
					log.Printf("WHITELISTED:  %s\n", req.URL)
					notifyProxyEvent("Allowed", req, longpollManager)
					return req, nil
				}
			}
		}
		// Check if this was explicitly whitelisted by user:
		if _, ok := manualWhiteList[strings.TrimSpace(urlString)]; ok {
			// no need to consider blacklists, serve content
			log.Printf("user-eplicit WHITELISTED:  %s\n", req.URL)
			notifyProxyEvent("Allowed", req, longpollManager)
			return req, nil
		}

		// See if we're manually allowing this page thru on time only
		if strings.HasSuffix(urlString, vars.ProxyExceptionString) {
			urlString := urlString[:len(urlString)-len(vars.ProxyExceptionString)]
			u, uErr := url.Parse(urlString)
			if uErr == nil {
				req.URL = u
				log.Printf("MANUALLY ALLOWED: %s\n", req.URL)
				notifyProxyEvent("Manually Allowed", req, longpollManager)
				return req, nil
			} else {
				log.Printf("ERROR trying to rewrite URL. Url: %s, Error: %s", urlString, uErr)
				return req, goproxy.NewResponse(req,
					goproxy.ContentTypeHtml, http.StatusForbidden,
					fmt.Sprintf(`<html>
                            <head><title>BAD URL</title></head>
                            <body>
                                <h1>Ehhh.... wut?</h1>
                                <hr />
                                <h2>Error rewriting URL:</h2>
                                <p style="color: black; font-family: monospace; background: #DDDDDD; padding: 20px;">%s</p>
                                <p>Error:</p>
                                <p style="color: red; font-family: monospace; background: #DDDDDD; padding: 20px;">%s</p>
                            </body>
                        </html>`, urlString, uErr))
			}
		}
		for _, b := range blackList {
			if b.MatchString(urlString) {
				log.Printf("BLACKLISTED:  %s\n", req.URL)
				notifyProxyEvent("Blocked", req, longpollManager)
				return req, goproxy.NewResponse(req,
					goproxy.ContentTypeHtml, http.StatusForbidden,
					fmt.Sprintf(`<html>
                            <head><title>BLOCKED</title></head>
                            <body>
                                <h1>I pity the fool!</h1>
                                <hr />
                                <h2>Webpage Blocked</h2>
                                <p style="color: black; font-family: monospace; background: #DDDDDD; padding: 20px;">%s</p>
                                <p><a href="%s%s">Continue to Webpage just this once.</a></p>
                                <p>or...</p>
                                <p><a href="http://127.0.0.1:%s/add-wl?url=%s&continue_to_page=yes">Add to Whitelist and continue.</a></p>
                            </body>
                        </html>`, req.URL, req.URL, vars.ProxyExceptionString,
						vars.ProxyControlPort, url.QueryEscape(req.URL.String())))
			}
		}
		log.Printf("NOT MATCHED: (allow by default) %s\n", req.URL)
		notifyProxyEvent("Not matched, default allowed", req, longpollManager)
		return req, nil
	})

	proxy.OnResponse(goproxy_html.IsHtml).Do(goproxy_html.HandleString(
		func(s string, ctx *goproxy.ProxyCtx) string {
			if strings.HasPrefix(ctx.Req.URL.Host, "http://127.0.0.1:") ||
				strings.HasPrefix(ctx.Req.URL.Host, "http://127.0.0.1/") ||
				strings.HasPrefix(ctx.Req.URL.Host, "127.0.0.1/") ||
				strings.HasPrefix(ctx.Req.URL.Host, "127.0.0.1:") {
				// Don't inject on our own content.
				// TODO: move this logic next to IsHtml so this func
				return s
			}
			// Don't inject iframe into responses that aren't successful
			// ie 2xx response codes.
			// Mainly this is to avoid injecting on our own block page,
			// but it probably doesn't make sense for other failed pages either
			if ctx.Resp.StatusCode < 200 || ctx.Resp.StatusCode >= 300 {
				// show page as-is
				// remember: blocking content is already enforced by this point,
				return s
			}
			match := vars.StartBodyTagMatcher.FindIndex([]byte(s))
			if match != nil && len(match) >= 2 {
				// TODO: make this more efficient by using a stream or some sort
				// of stringbuilder like thing that doesn't require mashing
				// giant strings together.
				return s[:match[1]] +
					// TODO: should this script get injected after the iframe to prevent a potential race condition?
					getParentControlScript() +
					"<div id=\"proxyblock-glass-overlay\" onclick=\"glassClose(this);\" style=\"position: fixed; top: 0; right: 0; left: 0; bottom: 0; background: #000000; opacity: 0.3; z-index: 99999998; display: none;\"></div>" +
					"<div id=\"proxyblock-controls\" style=\"position: fixed; height: 42px; width: 230px; top: 4px; right: 8px; z-index: 99999999;\">" +
					"<iframe id=\"proxyblock-frame\" scrolling=\"no\" style=\"overflow: hidden; background-color: #FFFFFF; border: 2px solid black; width: 100%; height: 100%;\" " +
					"src=\"http://127.0.0.1:" + vars.ProxyControlPort + pagecontrols.GetPageControlsUrl(ctx.Req.URL.String()) +
					"\"></iframe>" +
					"</div>" +
					s[match[1]:]
			} else {
				log.Printf("WARNING: No starting body tag found, must not be html, no injection.")
				return s
			}
		}))
	proxy.Verbose = verbose
	return proxy, nil
}