feat: add rfc8908 basic api endpoint implementation
This commit is contained in:
parent
e8b8bbd952
commit
1cc263ca8b
2
go.mod
2
go.mod
|
@ -5,5 +5,5 @@ go 1.15
|
|||
require (
|
||||
github.com/irai/arp v1.3.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
gitlab.com/wpetit/goweb v0.0.0-20201116180841-b73723b5f552
|
||||
gitlab.com/wpetit/goweb v0.0.0-20210329100650-576d5f8548a3
|
||||
)
|
||||
|
|
10
go.sum
10
go.sum
|
@ -1,5 +1,5 @@
|
|||
cdr.dev/slog v1.3.0 h1:MYN1BChIaVEGxdS7I5cpdyMC0+WfJfK8BETAfzfLUGQ=
|
||||
cdr.dev/slog v1.3.0/go.mod h1:C5OL99WyuOK8YHZdYY57dAPN1jK2WJlCdq2VP6xeQns=
|
||||
cdr.dev/slog v1.4.0 h1:tLXQJ/hZ5Q051h0MBHSd2Ha8xzdXj7CjtzmG/8dUvUk=
|
||||
cdr.dev/slog v1.4.0/go.mod h1:C5OL99WyuOK8YHZdYY57dAPN1jK2WJlCdq2VP6xeQns=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
|
@ -127,10 +127,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
|
|||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
gitlab.com/wpetit/goweb v0.0.0-20201116180841-b73723b5f552 h1:gr3i9XNCVMlFZi5E88j8qAUlOpvUidMbVn11ho4x7eI=
|
||||
gitlab.com/wpetit/goweb v0.0.0-20201116180841-b73723b5f552/go.mod h1:Gfv7cBOw1T2XwXMsLm1d9kAjMAdNtLMjPv+yCzRO9qk=
|
||||
gitlab.com/wpetit/goweb v0.0.0-20210329100043-1c740f83992f h1:SBORCOoEnJ/JTCS71not8Qg36LKvt2Kqk8/7BqE+93c=
|
||||
gitlab.com/wpetit/goweb v0.0.0-20210329100043-1c740f83992f/go.mod h1:uLIkkm7YE+9mjPLzbCq2GkIiTRN9sJChrEAZjujpqv8=
|
||||
gitlab.com/wpetit/goweb v0.0.0-20210329100650-576d5f8548a3 h1:9RxyXeV01/vjaAnJb9qbwM5Y+uJQB3XkcvtuxguuIWY=
|
||||
gitlab.com/wpetit/goweb v0.0.0-20210329100650-576d5f8548a3/go.mod h1:4+weXRJy9RxDw7XnYGP3HrxNWaJhBDZKgiG1E+zRlqw=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs=
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package rfc8908
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type IsCaptiveFunc func(*http.Request) (bool, error)
|
||||
|
||||
// RFC8098
|
||||
// See https://tools.ietf.org/html/rfc8908 - "5. API State Structure"
|
||||
type Response struct {
|
||||
Captive bool `json:"captive"`
|
||||
UserPortalURL string `json:"user-portal-url,omitempty"`
|
||||
VenueInfoURL string `json:"venue-info-url,omitempty"`
|
||||
CanExtendSession *bool `json:"can-extend-session,omitempty"`
|
||||
SecondsRemaining *int `json:"seconds-remaining,omitempty"`
|
||||
BytesRemaining *int `json:"bytes-remaining,omitempty"`
|
||||
}
|
||||
|
||||
// Handler returns a basic implementation of a Captive Portal API endpoint
|
||||
// as described in the IETF 8908 RFC (https://tools.ietf.org/html/rfc8908)
|
||||
func Handler(isCaptive IsCaptiveFunc, opts ...OptionsFunc) http.HandlerFunc {
|
||||
options := DefaultOptions()
|
||||
|
||||
for _, o := range opts {
|
||||
o(options)
|
||||
}
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
isCaptive, err := isCaptive(r)
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "could not retrieve client id"))
|
||||
}
|
||||
|
||||
ctx := r.Context()
|
||||
|
||||
var bytesRemaining *int
|
||||
if options.BytesRemaining != nil {
|
||||
bytesRemaining, err = options.BytesRemaining(ctx)
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "could not retrieve client remaining bytes"))
|
||||
}
|
||||
}
|
||||
|
||||
var secondsRemaining *int
|
||||
if options.SecondsRemaining != nil {
|
||||
secondsRemaining, err = options.SecondsRemaining(ctx)
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "could not retrieve client remaining seconds"))
|
||||
}
|
||||
}
|
||||
|
||||
w.Header().Add("Content-Type", "application/captive+json")
|
||||
|
||||
encoder := json.NewEncoder(w)
|
||||
res := &Response{
|
||||
Captive: isCaptive,
|
||||
VenueInfoURL: options.VenueInfoURL,
|
||||
UserPortalURL: options.UserPortalURL,
|
||||
CanExtendSession: options.CanExtendSession,
|
||||
SecondsRemaining: secondsRemaining,
|
||||
BytesRemaining: bytesRemaining,
|
||||
}
|
||||
|
||||
if err := encoder.Encode(res); err != nil {
|
||||
panic(errors.WithStack(err))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package rfc8908
|
||||
|
||||
import "context"
|
||||
|
||||
type Options struct {
|
||||
UserPortalURL string
|
||||
VenueInfoURL string
|
||||
CanExtendSession *bool
|
||||
SecondsRemaining SecondsRemainingFunc
|
||||
BytesRemaining BytesRemainingFunc
|
||||
}
|
||||
|
||||
type OptionsFunc func(*Options)
|
||||
|
||||
type SecondsRemainingFunc func(context.Context) (*int, error)
|
||||
|
||||
type BytesRemainingFunc func(context.Context) (*int, error)
|
||||
|
||||
func DefaultOptions() *Options {
|
||||
return &Options{}
|
||||
}
|
||||
|
||||
func WithUserPortalURL(userPortalURL string) OptionsFunc {
|
||||
return func(o *Options) {
|
||||
o.UserPortalURL = userPortalURL
|
||||
}
|
||||
}
|
||||
|
||||
func WithVenueInfoURL(venueInfoURL string) OptionsFunc {
|
||||
return func(o *Options) {
|
||||
o.VenueInfoURL = venueInfoURL
|
||||
}
|
||||
}
|
||||
|
||||
func WithCanExtendSession(canExtend bool) OptionsFunc {
|
||||
return func(o *Options) {
|
||||
o.CanExtendSession = &canExtend
|
||||
}
|
||||
}
|
||||
|
||||
func WithSecondsRemainingFunc(fn SecondsRemainingFunc) OptionsFunc {
|
||||
return func(o *Options) {
|
||||
o.SecondsRemaining = fn
|
||||
}
|
||||
}
|
||||
|
||||
func WithBytesRemainingFunc(fn BytesRemainingFunc) OptionsFunc {
|
||||
return func(o *Options) {
|
||||
o.BytesRemaining = fn
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue