mirror of
https://github.com/mpolden/echoip.git
synced 2025-02-05 06:45:06 +01:00
parent
6fa3c34c19
commit
0cd84ada1e
13
api/api.go
13
api/api.go
@ -6,13 +6,13 @@ import (
|
|||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/mpolden/ipd/useragent"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -24,10 +24,6 @@ const (
|
|||||||
textMediaType = "text/plain"
|
textMediaType = "text/plain"
|
||||||
)
|
)
|
||||||
|
|
||||||
var userAgentPattern = regexp.MustCompile(
|
|
||||||
`^(?:curl|Wget|fetch\slibfetch|ddclient|Go-http-client|HTTPie)\/.*|Go\s1\.1\spackage\shttp$`,
|
|
||||||
)
|
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
Template string
|
Template string
|
||||||
IPHeader string
|
IPHeader string
|
||||||
@ -210,7 +206,12 @@ func (a *API) NotFoundHandler(w http.ResponseWriter, r *http.Request) *appError
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cliMatcher(r *http.Request, rm *mux.RouteMatch) bool {
|
func cliMatcher(r *http.Request, rm *mux.RouteMatch) bool {
|
||||||
return userAgentPattern.MatchString(r.UserAgent())
|
ua := useragent.Parse(r.UserAgent())
|
||||||
|
switch ua.Product {
|
||||||
|
case "curl", "HTTPie", "Wget", "fetch libfetch", "Go", "Go-http-client", "ddclient":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
type appHandler func(http.ResponseWriter, *http.Request) *appError
|
type appHandler func(http.ResponseWriter, *http.Request) *appError
|
||||||
|
@ -150,6 +150,7 @@ func TestCLIMatcher(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{"curl/7.26.0", true},
|
{"curl/7.26.0", true},
|
||||||
{"Wget/1.13.4 (linux-gnu)", true},
|
{"Wget/1.13.4 (linux-gnu)", true},
|
||||||
|
{"Wget", true},
|
||||||
{"fetch libfetch/2.0", true},
|
{"fetch libfetch/2.0", true},
|
||||||
{"HTTPie/0.9.3", true},
|
{"HTTPie/0.9.3", true},
|
||||||
{"Go 1.1 package http", true},
|
{"Go 1.1 package http", true},
|
||||||
|
38
useragent/useragent.go
Normal file
38
useragent/useragent.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package useragent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserAgent struct {
|
||||||
|
Product string
|
||||||
|
Version string
|
||||||
|
Comment string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(s string) UserAgent {
|
||||||
|
parts := strings.SplitN(s, "/", 2)
|
||||||
|
var version, comment string
|
||||||
|
if len(parts) > 1 {
|
||||||
|
// If first character is a number, treat it as version
|
||||||
|
if parts[1][0] >= 48 && parts[1][0] <= 57 {
|
||||||
|
rest := strings.SplitN(parts[1], " ", 2)
|
||||||
|
version = rest[0]
|
||||||
|
if len(rest) > 1 {
|
||||||
|
comment = rest[1]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
comment = parts[1]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parts = strings.SplitN(s, " ", 2)
|
||||||
|
if len(parts) > 1 {
|
||||||
|
comment = parts[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UserAgent{
|
||||||
|
Product: parts[0],
|
||||||
|
Version: version,
|
||||||
|
Comment: comment,
|
||||||
|
}
|
||||||
|
}
|
36
useragent/useragent_test.go
Normal file
36
useragent/useragent_test.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package useragent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParse(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
in string
|
||||||
|
out UserAgent
|
||||||
|
}{
|
||||||
|
{"", UserAgent{}},
|
||||||
|
{"curl/7.26.0", UserAgent{Product: "curl", Version: "7.26.0"}},
|
||||||
|
{"Wget/1.13.4 (linux-gnu)", UserAgent{Product: "Wget", Version: "1.13.4", Comment: "(linux-gnu)"}},
|
||||||
|
{"Wget", UserAgent{Product: "Wget"}},
|
||||||
|
{"fetch libfetch/2.0", UserAgent{Product: "fetch libfetch", Version: "2.0"}},
|
||||||
|
{"Go 1.1 package http", UserAgent{Product: "Go", Comment: "1.1 package http"}},
|
||||||
|
{"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) " +
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.28 " +
|
||||||
|
"Safari/537.36", UserAgent{Product: "Mozilla", Version: "5.0", Comment: "(Macintosh; Intel Mac OS X 10_8_4) " +
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.28 " +
|
||||||
|
"Safari/537.36"}},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
ua := Parse(tt.in)
|
||||||
|
if got := ua.Product; got != tt.out.Product {
|
||||||
|
t.Errorf("got Product=%q for %q, want %q", got, tt.in, tt.out.Product)
|
||||||
|
}
|
||||||
|
if got := ua.Version; got != tt.out.Version {
|
||||||
|
t.Errorf("got Version=%q for %q, want %q", got, tt.in, tt.out.Version)
|
||||||
|
}
|
||||||
|
if got := ua.Comment; got != tt.out.Comment {
|
||||||
|
t.Errorf("got Comment=%q for %q, want %q", got, tt.in, tt.out.Comment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user