go-captiveportal/matcher.go

101 lines
2.1 KiB
Go

package captiveportal
import (
"net/http"
"strings"
"github.com/pkg/errors"
)
type OS int
const (
OSUnknown OS = iota
OSAndroid
OSApple
OSWindows
OSLinux
)
type Matcher interface {
Match(r *http.Request) (bool, OS, error)
}
type MatchFunc func(r *http.Request) (bool, OS, error)
func (f MatchFunc) Match(r *http.Request) (bool, OS, error) {
return f(r)
}
func MatchAndroid(r *http.Request) (bool, error) {
// Samples
//
// https://www.google.com/generate_204
// http://connectivitycheck.gstatic.com/generate_204
// http://www.google.com/gen_204
// http://play.googleapis.com/generate_204
// http://connectivitycheck.gstatic.com/generate_204
// http://clients3.google.com/generate_204
// http://g.cn
matches := strings.Contains(r.URL.Path, "generate_204") ||
strings.Contains(r.URL.Path, "gen_204") ||
strings.Contains(r.Host, "g.cn")
return matches, nil
}
func MatchApple(r *http.Request) (bool, error) {
// Samples
//
// http://www.apple.com/library/test/success.html
// http://captive.apple.com/hotspot-detect.html
matches := strings.Contains(r.Host, "www.apple.com") ||
strings.Contains(r.Host, "captive.apple.com")
return matches, nil
}
func MatchLinux(r *http.Request) (bool, error) {
// Samples
//
// http://start.ubuntu.com/connectivity-check.html
// http://nmcheck.gnome.org/check_network_status.txt
matches := strings.Contains(r.Host, "start.ubuntu.com") ||
strings.Contains(r.Host, "nmcheck.gnome.org")
return matches, nil
}
func MatchWindows(r *http.Request) (bool, error) {
// Samples
//
// http://www.msftncsi.com
// http://www.msftncsi.com/ncsi.txt
matches := strings.Contains(r.Host, "www.msftncsi.com")
return matches, nil
}
// nolint: gochecknoglobals
var defaultMatchers = map[OS]func(r *http.Request) (bool, error){
OSAndroid: MatchAndroid,
OSApple: MatchApple,
OSWindows: MatchWindows,
OSLinux: MatchLinux,
}
func DefaultMatch(r *http.Request) (bool, OS, error) {
for os, match := range defaultMatchers {
matches, err := match(r)
if err != nil {
return false, OSUnknown, errors.WithStack(err)
}
if matches {
return matches, os, nil
}
}
return false, OSUnknown, nil
}