Files
reseed-tools/reseed/server.go
Matt Drollette a457029b8c https server
2014-12-11 00:05:27 -06:00

90 lines
2.0 KiB
Go

package reseed
import (
"bytes"
"crypto/tls"
"fmt"
"io"
"net/http"
"os"
"github.com/PuerkitoBio/throttled"
"github.com/PuerkitoBio/throttled/store"
"github.com/gorilla/handlers"
"github.com/justinas/alice"
)
const (
I2P_USER_AGENT = "Wget/1.11.4"
)
type Server struct {
*http.Server
Reseeder Reseeder
}
func NewServer() *Server {
config := &tls.Config{MinVersion: tls.VersionTLS10}
h := &http.Server{TLSConfig: config}
server := Server{h, nil}
th := throttled.RateLimit(throttled.PerHour(4), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(10000))
middlewareChain := alice.New(proxiedMiddleware, loggingMiddleware, verifyMiddleware, th.Throttle)
mux := http.NewServeMux()
mux.Handle("/i2pseeds.su3", middlewareChain.Then(http.HandlerFunc(server.reseedHandler)))
server.Handler = mux
return &server
}
func (s *Server) indexHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Index")
}
func (s *Server) reseedHandler(w http.ResponseWriter, r *http.Request) {
peer := s.Reseeder.Peer(r)
seeds, err := s.Reseeder.Seeds(peer)
if nil != err {
http.Error(w, "500 Unable to provide seeds", http.StatusInternalServerError)
return
}
su3, err := s.Reseeder.CreateSu3(seeds)
if nil != err {
http.Error(w, "500 Unable to generate SU3", http.StatusInternalServerError)
return
}
io.Copy(w, bytes.NewReader(su3.Bytes()))
}
func loggingMiddleware(next http.Handler) http.Handler {
return handlers.CombinedLoggingHandler(os.Stdout, next)
}
func verifyMiddleware(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
if I2P_USER_AGENT != r.UserAgent() {
http.Error(w, "403 Forbidden", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
func proxiedMiddleware(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
if prior, ok := r.Header["X-Forwarded-For"]; ok {
r.RemoteAddr = prior[0]
}
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}