[tor-commits] [snowflake/main] Move http handlers to a separate file

arlo at torproject.org arlo at torproject.org
Thu Jul 8 19:44:16 UTC 2021


commit 0ced1cc32497f3b47a614ef4a526af7925447252
Author: Arlo Breault <abreault at wikimedia.org>
Date:   Thu May 20 08:31:30 2021 -0400

    Move http handlers to a separate file
---
 broker/broker.go | 196 ----------------------------------------------------
 broker/http.go   | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 205 insertions(+), 196 deletions(-)

diff --git a/broker/broker.go b/broker/broker.go
index 58f3955..437a4d1 100644
--- a/broker/broker.go
+++ b/broker/broker.go
@@ -8,10 +8,8 @@ package main
 import (
 	"container/heap"
 	"crypto/tls"
-	"errors"
 	"flag"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
@@ -21,17 +19,12 @@ import (
 	"syscall"
 	"time"
 
-	"git.torproject.org/pluggable-transports/snowflake.git/common/messages"
 	"git.torproject.org/pluggable-transports/snowflake.git/common/safelog"
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
 	"golang.org/x/crypto/acme/autocert"
 )
 
-const (
-	readLimit = 100000 // Maximum number of bytes to be read from an HTTP request
-)
-
 type BrokerContext struct {
 	snowflakes           *SnowflakeHeap
 	restrictedSnowflakes *SnowflakeHeap
@@ -69,38 +62,6 @@ func NewBrokerContext(metricsLogger *log.Logger) *BrokerContext {
 	}
 }
 
-// Implements the http.Handler interface
-type SnowflakeHandler struct {
-	*IPC
-	handle func(*IPC, http.ResponseWriter, *http.Request)
-}
-
-// Implements the http.Handler interface
-type MetricsHandler struct {
-	logFilename string
-	handle      func(string, http.ResponseWriter, *http.Request)
-}
-
-func (sh SnowflakeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Access-Control-Allow-Origin", "*")
-	w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Session-ID")
-	// Return early if it's CORS preflight.
-	if "OPTIONS" == r.Method {
-		return
-	}
-	sh.handle(sh.IPC, w, r)
-}
-
-func (mh MetricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Access-Control-Allow-Origin", "*")
-	w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Session-ID")
-	// Return early if it's CORS preflight.
-	if "OPTIONS" == r.Method {
-		return
-	}
-	mh.handle(mh.logFilename, w, r)
-}
-
 // Proxies may poll for client offers concurrently.
 type ProxyPoll struct {
 	id           string
@@ -178,169 +139,12 @@ func (ctx *BrokerContext) AddSnowflake(id string, proxyType string, natType stri
 	return snowflake
 }
 
-/*
-For snowflake proxies to request a client from the Broker.
-*/
-func proxyPolls(i *IPC, w http.ResponseWriter, r *http.Request) {
-	body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, readLimit))
-	if err != nil {
-		log.Println("Invalid data.")
-		w.WriteHeader(http.StatusBadRequest)
-		return
-	}
-
-	arg := messages.Arg{
-		Body:       body,
-		RemoteAddr: r.RemoteAddr,
-		NatType:    "",
-	}
-
-	var response []byte
-	err = i.ProxyPolls(arg, &response)
-	switch {
-	case err == nil:
-	case errors.Is(err, messages.ErrBadRequest):
-		w.WriteHeader(http.StatusBadRequest)
-		return
-	case errors.Is(err, messages.ErrInternal):
-		fallthrough
-	default:
-		log.Println(err)
-		w.WriteHeader(http.StatusInternalServerError)
-		return
-	}
-
-	if _, err := w.Write(response); err != nil {
-		log.Printf("proxyPolls unable to write offer with error: %v", err)
-	}
-}
-
 // Client offer contains an SDP and the NAT type of the client
 type ClientOffer struct {
 	natType string
 	sdp     []byte
 }
 
-/*
-Expects a WebRTC SDP offer in the Request to give to an assigned
-snowflake proxy, which responds with the SDP answer to be sent in
-the HTTP response back to the client.
-*/
-func clientOffers(i *IPC, w http.ResponseWriter, r *http.Request) {
-	body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, readLimit))
-	if err != nil {
-		log.Printf("Error reading client request: %s", err.Error())
-		w.WriteHeader(http.StatusBadRequest)
-		return
-	}
-
-	arg := messages.Arg{
-		Body:       body,
-		RemoteAddr: "",
-		NatType:    r.Header.Get("Snowflake-NAT-Type"),
-	}
-
-	var response []byte
-	err = i.ClientOffers(arg, &response)
-	switch {
-	case err == nil:
-	case errors.Is(err, messages.ErrUnavailable):
-		w.WriteHeader(http.StatusServiceUnavailable)
-		return
-	case errors.Is(err, messages.ErrTimeout):
-		w.WriteHeader(http.StatusGatewayTimeout)
-		return
-	default:
-		log.Println(err)
-		w.WriteHeader(http.StatusInternalServerError)
-		return
-	}
-
-	if _, err := w.Write(response); err != nil {
-		log.Printf("clientOffers unable to write answer with error: %v", err)
-	}
-}
-
-/*
-Expects snowflake proxes which have previously successfully received
-an offer from proxyHandler to respond with an answer in an HTTP POST,
-which the broker will pass back to the original client.
-*/
-func proxyAnswers(i *IPC, w http.ResponseWriter, r *http.Request) {
-	body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, readLimit))
-	if err != nil {
-		log.Println("Invalid data.")
-		w.WriteHeader(http.StatusBadRequest)
-		return
-	}
-
-	arg := messages.Arg{
-		Body:       body,
-		RemoteAddr: "",
-		NatType:    "",
-	}
-
-	var response []byte
-	err = i.ProxyAnswers(arg, &response)
-	switch {
-	case err == nil:
-	case errors.Is(err, messages.ErrBadRequest):
-		w.WriteHeader(http.StatusBadRequest)
-		return
-	case errors.Is(err, messages.ErrInternal):
-		fallthrough
-	default:
-		log.Println(err)
-		w.WriteHeader(http.StatusInternalServerError)
-		return
-	}
-
-	if _, err := w.Write(response); err != nil {
-		log.Printf("proxyAnswers unable to write answer response with error: %v", err)
-	}
-}
-
-func debugHandler(i *IPC, w http.ResponseWriter, r *http.Request) {
-	var response string
-
-	err := i.Debug(new(interface{}), &response)
-	if err != nil {
-		log.Println(err)
-		w.WriteHeader(http.StatusInternalServerError)
-		return
-	}
-
-	if _, err := w.Write([]byte(response)); err != nil {
-		log.Printf("writing proxy information returned error: %v ", err)
-	}
-}
-
-func robotsTxtHandler(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-	if _, err := w.Write([]byte("User-agent: *\nDisallow: /\n")); err != nil {
-		log.Printf("robotsTxtHandler unable to write, with this error: %v", err)
-	}
-}
-
-func metricsHandler(metricsFilename string, w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-
-	if metricsFilename == "" {
-		http.NotFound(w, r)
-		return
-	}
-	metricsFile, err := os.OpenFile(metricsFilename, os.O_RDONLY, 0644)
-	if err != nil {
-		log.Println("Error opening metrics file for reading")
-		http.NotFound(w, r)
-		return
-	}
-
-	if _, err := io.Copy(w, metricsFile); err != nil {
-		log.Printf("copying metricsFile returned error: %v", err)
-	}
-}
-
 func main() {
 	var acmeEmail string
 	var acmeHostnamesCommas string
diff --git a/broker/http.go b/broker/http.go
new file mode 100644
index 0000000..6555d7a
--- /dev/null
+++ b/broker/http.go
@@ -0,0 +1,205 @@
+package main
+
+import (
+	"errors"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"os"
+
+	"git.torproject.org/pluggable-transports/snowflake.git/common/messages"
+)
+
+const (
+	readLimit = 100000 // Maximum number of bytes to be read from an HTTP request
+)
+
+// Implements the http.Handler interface
+type SnowflakeHandler struct {
+	*IPC
+	handle func(*IPC, http.ResponseWriter, *http.Request)
+}
+
+func (sh SnowflakeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Access-Control-Allow-Origin", "*")
+	w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Session-ID")
+	// Return early if it's CORS preflight.
+	if "OPTIONS" == r.Method {
+		return
+	}
+	sh.handle(sh.IPC, w, r)
+}
+
+// Implements the http.Handler interface
+type MetricsHandler struct {
+	logFilename string
+	handle      func(string, http.ResponseWriter, *http.Request)
+}
+
+func (mh MetricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Access-Control-Allow-Origin", "*")
+	w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Session-ID")
+	// Return early if it's CORS preflight.
+	if "OPTIONS" == r.Method {
+		return
+	}
+	mh.handle(mh.logFilename, w, r)
+}
+
+func robotsTxtHandler(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	if _, err := w.Write([]byte("User-agent: *\nDisallow: /\n")); err != nil {
+		log.Printf("robotsTxtHandler unable to write, with this error: %v", err)
+	}
+}
+
+func metricsHandler(metricsFilename string, w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+
+	if metricsFilename == "" {
+		http.NotFound(w, r)
+		return
+	}
+	metricsFile, err := os.OpenFile(metricsFilename, os.O_RDONLY, 0644)
+	if err != nil {
+		log.Println("Error opening metrics file for reading")
+		http.NotFound(w, r)
+		return
+	}
+
+	if _, err := io.Copy(w, metricsFile); err != nil {
+		log.Printf("copying metricsFile returned error: %v", err)
+	}
+}
+
+func debugHandler(i *IPC, w http.ResponseWriter, r *http.Request) {
+	var response string
+
+	err := i.Debug(new(interface{}), &response)
+	if err != nil {
+		log.Println(err)
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	if _, err := w.Write([]byte(response)); err != nil {
+		log.Printf("writing proxy information returned error: %v ", err)
+	}
+}
+
+/*
+For snowflake proxies to request a client from the Broker.
+*/
+func proxyPolls(i *IPC, w http.ResponseWriter, r *http.Request) {
+	body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, readLimit))
+	if err != nil {
+		log.Println("Invalid data.")
+		w.WriteHeader(http.StatusBadRequest)
+		return
+	}
+
+	arg := messages.Arg{
+		Body:       body,
+		RemoteAddr: r.RemoteAddr,
+		NatType:    "",
+	}
+
+	var response []byte
+	err = i.ProxyPolls(arg, &response)
+	switch {
+	case err == nil:
+	case errors.Is(err, messages.ErrBadRequest):
+		w.WriteHeader(http.StatusBadRequest)
+		return
+	case errors.Is(err, messages.ErrInternal):
+		fallthrough
+	default:
+		log.Println(err)
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	if _, err := w.Write(response); err != nil {
+		log.Printf("proxyPolls unable to write offer with error: %v", err)
+	}
+}
+
+/*
+Expects a WebRTC SDP offer in the Request to give to an assigned
+snowflake proxy, which responds with the SDP answer to be sent in
+the HTTP response back to the client.
+*/
+func clientOffers(i *IPC, w http.ResponseWriter, r *http.Request) {
+	body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, readLimit))
+	if err != nil {
+		log.Printf("Error reading client request: %s", err.Error())
+		w.WriteHeader(http.StatusBadRequest)
+		return
+	}
+
+	arg := messages.Arg{
+		Body:       body,
+		RemoteAddr: "",
+		NatType:    r.Header.Get("Snowflake-NAT-Type"),
+	}
+
+	var response []byte
+	err = i.ClientOffers(arg, &response)
+	switch {
+	case err == nil:
+	case errors.Is(err, messages.ErrUnavailable):
+		w.WriteHeader(http.StatusServiceUnavailable)
+		return
+	case errors.Is(err, messages.ErrTimeout):
+		w.WriteHeader(http.StatusGatewayTimeout)
+		return
+	default:
+		log.Println(err)
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	if _, err := w.Write(response); err != nil {
+		log.Printf("clientOffers unable to write answer with error: %v", err)
+	}
+}
+
+/*
+Expects snowflake proxes which have previously successfully received
+an offer from proxyHandler to respond with an answer in an HTTP POST,
+which the broker will pass back to the original client.
+*/
+func proxyAnswers(i *IPC, w http.ResponseWriter, r *http.Request) {
+	body, err := ioutil.ReadAll(http.MaxBytesReader(w, r.Body, readLimit))
+	if err != nil {
+		log.Println("Invalid data.")
+		w.WriteHeader(http.StatusBadRequest)
+		return
+	}
+
+	arg := messages.Arg{
+		Body:       body,
+		RemoteAddr: "",
+		NatType:    "",
+	}
+
+	var response []byte
+	err = i.ProxyAnswers(arg, &response)
+	switch {
+	case err == nil:
+	case errors.Is(err, messages.ErrBadRequest):
+		w.WriteHeader(http.StatusBadRequest)
+		return
+	case errors.Is(err, messages.ErrInternal):
+		fallthrough
+	default:
+		log.Println(err)
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	if _, err := w.Write(response); err != nil {
+		log.Printf("proxyAnswers unable to write answer response with error: %v", err)
+	}
+}





More information about the tor-commits mailing list