<commit_before>package http

import (
	"fmt"
	"io/ioutil"
	"github.com/elazarl/go-bindata-assetfs"
	"log"
	"net"
	"net/http"
	"path"
	"strings"

	"github.com/mediocregopher/gobdns/config"
	"github.com/mediocregopher/gobdns/ips"
	"github.com/mediocregopher/gobdns/snapshot"
)

var usage = `
	GET    /                     Gives you this page

	GET    /api/snapshot         Returns an encoded snapshot of this instance's
	                             data

	GET    /api/domains/all      Gives you a space separated mapping of domains
	                             to ips

	POST   /api/domains/<domain> Maps the given domain to the given ip, which
	                             can be the body data for the request, otherwise
	                             the ip the request is coming from will be used.

	PUT    /api/domains/<domain> Same as POST'ing

	DELETE /api/domains/<domain> Removes the domain->ip mapping for the given
	                             domain

`

func init() {
	if config.APIAddr == "" {
		return
	}

	go func() {
		log.Printf("API Listening on %s", config.APIAddr)
		http.HandleFunc("/api/domains/all", getAll)
		http.HandleFunc("/api/domains/", putDelete)
		http.HandleFunc("/api/snapshot", getSnapshot)

		assetFS := assetfs.AssetFS{
			Asset: Asset,
			AssetDir: AssetDir,
		}

		http.Handle("/", http.FileServer(&assetFS))
		http.ListenAndServe(config.APIAddr, nil)
	}()
}

func getAll(w http.ResponseWriter, r *http.Request) {
	for domain, ip := range ips.GetAll() {
		fmt.Fprintf(w, "%s %s\n", domain, ip)
	}
}

func putDelete(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/api/domains/" {
		w.WriteHeader(404)
		return
	}

	domain := path.Base(r.URL.Path)

	switch r.Method {
	case "PUT", "POST":
		ipB, err := ioutil.ReadAll(r.Body)
		if err != nil {
			log.Println(err)
			w.WriteHeader(500)
			return
		}
		ip := strings.TrimSpace(string(ipB))
		if ip == "" {
			ip = getIP(r)
		}
		if net.ParseIP(ip) == nil {
			w.WriteHeader(400)
			fmt.Fprintf(w, "invalid ip: %s", ip)
			return
		}
		ips.Set(domain, ip)

	case "DELETE":
		ips.Unset(domain)
	}
}

func getIP(r *http.Request) string {
	if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
		return ip
	}
	portIdent := strings.LastIndex(r.RemoteAddr, ":")
	return r.RemoteAddr[:portIdent]
}

func getSnapshot(w http.ResponseWriter, r *http.Request) {
	b, err := snapshot.CreateEncoded()
	if err != nil {
		log.Printf("Creating snapshot: %s", err)
		w.WriteHeader(500)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(b)
	return
}

func root(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, usage)
}<commit_msg>get rid of usage, we don't want it there anymore<commit_after>package http

import (
	"fmt"
	"io/ioutil"
	"github.com/elazarl/go-bindata-assetfs"
	"log"
	"net"
	"net/http"
	"path"
	"strings"

	"github.com/mediocregopher/gobdns/config"
	"github.com/mediocregopher/gobdns/ips"
	"github.com/mediocregopher/gobdns/snapshot"
)

func init() {
	if config.APIAddr == "" {
		return
	}

	go func() {
		log.Printf("API Listening on %s", config.APIAddr)
		http.HandleFunc("/api/domains/all", getAll)
		http.HandleFunc("/api/domains/", putDelete)
		http.HandleFunc("/api/snapshot", getSnapshot)

		assetFS := assetfs.AssetFS{
			Asset: Asset,
			AssetDir: AssetDir,
		}

		http.Handle("/", http.FileServer(&assetFS))
		http.ListenAndServe(config.APIAddr, nil)
	}()
}

func getAll(w http.ResponseWriter, r *http.Request) {
	for domain, ip := range ips.GetAll() {
		fmt.Fprintf(w, "%s %s\n", domain, ip)
	}
}

func putDelete(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/api/domains/" {
		w.WriteHeader(404)
		return
	}

	domain := path.Base(r.URL.Path)

	switch r.Method {
	case "PUT", "POST":
		ipB, err := ioutil.ReadAll(r.Body)
		if err != nil {
			log.Println(err)
			w.WriteHeader(500)
			return
		}
		ip := strings.TrimSpace(string(ipB))
		if ip == "" {
			ip = getIP(r)
		}
		if net.ParseIP(ip) == nil {
			w.WriteHeader(400)
			fmt.Fprintf(w, "invalid ip: %s", ip)
			return
		}
		ips.Set(domain, ip)

	case "DELETE":
		ips.Unset(domain)
	}
}

func getIP(r *http.Request) string {
	if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
		return ip
	}
	portIdent := strings.LastIndex(r.RemoteAddr, ":")
	return r.RemoteAddr[:portIdent]
}

func getSnapshot(w http.ResponseWriter, r *http.Request) {
	b, err := snapshot.CreateEncoded()
	if err != nil {
		log.Printf("Creating snapshot: %s", err)
		w.WriteHeader(500)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(b)
	return
}
{'fraction_non_alphanumeric': 0.15538461538461537, 'fraction_numerical': 0.005274725274725275, 'mean_word_length': 3.0167696381288613, 'pattern_counts': {'":': 6, '<': 6, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7266196', 'n_tokens_mistral': 1864, 'n_tokens_neox': 1715, 'n_words': 368}