Rename rw, req to w, r
This commit is contained in:
parent
67842c6425
commit
faf94d8ba5
12
doc.go
12
doc.go
|
@ -64,14 +64,14 @@ Servers must be configured with certificates:
|
||||||
|
|
||||||
Servers can accept requests for multiple hosts and schemes:
|
Servers can accept requests for multiple hosts and schemes:
|
||||||
|
|
||||||
server.HandleFunc("example.com", func(rw *gmi.ResponseWriter, req *gmi.Request) {
|
server.HandleFunc("example.com", func(w *gmi.ResponseWriter, r *gmi.Request) {
|
||||||
fmt.Fprint(rw, "Welcome to example.com")
|
fmt.Fprint(w, "Welcome to example.com")
|
||||||
})
|
})
|
||||||
server.HandleFunc("example.org", func(rw *gmi.ResponseWriter, req *gmi.Request) {
|
server.HandleFunc("example.org", func(w *gmi.ResponseWriter, r *gmi.Request) {
|
||||||
fmt.Fprint(rw, "Welcome to example.org")
|
fmt.Fprint(w, "Welcome to example.org")
|
||||||
})
|
})
|
||||||
server.HandleSchemeFunc("http", "example.net", func(rw *gmi.ResponseWriter, req *gmi.Request) {
|
server.HandleSchemeFunc("http", "example.net", func(w *gmi.ResponseWriter, r *gmi.Request) {
|
||||||
fmt.Fprint(rw, "Proxied content from example.net")
|
fmt.Fprint(w, "Proxied content from example.net")
|
||||||
})
|
})
|
||||||
|
|
||||||
To start the server, call ListenAndServe:
|
To start the server, call ListenAndServe:
|
||||||
|
|
|
@ -58,75 +58,75 @@ func getSession(crt *x509.Certificate) (*session, bool) {
|
||||||
return session, ok
|
return session, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func welcome(rw *gmi.ResponseWriter, req *gmi.Request) {
|
func welcome(w *gmi.ResponseWriter, r *gmi.Request) {
|
||||||
rw.Write([]byte("Welcome to this example.\n=> /login Login\n"))
|
w.Write([]byte("Welcome to this example.\n=> /login Login\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func login(rw *gmi.ResponseWriter, req *gmi.Request) {
|
func login(w *gmi.ResponseWriter, r *gmi.Request) {
|
||||||
gmi.WithCertificate(rw, req, func(cert *x509.Certificate) {
|
gmi.WithCertificate(w, r, func(cert *x509.Certificate) {
|
||||||
gmi.WithInput(rw, req, "Username", func(username string) {
|
gmi.WithInput(w, r, "Username", func(username string) {
|
||||||
fingerprint := gmi.Fingerprint(cert)
|
fingerprint := gmi.Fingerprint(cert)
|
||||||
sessions[fingerprint] = &session{
|
sessions[fingerprint] = &session{
|
||||||
username: username,
|
username: username,
|
||||||
}
|
}
|
||||||
gmi.Redirect(rw, req, "/login/password")
|
gmi.Redirect(w, r, "/login/password")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func loginPassword(rw *gmi.ResponseWriter, req *gmi.Request) {
|
func loginPassword(w *gmi.ResponseWriter, r *gmi.Request) {
|
||||||
gmi.WithCertificate(rw, req, func(cert *x509.Certificate) {
|
gmi.WithCertificate(w, r, func(cert *x509.Certificate) {
|
||||||
session, ok := getSession(cert)
|
session, ok := getSession(cert)
|
||||||
if !ok {
|
if !ok {
|
||||||
gmi.CertificateNotAuthorized(rw, req)
|
gmi.CertificateNotAuthorized(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
gmi.WithSensitiveInput(rw, req, "Password", func(password string) {
|
gmi.WithSensitiveInput(w, r, "Password", func(password string) {
|
||||||
expected := logins[session.username].password
|
expected := logins[session.username].password
|
||||||
if password == expected {
|
if password == expected {
|
||||||
session.authorized = true
|
session.authorized = true
|
||||||
gmi.Redirect(rw, req, "/profile")
|
gmi.Redirect(w, r, "/profile")
|
||||||
} else {
|
} else {
|
||||||
gmi.SensitiveInput(rw, req, "Wrong password. Try again")
|
gmi.SensitiveInput(w, r, "Wrong password. Try again")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func logout(rw *gmi.ResponseWriter, req *gmi.Request) {
|
func logout(w *gmi.ResponseWriter, r *gmi.Request) {
|
||||||
gmi.WithCertificate(rw, req, func(cert *x509.Certificate) {
|
gmi.WithCertificate(w, r, func(cert *x509.Certificate) {
|
||||||
fingerprint := gmi.Fingerprint(cert)
|
fingerprint := gmi.Fingerprint(cert)
|
||||||
delete(sessions, fingerprint)
|
delete(sessions, fingerprint)
|
||||||
})
|
})
|
||||||
rw.Write([]byte("Successfully logged out.\n"))
|
w.Write([]byte("Successfully logged out.\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func profile(rw *gmi.ResponseWriter, req *gmi.Request) {
|
func profile(w *gmi.ResponseWriter, r *gmi.Request) {
|
||||||
gmi.WithCertificate(rw, req, func(cert *x509.Certificate) {
|
gmi.WithCertificate(w, r, func(cert *x509.Certificate) {
|
||||||
session, ok := getSession(cert)
|
session, ok := getSession(cert)
|
||||||
if !ok {
|
if !ok {
|
||||||
gmi.CertificateNotAuthorized(rw, req)
|
gmi.CertificateNotAuthorized(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user := logins[session.username]
|
user := logins[session.username]
|
||||||
profile := fmt.Sprintf("Username: %s\nAdmin: %t\n=> /logout Logout", session.username, user.admin)
|
profile := fmt.Sprintf("Username: %s\nAdmin: %t\n=> /logout Logout", session.username, user.admin)
|
||||||
rw.Write([]byte(profile))
|
w.Write([]byte(profile))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func admin(rw *gmi.ResponseWriter, req *gmi.Request) {
|
func admin(w *gmi.ResponseWriter, r *gmi.Request) {
|
||||||
gmi.WithCertificate(rw, req, func(cert *x509.Certificate) {
|
gmi.WithCertificate(w, r, func(cert *x509.Certificate) {
|
||||||
session, ok := getSession(cert)
|
session, ok := getSession(cert)
|
||||||
if !ok {
|
if !ok {
|
||||||
gmi.CertificateNotAuthorized(rw, req)
|
gmi.CertificateNotAuthorized(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user := logins[session.username]
|
user := logins[session.username]
|
||||||
if !user.admin {
|
if !user.admin {
|
||||||
gmi.CertificateNotAuthorized(rw, req)
|
gmi.CertificateNotAuthorized(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rw.Write([]byte("Welcome to the admin portal.\n"))
|
w.Write([]byte("Welcome to the admin portal.\n"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
10
fs.go
10
fs.go
|
@ -24,19 +24,19 @@ type fsHandler struct {
|
||||||
FS
|
FS
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fsh fsHandler) Serve(rw *ResponseWriter, req *Request) {
|
func (fsh fsHandler) Serve(w *ResponseWriter, r *Request) {
|
||||||
path := path.Clean(req.URL.Path)
|
path := path.Clean(r.URL.Path)
|
||||||
f, err := fsh.Open(path)
|
f, err := fsh.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
NotFound(rw, req)
|
NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Detect mimetype
|
// Detect mimetype
|
||||||
ext := filepath.Ext(path)
|
ext := filepath.Ext(path)
|
||||||
mimetype := mime.TypeByExtension(ext)
|
mimetype := mime.TypeByExtension(ext)
|
||||||
rw.SetMimetype(mimetype)
|
w.SetMimetype(mimetype)
|
||||||
// Copy file to response writer
|
// Copy file to response writer
|
||||||
io.Copy(rw, f)
|
io.Copy(w, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace with io/fs.FS when available
|
// TODO: replace with io/fs.FS when available
|
||||||
|
|
92
server.go
92
server.go
|
@ -199,7 +199,7 @@ func (r *ResponseWriter) Write(b []byte) (int, error) {
|
||||||
// respond responds to a connection.
|
// respond responds to a connection.
|
||||||
func (s *Server) respond(conn net.Conn) {
|
func (s *Server) respond(conn net.Conn) {
|
||||||
r := bufio.NewReader(conn)
|
r := bufio.NewReader(conn)
|
||||||
rw := newResponseWriter(conn)
|
w := newResponseWriter(conn)
|
||||||
// Read requested URL
|
// Read requested URL
|
||||||
rawurl, err := r.ReadString('\r')
|
rawurl, err := r.ReadString('\r')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -209,16 +209,16 @@ func (s *Server) respond(conn net.Conn) {
|
||||||
if b, err := r.ReadByte(); err != nil {
|
if b, err := r.ReadByte(); err != nil {
|
||||||
return
|
return
|
||||||
} else if b != '\n' {
|
} else if b != '\n' {
|
||||||
rw.WriteHeader(StatusBadRequest, "Bad request")
|
w.WriteHeader(StatusBadRequest, "Bad request")
|
||||||
}
|
}
|
||||||
// Trim carriage return
|
// Trim carriage return
|
||||||
rawurl = rawurl[:len(rawurl)-1]
|
rawurl = rawurl[:len(rawurl)-1]
|
||||||
// Ensure URL is valid
|
// Ensure URL is valid
|
||||||
if len(rawurl) > 1024 {
|
if len(rawurl) > 1024 {
|
||||||
rw.WriteHeader(StatusBadRequest, "Bad request")
|
w.WriteHeader(StatusBadRequest, "Bad request")
|
||||||
} else if url, err := url.Parse(rawurl); err != nil || url.User != nil {
|
} else if url, err := url.Parse(rawurl); err != nil || url.User != nil {
|
||||||
// Note that we return an error status if User is specified in the URL
|
// Note that we return an error status if User is specified in the URL
|
||||||
rw.WriteHeader(StatusBadRequest, "Bad request")
|
w.WriteHeader(StatusBadRequest, "Bad request")
|
||||||
} else {
|
} else {
|
||||||
// Gather information about the request
|
// Gather information about the request
|
||||||
req := &Request{
|
req := &Request{
|
||||||
|
@ -226,14 +226,14 @@ func (s *Server) respond(conn net.Conn) {
|
||||||
RemoteAddr: conn.RemoteAddr(),
|
RemoteAddr: conn.RemoteAddr(),
|
||||||
TLS: conn.(*tls.Conn).ConnectionState(),
|
TLS: conn.(*tls.Conn).ConnectionState(),
|
||||||
}
|
}
|
||||||
s.handler(req).Serve(rw, req)
|
s.handler(req).Serve(w, req)
|
||||||
}
|
}
|
||||||
rw.w.Flush()
|
w.w.Flush()
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handler(req *Request) Handler {
|
func (s *Server) handler(r *Request) Handler {
|
||||||
if h, ok := s.handlers[handlerKey{req.URL.Scheme, req.URL.Hostname()}]; ok {
|
if h, ok := s.handlers[handlerKey{r.URL.Scheme, r.URL.Hostname()}]; ok {
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
return NotFoundHandler()
|
return NotFoundHandler()
|
||||||
|
@ -246,24 +246,24 @@ type Handler interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input responds to the request with a request for input using the given prompt.
|
// Input responds to the request with a request for input using the given prompt.
|
||||||
func Input(rw *ResponseWriter, req *Request, prompt string) {
|
func Input(w *ResponseWriter, r *Request, prompt string) {
|
||||||
rw.WriteHeader(StatusInput, prompt)
|
w.WriteHeader(StatusInput, prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InputHandler returns a simple handler that responds to each request with
|
// InputHandler returns a simple handler that responds to each request with
|
||||||
// a request for input.
|
// a request for input.
|
||||||
func InputHandler(prompt string) Handler {
|
func InputHandler(prompt string) Handler {
|
||||||
return HandlerFunc(func(rw *ResponseWriter, req *Request) {
|
return HandlerFunc(func(w *ResponseWriter, r *Request) {
|
||||||
Input(rw, req, prompt)
|
Input(w, r, prompt)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithInput either responds to the request with StatusInput if no input
|
// WithInput either responds to the request with StatusInput if no input
|
||||||
// is provided, or calls f with the input when provided.
|
// is provided, or calls f with the input when provided.
|
||||||
func WithInput(rw *ResponseWriter, req *Request, prompt string, f func(string)) {
|
func WithInput(w *ResponseWriter, r *Request, prompt string, f func(string)) {
|
||||||
input := req.URL.RawQuery
|
input := r.URL.RawQuery
|
||||||
if input == "" {
|
if input == "" {
|
||||||
Input(rw, req, prompt)
|
Input(w, r, prompt)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f(input)
|
f(input)
|
||||||
|
@ -271,58 +271,58 @@ func WithInput(rw *ResponseWriter, req *Request, prompt string, f func(string))
|
||||||
|
|
||||||
// Sensitive responds to the request with a request for sensitive input
|
// Sensitive responds to the request with a request for sensitive input
|
||||||
// using the given prompt.
|
// using the given prompt.
|
||||||
func SensitiveInput(rw *ResponseWriter, req *Request, prompt string) {
|
func SensitiveInput(w *ResponseWriter, r *Request, prompt string) {
|
||||||
rw.WriteHeader(StatusSensitiveInput, prompt)
|
w.WriteHeader(StatusSensitiveInput, prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SensitiveInputHandler returns a simpler handler that responds to each request
|
// SensitiveInputHandler returns a simpler handler that responds to each request
|
||||||
// with a request for sensitive input.
|
// with a request for sensitive input.
|
||||||
func SensitiveInputHandler(prompt string) Handler {
|
func SensitiveInputHandler(prompt string) Handler {
|
||||||
return HandlerFunc(func(rw *ResponseWriter, req *Request) {
|
return HandlerFunc(func(w *ResponseWriter, r *Request) {
|
||||||
SensitiveInput(rw, req, prompt)
|
SensitiveInput(w, r, prompt)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithSensitiveInput either responds to the request with StatusSensitiveInput
|
// WithSensitiveInput either responds to the request with StatusSensitiveInput
|
||||||
// if no input is provided, or calls f with the input when provided.
|
// if no input is provided, or calls f with the input when provided.
|
||||||
func WithSensitiveInput(rw *ResponseWriter, req *Request, prompt string, f func(string)) {
|
func WithSensitiveInput(w *ResponseWriter, r *Request, prompt string, f func(string)) {
|
||||||
input := req.URL.RawQuery
|
input := r.URL.RawQuery
|
||||||
if input == "" {
|
if input == "" {
|
||||||
SensitiveInput(rw, req, prompt)
|
SensitiveInput(w, r, prompt)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f(input)
|
f(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect replies to the request with a redirect to the given URL.
|
// Redirect replies to the request with a redirect to the given URL.
|
||||||
func Redirect(rw *ResponseWriter, req *Request, url string) {
|
func Redirect(w *ResponseWriter, r *Request, url string) {
|
||||||
rw.WriteHeader(StatusRedirect, url)
|
w.WriteHeader(StatusRedirect, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedirectHandler returns a simple handler that responds to each request with
|
// RedirectHandler returns a simple handler that responds to each request with
|
||||||
// a redirect to the given URL.
|
// a redirect to the given URL.
|
||||||
func RedirectHandler(url string) Handler {
|
func RedirectHandler(url string) Handler {
|
||||||
return HandlerFunc(func(rw *ResponseWriter, req *Request) {
|
return HandlerFunc(func(w *ResponseWriter, r *Request) {
|
||||||
Redirect(rw, req, url)
|
Redirect(w, r, url)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// PermanentRedirect replies to the request with a permanent redirect to the given URL.
|
// PermanentRedirect replies to the request with a permanent redirect to the given URL.
|
||||||
func PermanentRedirect(rw *ResponseWriter, req *Request, url string) {
|
func PermanentRedirect(w *ResponseWriter, r *Request, url string) {
|
||||||
rw.WriteHeader(StatusRedirectPermanent, url)
|
w.WriteHeader(StatusRedirectPermanent, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PermanentRedirectHandler returns a simple handler that responds to each request with
|
// PermanentRedirectHandler returns a simple handler that responds to each request with
|
||||||
// a redirect to the given URL.
|
// a redirect to the given URL.
|
||||||
func PermanentRedirectHandler(url string) Handler {
|
func PermanentRedirectHandler(url string) Handler {
|
||||||
return HandlerFunc(func(rw *ResponseWriter, req *Request) {
|
return HandlerFunc(func(w *ResponseWriter, r *Request) {
|
||||||
PermanentRedirect(rw, req, url)
|
PermanentRedirect(w, r, url)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotFound replies to the request with the NotFound status code.
|
// NotFound replies to the request with the NotFound status code.
|
||||||
func NotFound(rw *ResponseWriter, req *Request) {
|
func NotFound(w *ResponseWriter, r *Request) {
|
||||||
rw.WriteHeader(StatusNotFound, "Not found")
|
w.WriteHeader(StatusNotFound, "Not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotFoundHandler returns a simple handler that responds to each request with
|
// NotFoundHandler returns a simple handler that responds to each request with
|
||||||
|
@ -332,8 +332,8 @@ func NotFoundHandler() Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gone replies to the request with the Gone status code.
|
// Gone replies to the request with the Gone status code.
|
||||||
func Gone(rw *ResponseWriter, req *Request) {
|
func Gone(w *ResponseWriter, r *Request) {
|
||||||
rw.WriteHeader(StatusGone, "Gone")
|
w.WriteHeader(StatusGone, "Gone")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoneHandler returns a simple handler that responds to each request with
|
// GoneHandler returns a simple handler that responds to each request with
|
||||||
|
@ -344,24 +344,24 @@ func GoneHandler() Handler {
|
||||||
|
|
||||||
// CertificateRequired responds to the request with the CertificateRequired
|
// CertificateRequired responds to the request with the CertificateRequired
|
||||||
// status code.
|
// status code.
|
||||||
func CertificateRequired(rw *ResponseWriter, req *Request) {
|
func CertificateRequired(w *ResponseWriter, r *Request) {
|
||||||
rw.WriteHeader(StatusCertificateRequired, "Certificate required")
|
w.WriteHeader(StatusCertificateRequired, "Certificate required")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CertificateNotAuthorized responds to the request with
|
// CertificateNotAuthorized responds to the request with
|
||||||
// the CertificateNotAuthorized status code.
|
// the CertificateNotAuthorized status code.
|
||||||
func CertificateNotAuthorized(rw *ResponseWriter, req *Request) {
|
func CertificateNotAuthorized(w *ResponseWriter, r *Request) {
|
||||||
rw.WriteHeader(StatusCertificateNotAuthorized, "Certificate not authorized")
|
w.WriteHeader(StatusCertificateNotAuthorized, "Certificate not authorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithCertificate either responds with CertificateRequired if the client did
|
// WithCertificate either responds with CertificateRequired if the client did
|
||||||
// not provide a certificate, or calls f with the first ceritificate provided.
|
// not provide a certificate, or calls f with the first ceritificate provided.
|
||||||
func WithCertificate(rw *ResponseWriter, req *Request, f func(*x509.Certificate)) {
|
func WithCertificate(w *ResponseWriter, r *Request, f func(*x509.Certificate)) {
|
||||||
if len(req.TLS.PeerCertificates) == 0 {
|
if len(r.TLS.PeerCertificates) == 0 {
|
||||||
CertificateRequired(rw, req)
|
CertificateRequired(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cert := req.TLS.PeerCertificates[0]
|
cert := r.TLS.PeerCertificates[0]
|
||||||
f(cert)
|
f(cert)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,16 +369,16 @@ func WithCertificate(rw *ResponseWriter, req *Request, f func(*x509.Certificate)
|
||||||
// clients if they did not provide one, and calls f with the first certificate
|
// clients if they did not provide one, and calls f with the first certificate
|
||||||
// if they did.
|
// if they did.
|
||||||
func CertificateHandler(f func(*x509.Certificate)) Handler {
|
func CertificateHandler(f func(*x509.Certificate)) Handler {
|
||||||
return HandlerFunc(func(rw *ResponseWriter, req *Request) {
|
return HandlerFunc(func(w *ResponseWriter, r *Request) {
|
||||||
WithCertificate(rw, req, f)
|
WithCertificate(w, r, f)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandlerFunc is a wrapper around a bare function that implements Handler.
|
// HandlerFunc is a wrapper around a bare function that implements Handler.
|
||||||
type HandlerFunc func(*ResponseWriter, *Request)
|
type HandlerFunc func(*ResponseWriter, *Request)
|
||||||
|
|
||||||
func (f HandlerFunc) Serve(rw *ResponseWriter, req *Request) {
|
func (f HandlerFunc) Serve(w *ResponseWriter, r *Request) {
|
||||||
f(rw, req)
|
f(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following code is modified from the net/http package.
|
// The following code is modified from the net/http package.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user