fix some bugs and make middleware work
This commit is contained in:
parent
1a755192fb
commit
5541785463
2 changed files with 47 additions and 18 deletions
|
@ -52,8 +52,13 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
URL *url.URL
|
URL *url.URL
|
||||||
|
RemoteAddr string
|
||||||
|
|
||||||
|
// RequestURI is the unmodified request-target of the Request-Line as sent by the client
|
||||||
|
// to a server. Usually the URL field should be used instead.
|
||||||
|
RequestURI string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
|
@ -135,7 +140,12 @@ func (s *Server) handleConnection(conn net.Conn, sem chan struct{}) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
r := &Request{ctx: ctx, URL: header.URL}
|
r := &Request{
|
||||||
|
ctx: ctx,
|
||||||
|
URL: header.URL,
|
||||||
|
RequestURI: header.rawuri,
|
||||||
|
RemoteAddr: conn.RemoteAddr().String(),
|
||||||
|
}
|
||||||
s.Handler.ServeGemini(conn, r)
|
s.Handler.ServeGemini(conn, r)
|
||||||
case <-time.After(s.ReadTimeout):
|
case <-time.After(s.ReadTimeout):
|
||||||
WriteHeader(conn, StatusServerUnavailable, "")
|
WriteHeader(conn, StatusServerUnavailable, "")
|
||||||
|
@ -157,48 +167,54 @@ func (s *Server) handleRequestError(conn net.Conn, req request) {
|
||||||
// conn handler
|
// conn handler
|
||||||
|
|
||||||
type request struct {
|
type request struct {
|
||||||
URL *url.URL
|
rawuri string
|
||||||
err error
|
URL *url.URL
|
||||||
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestChannel(c net.Conn, rsp chan request) {
|
func requestChannel(c net.Conn, rsp chan request) {
|
||||||
u, err := readHeader(c)
|
r, err := readHeader(c)
|
||||||
rsp <- request{u, err}
|
r.err = err
|
||||||
|
rsp <- *r
|
||||||
}
|
}
|
||||||
|
|
||||||
func readHeader(c net.Conn) (*url.URL, error) {
|
func readHeader(c net.Conn) (*request, error) {
|
||||||
|
r := &request{}
|
||||||
req, err := bufio.NewReader(c).ReadString('\r')
|
req, err := bufio.NewReader(c).ReadString('\r')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Error(StatusTemporaryFailure, errors.New("error reading request"))
|
return nil, Error(StatusTemporaryFailure, errors.New("error reading request"))
|
||||||
}
|
}
|
||||||
|
r.rawuri = req
|
||||||
|
|
||||||
requestURL := strings.TrimSpace(req)
|
requestURL := strings.TrimSpace(req)
|
||||||
if requestURL == "" {
|
if requestURL == "" {
|
||||||
return nil, Error(StatusBadRequest, errors.New("empty request URL"))
|
return r, Error(StatusBadRequest, errors.New("empty request URL"))
|
||||||
} else if !utf8.ValidString(requestURL) {
|
} else if !utf8.ValidString(requestURL) {
|
||||||
return nil, Error(StatusBadRequest, errors.New("not a valid utf-8 url"))
|
return r, Error(StatusBadRequest, errors.New("not a valid utf-8 url"))
|
||||||
} else if len(requestURL) > URLMaxBytes {
|
} else if len(requestURL) > URLMaxBytes {
|
||||||
return nil, Error(StatusBadRequest, ErrHeaderTooLong)
|
return r, Error(StatusBadRequest, ErrHeaderTooLong)
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedURL, err := url.Parse(requestURL)
|
parsedURL, err := url.Parse(requestURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Error(StatusBadRequest, err)
|
return r, Error(StatusBadRequest, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r.URL = parsedURL
|
||||||
|
|
||||||
if parsedURL.Scheme != "" && parsedURL.Scheme != "gemini" {
|
if parsedURL.Scheme != "" && parsedURL.Scheme != "gemini" {
|
||||||
return nil, Error(StatusProxyRequestRefused, fmt.Errorf("unknown protocol scheme %s", parsedURL.Scheme))
|
return r, Error(StatusProxyRequestRefused, fmt.Errorf("unknown protocol scheme %s", parsedURL.Scheme))
|
||||||
} else if parsedURL.Host == "" {
|
} else if parsedURL.Host == "" {
|
||||||
return nil, Error(StatusBadRequest, errors.New("empty host"))
|
return r, Error(StatusBadRequest, errors.New("empty host"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsedURL.Path == "" {
|
if parsedURL.Path == "" {
|
||||||
return nil, Error(StatusRedirectPermanent, errors.New("./"+parsedURL.Path))
|
return r, Error(StatusRedirectPermanent, errors.New("./"+parsedURL.Path))
|
||||||
} else if parsedURL.Path != path.Clean(parsedURL.Path) {
|
} else if parsedURL.Path != path.Clean(parsedURL.Path) {
|
||||||
return nil, Error(StatusBadRequest, errors.New("path error"))
|
return r, Error(StatusBadRequest, errors.New("path error"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsedURL, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Shutdown(ctx context.Context) error {
|
func (s *Server) Shutdown(ctx context.Context) error {
|
||||||
|
|
15
main.go
15
main.go
|
@ -11,6 +11,7 @@ import (
|
||||||
"mime"
|
"mime"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/n0x1m/gmifs/gemini"
|
"github.com/n0x1m/gmifs/gemini"
|
||||||
|
@ -112,7 +113,19 @@ func main() {
|
||||||
|
|
||||||
func logger(next gemini.Handler) gemini.Handler {
|
func logger(next gemini.Handler) gemini.Handler {
|
||||||
fn := func(w io.Writer, r *gemini.Request) {
|
fn := func(w io.Writer, r *gemini.Request) {
|
||||||
log.Println(r.URL)
|
t := time.Now()
|
||||||
|
|
||||||
|
next.ServeGemini(w, r)
|
||||||
|
|
||||||
|
ip := strings.Split(r.RemoteAddr, ":")[0]
|
||||||
|
hostname, _ := os.Hostname()
|
||||||
|
fmt.Printf("%s %s - - [%s] \"%s\" - %v\n",
|
||||||
|
hostname,
|
||||||
|
ip,
|
||||||
|
t.Format("02/Jan/2006:15:04:05 -0700"),
|
||||||
|
r.URL.Path,
|
||||||
|
time.Since(t),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return gemini.HandlerFunc(fn)
|
return gemini.HandlerFunc(fn)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue