commit 940a0ab0e048913272e4bbfa1b75ac14a456b33e
Author: Arlo Breault <[email protected]>
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 mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to