Skip to content

Commit

Permalink
minor internal updates. Fixed returning nil from OnError in router
Browse files Browse the repository at this point in the history
  • Loading branch information
flrdv committed Feb 18, 2024
1 parent 2402ca0 commit 037aca9
Showing 1 changed file with 33 additions and 33 deletions.
66 changes: 33 additions & 33 deletions internal/server/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,46 @@ package http

import (
"bytes"
"errors"
"fmt"
"github.com/indigo-web/indigo/config"
"github.com/indigo-web/indigo/http"
"github.com/indigo-web/indigo/http/proto"
"github.com/indigo-web/indigo/http/status"
"github.com/indigo-web/indigo/internal/server/tcp"
"github.com/indigo-web/indigo/internal/transport"
"github.com/indigo-web/indigo/router"
"github.com/indigo-web/indigo/settings"
"github.com/indigo-web/utils/uf"
"os"
)

type Server struct {
router router.Router
upgradePreResp *http.Response
onDisconnect settings.OnDisconnectCallback
onDisconnect config.OnDisconnectCallback
}

func NewServer(router router.Router, onDisconnect settings.OnDisconnectCallback) *Server {
func NewServer(router router.Router, onDisconnect config.OnDisconnectCallback) *Server {
return &Server{
router: router,
upgradePreResp: http.NewResponse(),
onDisconnect: onDisconnect,
}
}

func (h *Server) Run(client tcp.Client, req *http.Request, trans transport.Transport) {
for h.HandleRequest(client, req, trans) {
func (s *Server) Run(client tcp.Client, req *http.Request, trans transport.Transport) {
for s.HandleRequest(client, req, trans) {
}

if h.onDisconnect != nil {
_ = trans.Write(req.Proto, req, h.onDisconnect(req), client)
if s.onDisconnect != nil {
_ = trans.Write(req.Proto, req, s.onDisconnect(req), client)
}

_ = client.Close()
}

func (h *Server) HandleRequest(client tcp.Client, req *http.Request, trans transport.Transport) (ok bool) {
func (s *Server) HandleRequest(client tcp.Client, req *http.Request, trans transport.Transport) (ok bool) {
data, err := client.Read()
if err != nil {
if errors.Is(err, os.ErrDeadlineExceeded) {
return false
}

// TODO: maybe, passing the err as-is would be a better solution? However, in this case it'll
// be more difficult to recognize what exact kind of error that is.
_ = trans.Write(req.Proto, req, h.router.OnError(req, status.ErrCloseConnection), client)
_ = trans.Write(req.Proto, req, s.onError(req, err), client)
return false
}

Expand All @@ -63,7 +55,7 @@ func (h *Server) HandleRequest(client tcp.Client, req *http.Request, trans trans
protoToken := uf.B2S(bytes.TrimSpace(proto.ToBytes(req.Upgrade)))
trans.PreWrite(
req.Proto,
h.upgradePreResp.
s.upgradePreResp.
Code(status.SwitchingProtocols).
Header("Connection", "upgrade").
Header("Upgrade", protoToken),
Expand All @@ -73,39 +65,47 @@ func (h *Server) HandleRequest(client tcp.Client, req *http.Request, trans trans

client.Unread(extra)
req.Body.Init(req)
response := h.router.OnRequest(req)
if response == nil {
response = req.Respond()
}

if req.WasHijacked() {
return false
}

if err = trans.Write(protocol, req, response, client); err != nil {
// in case we failed to render the response, just close the connection silently.
// This may affect cases, when the error occurred during rendering an attachment,
// but server anyway cannot recognize them, so the only thing will be done here
// is notifying the router about disconnection
h.router.OnError(req, status.ErrCloseConnection)
if err = trans.Write(protocol, req, s.onRequest(req), client); err != nil {
// if error happened during writing the response, it makes no sense to try
// to write anything again
s.onError(req, status.ErrCloseConnection)
return false
}

if err = req.Clear(); err != nil {
// abusing the fact, that req.Clear() will return an error ONLY if socket error
// occurred while reading.
// TODO: what's if the error lays in decoding? This should somehow be processed
h.router.OnError(req, status.ErrCloseConnection)
// abusing the fact that req.Clear() can fail only due to read error
s.onError(req, status.ErrCloseConnection)
return false
}
case transport.Error:
// as fatal error already happened and connection will anyway be closed, we don't
// care about any socket errors anymore
_ = trans.Write(req.Proto, req, h.router.OnError(req, err), client)
_ = trans.Write(req.Proto, req, s.onError(req, err), client)
return false
default:
panic(fmt.Sprintf("BUG: got unexpected parser state"))
}

return true
}

func (s *Server) onError(req *http.Request, err error) *http.Response {
return notNil(req, s.router.OnError(req, err))
}

func (s *Server) onRequest(req *http.Request) *http.Response {
return notNil(req, s.router.OnRequest(req))
}

func notNil(req *http.Request, resp *http.Response) *http.Response {
if resp != nil {
return resp
}

return http.Respond(req)
}

0 comments on commit 037aca9

Please sign in to comment.