unfinished mess
This commit is contained in:
parent
6c3b17ba0d
commit
2e2e3b1ec8
26 changed files with 364 additions and 171 deletions
|
@ -6,7 +6,7 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/mr-karan/doggo/internal/app"
|
||||
"github.com/mr-karan/doggo/internal/hub"
|
||||
"github.com/mr-karan/doggo/pkg/utils"
|
||||
"github.com/mr-karan/logf"
|
||||
|
||||
|
@ -31,7 +31,7 @@ func main() {
|
|||
initConfig()
|
||||
|
||||
// Initialize app.
|
||||
app := app.New(logger, buildString)
|
||||
app := hub.New(logger, buildString)
|
||||
|
||||
// Register router instance.
|
||||
r := chi.NewRouter()
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/mr-karan/doggo/internal/app"
|
||||
"github.com/mr-karan/doggo/internal/hub"
|
||||
"github.com/mr-karan/doggo/pkg/models"
|
||||
"github.com/mr-karan/doggo/pkg/resolvers"
|
||||
)
|
||||
|
@ -21,7 +21,7 @@ type httpResp struct {
|
|||
|
||||
func handleIndexAPI(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
app = r.Context().Value("app").(app.App)
|
||||
app = r.Context().Value("app").(hub.Hub)
|
||||
)
|
||||
|
||||
sendResponse(w, http.StatusOK, fmt.Sprintf("Welcome to Doggo API. Version: %s", app.Version))
|
||||
|
@ -35,21 +35,21 @@ func handleHealthCheck(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func handleLookup(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
app = r.Context().Value("app").(app.App)
|
||||
app = r.Context().Value("app").(hub.Hub)
|
||||
)
|
||||
|
||||
// Read body.
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
defer r.Body.Close()
|
||||
if err != nil {
|
||||
app.Logger.WithError(err).Error("error reading request body")
|
||||
app.Log.WithError(err).Error("error reading request body")
|
||||
sendErrorResponse(w, fmt.Sprintf("Invalid JSON payload"), http.StatusBadRequest, nil)
|
||||
return
|
||||
}
|
||||
// Prepare query flags.
|
||||
var qFlags models.QueryFlags
|
||||
if err := json.Unmarshal(b, &qFlags); err != nil {
|
||||
app.Logger.WithError(err).Error("error unmarshalling payload")
|
||||
app.Log.WithError(err).Error("error unmarshalling payload")
|
||||
sendErrorResponse(w, fmt.Sprintf("Invalid JSON payload"), http.StatusBadRequest, nil)
|
||||
return
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ func handleLookup(w http.ResponseWriter, r *http.Request) {
|
|||
// Load Nameservers.
|
||||
err = app.LoadNameservers()
|
||||
if err != nil {
|
||||
app.Logger.WithError(err).Error("error loading nameservers")
|
||||
app.Log.WithError(err).Error("error loading nameservers")
|
||||
sendErrorResponse(w, fmt.Sprintf("Error looking up for records."), http.StatusInternalServerError, nil)
|
||||
return
|
||||
}
|
||||
|
@ -82,10 +82,10 @@ func handleLookup(w http.ResponseWriter, r *http.Request) {
|
|||
SearchList: app.ResolverOpts.SearchList,
|
||||
Ndots: app.ResolverOpts.Ndots,
|
||||
Timeout: app.QueryFlags.Timeout * time.Second,
|
||||
Logger: app.Logger,
|
||||
Logger: app.Log,
|
||||
})
|
||||
if err != nil {
|
||||
app.Logger.WithError(err).Error("error loading resolver")
|
||||
app.Log.WithError(err).Error("error loading resolver")
|
||||
sendErrorResponse(w, fmt.Sprintf("Error looking up for records."), http.StatusInternalServerError, nil)
|
||||
return
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ func handleLookup(w http.ResponseWriter, r *http.Request) {
|
|||
for _, rslv := range app.Resolvers {
|
||||
resp, err := rslv.Lookup(q)
|
||||
if err != nil {
|
||||
app.Logger.WithError(err).Error("error looking up DNS records")
|
||||
app.Log.WithError(err).Error("error looking up DNS records")
|
||||
sendErrorResponse(w, fmt.Sprintf("Error looking up for records."), http.StatusInternalServerError, nil)
|
||||
return
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ func handleLookup(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// wrap is a middleware that wraps HTTP handlers and injects the "app" context.
|
||||
func wrap(app app.App, next http.HandlerFunc) http.HandlerFunc {
|
||||
func wrap(app hub.Hub, next http.HandlerFunc) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "app", app)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
"github.com/knadh/koanf"
|
||||
"github.com/knadh/koanf/providers/posflag"
|
||||
"github.com/mr-karan/doggo/internal/app"
|
||||
"github.com/mr-karan/doggo/pkg/resolvers"
|
||||
"github.com/mr-karan/doggo/pkg/utils"
|
||||
"github.com/mr-karan/doggo/internal/resolvers"
|
||||
"github.com/mr-karan/doggo/internal/utils"
|
||||
"github.com/mr-karan/logf"
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
108
cmd/doggo-v1/help.go
Normal file
108
cmd/doggo-v1/help.go
Normal file
|
@ -0,0 +1,108 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
// appHelpTextTemplate is the text/template to customise the Help output.
|
||||
// Uses text/template to render templates.
|
||||
var appHelpTextTemplate = `{{ "NAME" | color "" "heading" }}:
|
||||
{{ .Name | color "green" "bold" }} 🐶 {{.Description}}
|
||||
|
||||
{{ "USAGE" | color "" "heading" }}:
|
||||
{{ .Name | color "green" "bold" }} [--] {{ "[query options]" | color "yellow" "" }} {{ "[arguments...]" | color "cyan" "" }}
|
||||
|
||||
{{ "VERSION" | color "" "heading" }}:
|
||||
{{.Version | color "red" "" }}
|
||||
|
||||
{{ "EXAMPLES" | color "" "heading" }}:
|
||||
{{ .Name | color "green" "bold" }} {{ "mrkaran.dev" | color "cyan" "" }} {{"\t"}} Query a domain using defaults.
|
||||
{{ .Name | color "green" "bold" }} {{ "mrkaran.dev CNAME" | color "cyan" "" }} {{"\t"}} Looks up for a CNAME record.
|
||||
{{ .Name | color "green" "bold" }} {{ "mrkaran.dev MX @9.9.9.9" | color "cyan" "" }} {{"\t"}} Uses a custom DNS resolver.
|
||||
{{ .Name | color "green" "bold" }} {{"-q mrkaran.dev -t MX -n 1.1.1.1" | color "yellow" ""}} {{"\t"}} Using named arguments.
|
||||
|
||||
{{ "Free Form Arguments" | color "" "heading" }}:
|
||||
Supply hostnames, query types, classes without any flag. For eg:
|
||||
{{ .Name | color "green" "bold" }} {{"mrkaran.dev A @1.1.1.1" | color "cyan" "" }}
|
||||
|
||||
{{ "Transport Options" | color "" "heading" }}:
|
||||
Based on the URL scheme the correct resolver is chosen.
|
||||
Fallbacks to UDP resolver if no scheme is present.
|
||||
|
||||
{{"@udp://" | color "yellow" ""}} eg: @1.1.1.1 initiates a {{"UDP" | color "cyan" ""}} resolver for 1.1.1.1:53.
|
||||
{{"@tcp://" | color "yellow" ""}} eg: @tcp://1.1.1.1 initiates a {{"TCP" | color "cyan" ""}} resolver for 1.1.1.1:53.
|
||||
{{"@https://" | color "yellow" ""}} eg: @https://cloudflare-dns.com/dns-query initiates a {{"DOH" | color "cyan" ""}} resolver for Cloudflare DoH server.
|
||||
{{"@tls://" | color "yellow" ""}} eg: @tls://1.1.1.1 initiates a {{"DoT" | color "cyan" ""}} resolver for 1.1.1.1:853.
|
||||
{{"@sdns://" | color "yellow" ""}} initiates a {{"DNSCrypt" | color "cyan" ""}} or {{"DoH" | color "cyan" ""}} resolver using its DNS stamp.
|
||||
{{"@quic://" | color "yellow" ""}} initiates a {{"DOQ" | color "cyan" ""}} resolver.
|
||||
|
||||
{{ "Query Options" | color "" "heading" }}:
|
||||
{{"-q, --query=HOSTNAME" | color "yellow" ""}} Hostname to query the DNS records for (eg {{"mrkaran.dev" | color "cyan" ""}}).
|
||||
{{"-t, --type=TYPE" | color "yellow" ""}} Type of the DNS Record ({{"A, MX, NS" | color "cyan" ""}} etc).
|
||||
{{"-n, --nameserver=ADDR" | color "yellow" ""}} Address of a specific nameserver to send queries to ({{"9.9.9.9, 8.8.8.8" | color "cyan" ""}} etc).
|
||||
{{"-c, --class=CLASS" | color "yellow" ""}} Network class of the DNS record ({{"IN, CH, HS" | color "cyan" ""}} etc).
|
||||
{{"-x, --reverse" | color "yellow" ""}} Performs a DNS Lookup for an IPv4 or IPv6 address. Sets the query type and class to PTR and IN respectively.
|
||||
|
||||
{{ "Resolver Options" | color "" "heading" }}:
|
||||
{{"--strategy=STRATEGY" | color "yellow" ""}} Specify strategy to query nameserver listed in etc/resolv.conf. ({{"all, random, first" | color "cyan" ""}}).
|
||||
{{"--ndots=INT" | color "yellow" ""}} Specify ndots parameter. Takes value from /etc/resolv.conf if using the system namesever or 1 otherwise.
|
||||
{{"--search" | color "yellow" ""}} Use the search list defined in resolv.conf. Defaults to true. Set --search=false to disable search list.
|
||||
{{"--timeout" | color "yellow" ""}} Specify timeout (in seconds) for the resolver to return a response.
|
||||
{{"-4 --ipv4" | color "yellow" ""}} Use IPv4 only.
|
||||
{{"-6 --ipv6" | color "yellow" ""}} Use IPv6 only.
|
||||
{{"--ndots=INT" | color "yellow" ""}} Specify ndots parameter. Takes value from /etc/resolv.conf if using the system namesever or 1 otherwise.
|
||||
{{"--tls-hostname=HOSTNAME" | color "yellow" ""}} Provide a hostname for doing verification of the certificate if the provided DoT nameserver is an IP.
|
||||
{{"--skip-hostname-verification" | color "yellow" ""}} Skip TLS Hostname Verification in case of DOT Lookups.
|
||||
|
||||
{{ "Output Options" | color "" "heading" }}:
|
||||
{{"-J, --json " | color "yellow" ""}} Format the output as JSON.
|
||||
{{"--short" | color "yellow" ""}} Short output format. Shows only the response section.
|
||||
{{"--color " | color "yellow" ""}} Defaults to true. Set --color=false to disable colored output.
|
||||
{{"--debug " | color "yellow" ""}} Enable debug logging.
|
||||
{{"--time" | color "yellow" ""}} Shows how long the response took from the server.
|
||||
`
|
||||
|
||||
func renderCustomHelp() {
|
||||
helpTmplVars := map[string]string{
|
||||
"Name": "doggo",
|
||||
"Description": "DNS Client for Humans",
|
||||
"Version": buildString,
|
||||
}
|
||||
tmpl, err := template.New("test").Funcs(template.FuncMap{
|
||||
"color": func(clr string, format string, str string) string {
|
||||
formatter := color.New()
|
||||
switch c := clr; c {
|
||||
case "yellow":
|
||||
formatter = formatter.Add(color.FgYellow)
|
||||
case "red":
|
||||
formatter = formatter.Add(color.FgRed)
|
||||
case "cyan":
|
||||
formatter = formatter.Add(color.FgCyan)
|
||||
case "green":
|
||||
formatter = formatter.Add(color.FgGreen)
|
||||
}
|
||||
switch f := format; f {
|
||||
case "bold":
|
||||
formatter = formatter.Add(color.Bold)
|
||||
case "underline":
|
||||
formatter = formatter.Add(color.Underline)
|
||||
case "heading":
|
||||
formatter = formatter.Add(color.Bold, color.Underline)
|
||||
}
|
||||
return formatter.SprintFunc()(str)
|
||||
},
|
||||
}).Parse(appHelpTextTemplate)
|
||||
if err != nil {
|
||||
// should ideally never happen.
|
||||
panic(err)
|
||||
}
|
||||
err = tmpl.Execute(os.Stdout, helpTmplVars)
|
||||
if err != nil {
|
||||
// should ideally never happen.
|
||||
panic(err)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
10
cmd/doggo/init.go
Normal file
10
cmd/doggo/init.go
Normal file
|
@ -0,0 +1,10 @@
|
|||
package main
|
||||
|
||||
import "github.com/mr-karan/logf"
|
||||
|
||||
func initLogger() *logf.Logger {
|
||||
logf := logf.New()
|
||||
logf.SetColorOutput(true)
|
||||
|
||||
return logf
|
||||
}
|
77
cmd/doggo/main.go
Normal file
77
cmd/doggo/main.go
Normal file
|
@ -0,0 +1,77 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
buildString = "unknown"
|
||||
lo = initLogger()
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Intialize new CLI app.
|
||||
app := cli.NewApp()
|
||||
app.Name = "doggo"
|
||||
app.Usage = "DNS Client for Humans"
|
||||
app.Version = buildString
|
||||
|
||||
// Query Options.
|
||||
queryFlags := []cli.Flag{
|
||||
&cli.StringSliceFlag{
|
||||
Name: "query",
|
||||
Value: cli.NewStringSlice(),
|
||||
Aliases: []string{"q"},
|
||||
Usage: "Hostname to query the DNS records for (eg mrkaran.dev)",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "type",
|
||||
Value: cli.NewStringSlice(),
|
||||
Aliases: []string{"t"},
|
||||
Usage: "Type of DNS record to be queried (A, AAAA, MX etc)",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "class",
|
||||
Value: cli.NewStringSlice(),
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Network class of the DNS record to be queried (IN, CH, HS etc)",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "nameservers",
|
||||
Value: cli.NewStringSlice(),
|
||||
Aliases: []string{"n"},
|
||||
Usage: "DNS Server address to send queries (eg 1.1.1.1, 8.8.8.8)",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "reverse",
|
||||
Value: false,
|
||||
Aliases: []string{"x"},
|
||||
Usage: "Performs a DNS Lookup for an IPv4 or IPv6 address. Sets the query type and class to PTR and IN respectively",
|
||||
},
|
||||
}
|
||||
|
||||
// Resolver Options.
|
||||
|
||||
cli.AppHelpTemplate = appHelpTextTemplate
|
||||
|
||||
app.Flags = append(app.Flags, queryFlags...)
|
||||
|
||||
sort.Sort(cli.FlagsByName(app.Flags))
|
||||
|
||||
// // Define actions.
|
||||
app.Action = Lookup
|
||||
|
||||
// Run the app.
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
lo.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func Lookup(c *cli.Context) error {
|
||||
fmt.Println(c.StringSlice("query"))
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue