Merge pull request #465 from elotreum/custom-routes

http: allow for customized routes
This commit is contained in:
mrd0ll4r 2020-01-18 11:40:37 +01:00 committed by GitHub
commit 85d646d1ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 25 deletions

View file

@ -54,6 +54,22 @@ type QueryParams struct {
infoHashes []InfoHash
}
type routeParamsKey struct{}
// RouteParamsKey is a key for the context of a request that
// contains the named parameters from the http router.
var RouteParamsKey = routeParamsKey{}
// RouteParam is a type that contains the values from the named parameters
// on the route.
type RouteParam struct {
Key string
Value string
}
// RouteParams is a collection of RouteParam instances.
type RouteParams []RouteParam
// ParseURLData parses a request URL or UDP URLData as defined in BEP41.
// It expects a concatenated string of the request's path and query parts as
// defined in RFC 3986. As both the udp: and http: scheme used by BitTorrent

View file

@ -41,15 +41,25 @@ chihaya:
# Disabling this should increase performance/decrease load.
enable_request_timing: false
# Whether to listen on /announce.php and /scrape.php in addition to their
# non-.php counterparts.
# This is an option for compatibility with (very) old clients or otherwise
# outdated systems.
# This might be useful to retracker.local users, for more information see
# http://rutracker.wiki/Оптимизация_обмена_битторрент_траффиком_в_локальных_сетях
# and
# http://rutracker.wiki/Retracker.local
enable_legacy_php_urls: false
# An array of routes to listen on for announce requests. This is an option
# to support trackers that do not listen for /announce or need to listen
# on multiple routes.
#
# This supports named parameters and catch-all parameters as described at
# https://github.com/julienschmidt/httprouter#named-parameters
announce_routes:
- "/announce"
# - "/announce.php"
# An array of routes to listen on for scrape requests. This is an option
# to support trackers that do not listen for /scrape or need to listen
# on multiple routes.
#
# This supports named parameters and catch-all parameters as described at
# https://github.com/julienschmidt/httprouter#named-parameters
scrape_routes:
- "/scrape"
# - "/scrape.php"
# When enabled, the IP address used to connect to the tracker will not
# override the value clients advertise as their IP address.

View file

@ -16,7 +16,10 @@ chihaya:
enable_keepalive: false
idle_timeout: 30s
enable_request_timing: false
enable_legacy_php_urls: false
announce_routes:
- "/announce"
scrape_routes:
- "/scrape"
allow_ip_spoofing: false
real_ip_header: "x-real-ip"
max_numwant: 100

View file

@ -16,7 +16,10 @@ chihaya:
enable_keepalive: false
idle_timeout: 30s
enable_request_timing: false
enable_legacy_php_urls: false
announce_routes:
- "/announce"
scrape_routes:
- "/scrape"
allow_ip_spoofing: false
real_ip_header: "x-real-ip"
max_numwant: 100

View file

@ -29,7 +29,8 @@ type Config struct {
EnableKeepAlive bool `yaml:"enable_keepalive"`
TLSCertPath string `yaml:"tls_cert_path"`
TLSKeyPath string `yaml:"tls_key_path"`
EnableLegacyPHPURLs bool `yaml:"enable_legacy_php_urls"`
AnnounceRoutes []string `yaml:"announce_routes"`
ScrapeRoutes []string `yaml:"scrape_routes"`
EnableRequestTiming bool `yaml:"enable_request_timing"`
ParseOptions `yaml:",inline"`
}
@ -45,7 +46,8 @@ func (cfg Config) LogFields() log.Fields {
"enableKeepAlive": cfg.EnableKeepAlive,
"tlsCertPath": cfg.TLSCertPath,
"tlsKeyPath": cfg.TLSKeyPath,
"enableLegacyPHPURLs": cfg.EnableLegacyPHPURLs,
"announceRoutes": cfg.AnnounceRoutes,
"scrapeRoutes": cfg.ScrapeRoutes,
"enableRequestTiming": cfg.EnableRequestTiming,
"allowIPSpoofing": cfg.AllowIPSpoofing,
"realIPHeader": cfg.RealIPHeader,
@ -154,6 +156,10 @@ func NewFrontend(logic frontend.TrackerLogic, provided Config) (*Frontend, error
return nil, errors.New("must specify addr or https_addr or both")
}
if len(cfg.AnnounceRoutes) < 1 || len(cfg.ScrapeRoutes) < 1 {
return nil, errors.New("must specify routes")
}
// If TLS is enabled, create a key pair.
if cfg.TLSCertPath != "" && cfg.TLSKeyPath != "" {
var err error
@ -236,15 +242,12 @@ func (f *Frontend) makeStopFunc(stopSrv *http.Server) stop.Func {
func (f *Frontend) handler() http.Handler {
router := httprouter.New()
router.GET("/announce", f.announceRoute)
router.GET("/scrape", f.scrapeRoute)
if f.EnableLegacyPHPURLs {
log.Info("http: enabling legacy PHP URLs")
router.GET("/announce.php", f.announceRoute)
router.GET("/scrape.php", f.scrapeRoute)
for _, route := range f.AnnounceRoutes {
router.GET(route, f.announceRoute)
}
for _, route := range f.ScrapeRoutes {
router.GET(route, f.scrapeRoute)
}
return router
}
@ -288,8 +291,16 @@ func (f *Frontend) serveHTTPS(l net.Listener) error {
return nil
}
func injectRouteParamsToContext(ctx context.Context, ps httprouter.Params) context.Context {
rp := bittorrent.RouteParams{}
for _, p := range ps {
rp = append(rp, bittorrent.RouteParam{Key: p.Key, Value: p.Value})
}
return context.WithValue(ctx, bittorrent.RouteParamsKey, rp)
}
// announceRoute parses and responds to an Announce.
func (f *Frontend) announceRoute(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
func (f *Frontend) announceRoute(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
var err error
var start time.Time
if f.EnableRequestTiming {
@ -312,7 +323,8 @@ func (f *Frontend) announceRoute(w http.ResponseWriter, r *http.Request, _ httpr
af = new(bittorrent.AddressFamily)
*af = req.IP.AddressFamily
ctx, resp, err := f.logic.HandleAnnounce(context.Background(), req)
ctx := injectRouteParamsToContext(context.Background(), ps)
ctx, resp, err := f.logic.HandleAnnounce(ctx, req)
if err != nil {
WriteError(w, err)
return
@ -329,7 +341,7 @@ func (f *Frontend) announceRoute(w http.ResponseWriter, r *http.Request, _ httpr
}
// scrapeRoute parses and responds to a Scrape.
func (f *Frontend) scrapeRoute(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
func (f *Frontend) scrapeRoute(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
var err error
var start time.Time
if f.EnableRequestTiming {
@ -370,7 +382,8 @@ func (f *Frontend) scrapeRoute(w http.ResponseWriter, r *http.Request, _ httprou
af = new(bittorrent.AddressFamily)
*af = req.AddressFamily
ctx, resp, err := f.logic.HandleScrape(context.Background(), req)
ctx := injectRouteParamsToContext(context.Background(), ps)
ctx, resp, err := f.logic.HandleScrape(ctx, req)
if err != nil {
WriteError(w, err)
return