Restructure

This commit is contained in:
Martin Polden 2018-02-10 13:24:32 +01:00
parent 7362c9043a
commit 35061bfe83
5 changed files with 63 additions and 62 deletions

View File

@ -1,15 +1,12 @@
package main package main
import ( import (
"net/http"
flags "github.com/jessevdk/go-flags" flags "github.com/jessevdk/go-flags"
"os" "os"
"github.com/mpolden/ipd/http"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/mpolden/ipd/api"
) )
func main() { func main() {
@ -35,7 +32,7 @@ func main() {
} }
log.Level = level log.Level = level
oracle := api.NewOracle() oracle := http.NewOracle()
if opts.ReverseLookup { if opts.ReverseLookup {
log.Println("Enabling reverse lookup") log.Println("Enabling reverse lookup")
oracle.EnableLookupAddr() oracle.EnableLookupAddr()
@ -60,12 +57,12 @@ func main() {
log.Printf("Trusting header %s to contain correct remote IP", opts.IPHeader) log.Printf("Trusting header %s to contain correct remote IP", opts.IPHeader)
} }
api := api.New(oracle, log) server := http.New(oracle, log)
api.Template = opts.Template server.Template = opts.Template
api.IPHeader = opts.IPHeader server.IPHeader = opts.IPHeader
log.Printf("Listening on http://%s", opts.Listen) log.Printf("Listening on http://%s", opts.Listen)
if err := http.ListenAndServe(opts.Listen, api.Router()); err != nil { if err := server.ListenAndServe(opts.Listen); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

View File

@ -1,4 +1,4 @@
package api package http
import "net/http" import "net/http"

View File

@ -1,4 +1,4 @@
package api package http
import ( import (
"encoding/json" "encoding/json"
@ -23,7 +23,7 @@ const (
textMediaType = "text/plain" textMediaType = "text/plain"
) )
type API struct { type Server struct {
Template string Template string
IPHeader string IPHeader string
oracle Oracle oracle Oracle
@ -45,8 +45,8 @@ type PortResponse struct {
Reachable bool `json:"reachable"` Reachable bool `json:"reachable"`
} }
func New(oracle Oracle, logger *logrus.Logger) *API { func New(oracle Oracle, logger *logrus.Logger) *Server {
return &API{oracle: oracle, log: logger} return &Server{oracle: oracle, log: logger}
} }
func ipToDecimal(ip net.IP) *big.Int { func ipToDecimal(ip net.IP) *big.Int {
@ -75,27 +75,27 @@ func ipFromRequest(header string, r *http.Request) (net.IP, error) {
return ip, nil return ip, nil
} }
func (a *API) newResponse(r *http.Request) (Response, error) { func (s *Server) newResponse(r *http.Request) (Response, error) {
ip, err := ipFromRequest(a.IPHeader, r) ip, err := ipFromRequest(s.IPHeader, r)
if err != nil { if err != nil {
return Response{}, err return Response{}, err
} }
ipDecimal := ipToDecimal(ip) ipDecimal := ipToDecimal(ip)
country, err := a.oracle.LookupCountry(ip) country, err := s.oracle.LookupCountry(ip)
if err != nil { if err != nil {
a.log.Debug(err) s.log.Debug(err)
} }
countryISO, err := a.oracle.LookupCountryISO(ip) countryISO, err := s.oracle.LookupCountryISO(ip)
if err != nil { if err != nil {
a.log.Debug(err) s.log.Debug(err)
} }
city, err := a.oracle.LookupCity(ip) city, err := s.oracle.LookupCity(ip)
if err != nil { if err != nil {
a.log.Debug(err) s.log.Debug(err)
} }
hostnames, err := a.oracle.LookupAddr(ip) hostnames, err := s.oracle.LookupAddr(ip)
if err != nil { if err != nil {
a.log.Debug(err) s.log.Debug(err)
} }
return Response{ return Response{
IP: ip, IP: ip,
@ -107,7 +107,7 @@ func (a *API) newResponse(r *http.Request) (Response, error) {
}, nil }, nil
} }
func (a *API) newPortResponse(r *http.Request) (PortResponse, error) { func (s *Server) newPortResponse(r *http.Request) (PortResponse, error) {
vars := mux.Vars(r) vars := mux.Vars(r)
port, err := strconv.ParseUint(vars["port"], 10, 16) port, err := strconv.ParseUint(vars["port"], 10, 16)
if err != nil { if err != nil {
@ -116,11 +116,11 @@ func (a *API) newPortResponse(r *http.Request) (PortResponse, error) {
if port < 1 || port > 65355 { if port < 1 || port > 65355 {
return PortResponse{Port: port}, fmt.Errorf("invalid port: %d", port) return PortResponse{Port: port}, fmt.Errorf("invalid port: %d", port)
} }
ip, err := ipFromRequest(a.IPHeader, r) ip, err := ipFromRequest(s.IPHeader, r)
if err != nil { if err != nil {
return PortResponse{Port: port}, err return PortResponse{Port: port}, err
} }
err = a.oracle.LookupPort(ip, port) err = s.oracle.LookupPort(ip, port)
return PortResponse{ return PortResponse{
IP: ip, IP: ip,
Port: port, Port: port,
@ -128,8 +128,8 @@ func (a *API) newPortResponse(r *http.Request) (PortResponse, error) {
}, nil }, nil
} }
func (a *API) CLIHandler(w http.ResponseWriter, r *http.Request) *appError { func (s *Server) CLIHandler(w http.ResponseWriter, r *http.Request) *appError {
ip, err := ipFromRequest(a.IPHeader, r) ip, err := ipFromRequest(s.IPHeader, r)
if err != nil { if err != nil {
return internalServerError(err) return internalServerError(err)
} }
@ -137,8 +137,8 @@ func (a *API) CLIHandler(w http.ResponseWriter, r *http.Request) *appError {
return nil return nil
} }
func (a *API) CLICountryHandler(w http.ResponseWriter, r *http.Request) *appError { func (s *Server) CLICountryHandler(w http.ResponseWriter, r *http.Request) *appError {
response, err := a.newResponse(r) response, err := s.newResponse(r)
if err != nil { if err != nil {
return internalServerError(err) return internalServerError(err)
} }
@ -146,8 +146,8 @@ func (a *API) CLICountryHandler(w http.ResponseWriter, r *http.Request) *appErro
return nil return nil
} }
func (a *API) CLICountryISOHandler(w http.ResponseWriter, r *http.Request) *appError { func (s *Server) CLICountryISOHandler(w http.ResponseWriter, r *http.Request) *appError {
response, err := a.newResponse(r) response, err := s.newResponse(r)
if err != nil { if err != nil {
return internalServerError(err) return internalServerError(err)
} }
@ -155,8 +155,8 @@ func (a *API) CLICountryISOHandler(w http.ResponseWriter, r *http.Request) *appE
return nil return nil
} }
func (a *API) CLICityHandler(w http.ResponseWriter, r *http.Request) *appError { func (s *Server) CLICityHandler(w http.ResponseWriter, r *http.Request) *appError {
response, err := a.newResponse(r) response, err := s.newResponse(r)
if err != nil { if err != nil {
return internalServerError(err) return internalServerError(err)
} }
@ -164,8 +164,8 @@ func (a *API) CLICityHandler(w http.ResponseWriter, r *http.Request) *appError {
return nil return nil
} }
func (a *API) JSONHandler(w http.ResponseWriter, r *http.Request) *appError { func (s *Server) JSONHandler(w http.ResponseWriter, r *http.Request) *appError {
response, err := a.newResponse(r) response, err := s.newResponse(r)
if err != nil { if err != nil {
return internalServerError(err).AsJSON() return internalServerError(err).AsJSON()
} }
@ -178,8 +178,8 @@ func (a *API) JSONHandler(w http.ResponseWriter, r *http.Request) *appError {
return nil return nil
} }
func (a *API) PortHandler(w http.ResponseWriter, r *http.Request) *appError { func (s *Server) PortHandler(w http.ResponseWriter, r *http.Request) *appError {
response, err := a.newPortResponse(r) response, err := s.newPortResponse(r)
if err != nil { if err != nil {
return badRequest(err).WithMessage(fmt.Sprintf("Invalid port: %d", response.Port)).AsJSON() return badRequest(err).WithMessage(fmt.Sprintf("Invalid port: %d", response.Port)).AsJSON()
} }
@ -192,12 +192,12 @@ func (a *API) PortHandler(w http.ResponseWriter, r *http.Request) *appError {
return nil return nil
} }
func (a *API) DefaultHandler(w http.ResponseWriter, r *http.Request) *appError { func (s *Server) DefaultHandler(w http.ResponseWriter, r *http.Request) *appError {
response, err := a.newResponse(r) response, err := s.newResponse(r)
if err != nil { if err != nil {
return internalServerError(err) return internalServerError(err)
} }
t, err := template.New(filepath.Base(a.Template)).ParseFiles(a.Template) t, err := template.New(filepath.Base(s.Template)).ParseFiles(s.Template)
if err != nil { if err != nil {
return internalServerError(err) return internalServerError(err)
} }
@ -205,14 +205,14 @@ func (a *API) DefaultHandler(w http.ResponseWriter, r *http.Request) *appError {
Host string Host string
Response Response
Oracle Oracle
}{r.Host, response, a.oracle} }{r.Host, response, s.oracle}
if err := t.Execute(w, &data); err != nil { if err := t.Execute(w, &data); err != nil {
return internalServerError(err) return internalServerError(err)
} }
return nil return nil
} }
func (a *API) NotFoundHandler(w http.ResponseWriter, r *http.Request) *appError { func (s *Server) NotFoundHandler(w http.ResponseWriter, r *http.Request) *appError {
err := notFound(nil).WithMessage("404 page not found") err := notFound(nil).WithMessage("404 page not found")
if r.Header.Get("accept") == jsonMediaType { if r.Header.Get("accept") == jsonMediaType {
err = err.AsJSON() err = err.AsJSON()
@ -253,29 +253,33 @@ func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
} }
func (a *API) Router() http.Handler { func (s *Server) Handler() http.Handler {
r := mux.NewRouter() r := mux.NewRouter()
// JSON // JSON
r.Handle("/", appHandler(a.JSONHandler)).Methods("GET").Headers("Accept", jsonMediaType) r.Handle("/", appHandler(s.JSONHandler)).Methods("GET").Headers("Accept", jsonMediaType)
r.Handle("/json", appHandler(a.JSONHandler)).Methods("GET") r.Handle("/json", appHandler(s.JSONHandler)).Methods("GET")
// CLI // CLI
r.Handle("/", appHandler(a.CLIHandler)).Methods("GET").MatcherFunc(cliMatcher) r.Handle("/", appHandler(s.CLIHandler)).Methods("GET").MatcherFunc(cliMatcher)
r.Handle("/", appHandler(a.CLIHandler)).Methods("GET").Headers("Accept", textMediaType) r.Handle("/", appHandler(s.CLIHandler)).Methods("GET").Headers("Accept", textMediaType)
r.Handle("/ip", appHandler(a.CLIHandler)).Methods("GET") r.Handle("/ip", appHandler(s.CLIHandler)).Methods("GET")
r.Handle("/country", appHandler(a.CLICountryHandler)).Methods("GET") r.Handle("/country", appHandler(s.CLICountryHandler)).Methods("GET")
r.Handle("/country-iso", appHandler(a.CLICountryISOHandler)).Methods("GET") r.Handle("/country-iso", appHandler(s.CLICountryISOHandler)).Methods("GET")
r.Handle("/city", appHandler(a.CLICityHandler)).Methods("GET") r.Handle("/city", appHandler(s.CLICityHandler)).Methods("GET")
// Browser // Browser
r.Handle("/", appHandler(a.DefaultHandler)).Methods("GET") r.Handle("/", appHandler(s.DefaultHandler)).Methods("GET")
// Port testing // Port testing
r.Handle("/port/{port:[0-9]+}", appHandler(a.PortHandler)).Methods("GET") r.Handle("/port/{port:[0-9]+}", appHandler(s.PortHandler)).Methods("GET")
// Not found handler which returns JSON when appropriate // Not found handler which returns JSON when appropriate
r.NotFoundHandler = appHandler(a.NotFoundHandler) r.NotFoundHandler = appHandler(s.NotFoundHandler)
return r return r
} }
func (s *Server) ListenAndServe(addr string) error {
return http.ListenAndServe(addr, s.Handler())
}

View File

@ -1,4 +1,4 @@
package api package http
import ( import (
"io/ioutil" "io/ioutil"
@ -22,8 +22,8 @@ func (r *mockOracle) IsLookupCountryEnabled() bool { return true }
func (r *mockOracle) IsLookupCityEnabled() bool { return true } func (r *mockOracle) IsLookupCityEnabled() bool { return true }
func (r *mockOracle) IsLookupPortEnabled() bool { return true } func (r *mockOracle) IsLookupPortEnabled() bool { return true }
func newTestAPI() *API { func newTestAPI() *Server {
return &API{oracle: &mockOracle{}} return &Server{oracle: &mockOracle{}}
} }
func httpGet(url string, acceptMediaType string, userAgent string) (string, int, error) { func httpGet(url string, acceptMediaType string, userAgent string) (string, int, error) {
@ -49,7 +49,7 @@ func httpGet(url string, acceptMediaType string, userAgent string) (string, int,
func TestCLIHandlers(t *testing.T) { func TestCLIHandlers(t *testing.T) {
log.SetOutput(ioutil.Discard) log.SetOutput(ioutil.Discard)
s := httptest.NewServer(newTestAPI().Router()) s := httptest.NewServer(newTestAPI().Handler())
var tests = []struct { var tests = []struct {
url string url string
@ -83,7 +83,7 @@ func TestCLIHandlers(t *testing.T) {
func TestJSONHandlers(t *testing.T) { func TestJSONHandlers(t *testing.T) {
log.SetOutput(ioutil.Discard) log.SetOutput(ioutil.Discard)
s := httptest.NewServer(newTestAPI().Router()) s := httptest.NewServer(newTestAPI().Handler())
var tests = []struct { var tests = []struct {
url string url string

View File

@ -1,4 +1,4 @@
package api package http
import ( import (
"fmt" "fmt"