commit 940a0ab0e048913272e4bbfa1b75ac14a456b33e Author: Arlo Breault arlolra@gmail.com Date: Tue Nov 19 00:00:59 2013 -0800
Start an API.
One route, /api/bulk --- check.go | 1 + datastore.go | 36 ++++++++++++++++++++++++++++++++---- handlers.go | 18 +++++++++++++----- 3 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/check.go b/check.go index 73e6a7c..00b25b6 100644 --- a/check.go +++ b/check.go @@ -60,6 +60,7 @@ func main() { // routes http.HandleFunc("/", RootHandler(CompileTemplate(*basePath, domain, "index.html"), exits, domain, Phttp, Locales)) bulk := BulkHandler(CompileTemplate(*basePath, domain, "bulk.html"), exits, domain) + http.HandleFunc("/api/bulk", bulk) http.HandleFunc("/torbulkexitlist", bulk) http.HandleFunc("/cgi-bin/TorBulkExitList.py", bulk)
diff --git a/datastore.go b/datastore.go index c01acc6..c23109b 100644 --- a/datastore.go +++ b/datastore.go @@ -84,6 +84,19 @@ func (p PolicyList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+type ExitInfo struct { + Address string + Fingerprint string +} + +func (e ExitInfo) toJSON() (b []byte) { + j, err := json.MarshalIndent(e, "", " ") + if err != nil { + return + } + return j +} + type Exits struct { List PolicyList UpdateTime time.Time @@ -93,15 +106,30 @@ type Exits struct {
func (e *Exits) Dump(w io.Writer, tminus int, ip string, port int) { ap := AddressPort{ip, port} - e.GetAllExits(ap, tminus, func(exit string, _ string) { + e.GetAllExits(ap, tminus, func(exit string, _ string, _ int) { w.Write([]byte(exit + "\n")) }) }
-func (e *Exits) GetAllExits(ap AddressPort, tminus int, fn func(string, string)) { +func (e *Exits) DumpJSON(w io.Writer, tminus int, ip string, port int) { + ap := AddressPort{ip, port} + Prefix := []byte(",\n") + w.Write([]byte("[")) + e.GetAllExits(ap, tminus, func(address string, fingerprint string, ind int) { + if ind > 0 { + w.Write(Prefix) + } + w.Write(ExitInfo{address, fingerprint}.toJSON()) + }) + w.Write([]byte("]")) +} + +func (e *Exits) GetAllExits(ap AddressPort, tminus int, fn func(string, string, int)) { + ind := 0 for _, val := range e.List { if val.Tminus <= tminus && val.CanExit(ap) { - fn(val.Address, val.Fingerprint) + fn(val.Address, val.Fingerprint, ind) + ind += 1 } } } @@ -110,7 +138,7 @@ var DefaultTarget = AddressPort{"38.229.70.31", 443}
func (e *Exits) PreComputeTorList() { newmap := make(map[string]string) - e.GetAllExits(DefaultTarget, 16, func(ip string, fingerprint string) { + e.GetAllExits(DefaultTarget, 16, func(ip string, fingerprint string, _ int) { newmap[ip] = fingerprint }) e.IsTorLookup = newmap diff --git a/handlers.go b/handlers.go index eee6948..9342ff8 100644 --- a/handlers.go +++ b/handlers.go @@ -9,6 +9,7 @@ import ( "log" "net" "net/http" + "regexp" "strconv" "time" ) @@ -89,6 +90,8 @@ func RootHandler(Layout *template.Template, Exits *Exits, domain *gettext.Domain
func BulkHandler(Layout *template.Template, Exits *Exits, domain *gettext.Domain) http.HandlerFunc {
+ ApiPath := regexp.MustCompile("^/api/") + return func(w http.ResponseWriter, r *http.Request) { q := r.URL.Query()
@@ -103,12 +106,17 @@ func BulkHandler(Layout *template.Template, Exits *Exits, domain *gettext.Domain
w.Header().Set("Last-Modified", Exits.UpdateTime.UTC().Format(http.TimeFormat))
- str := fmt.Sprintf("# This is a list of all Tor exit nodes from the past %d hours that can contact %s on port %d #\n", n, ip, port) - str += fmt.Sprintf("# You can update this list by visiting https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=%s%s%s #\n", ip, port_str, n_str) - str += fmt.Sprintf("# This file was generated on %v #\n", Exits.UpdateTime.UTC().Format(time.UnixDate)) - fmt.Fprintf(w, str) + if q.Get("format") == "json" || ApiPath.MatchString(r.URL.Path) { + w.Header().Set("Content-Type", "application/json") + Exits.DumpJSON(w, n, ip, port) + } else { + str := fmt.Sprintf("# This is a list of all Tor exit nodes from the past %d hours that can contact %s on port %d #\n", n, ip, port) + str += fmt.Sprintf("# You can update this list by visiting https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=%s%s%s #\n", ip, port_str, n_str) + str += fmt.Sprintf("# This file was generated on %v #\n", Exits.UpdateTime.UTC().Format(time.UnixDate)) + fmt.Fprintf(w, str) + Exits.Dump(w, n, ip, port) + }
- Exits.Dump(w, n, ip, port) }
}
tor-commits@lists.torproject.org