mhttp: implement MListenAndServe, using new mctx/mrun/mcfg framework
This commit is contained in:
parent
a0a531cdd2
commit
ef2e76de45
@ -10,35 +10,47 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mediocregopher/mediocre-go-lib/m"
|
"github.com/mediocregopher/mediocre-go-lib/mctx"
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mcfg"
|
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mlog"
|
"github.com/mediocregopher/mediocre-go-lib/mlog"
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mnet"
|
"github.com/mediocregopher/mediocre-go-lib/mnet"
|
||||||
|
"github.com/mediocregopher/mediocre-go-lib/mrun"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CfgServer initializes and returns an *http.Server which will initialize on
|
// MListenAndServe returns an http.Server which will be initialized and have
|
||||||
// the Start hook. This also sets up config params for configuring the address
|
// ListenAndServe called on it (asynchronously) when the start event is
|
||||||
// being listened on.
|
// triggered on ctx (see mrun.Start). The Server will have Shutdown called on it
|
||||||
func CfgServer(cfg *mcfg.Cfg, h http.Handler) *http.Server {
|
// when the stop event is triggered on ctx (see mrun.Stop).
|
||||||
cfg = cfg.Child("http")
|
//
|
||||||
addr := cfg.ParamString("addr", ":0", "Address to listen on. Default is any open port")
|
// This function automatically handles setting up configuration parameters via
|
||||||
|
// mcfg. The default listen address is ":0".
|
||||||
|
func MListenAndServe(ctx mctx.Context, h http.Handler) *http.Server {
|
||||||
|
ctx = mctx.ChildOf(ctx, "http")
|
||||||
|
listener := mnet.MListen(ctx, "tcp", "")
|
||||||
|
listener.NoCloseOnStop = true // http.Server.Shutdown will do this
|
||||||
|
logger := mlog.From(ctx).WithKV(listener)
|
||||||
|
|
||||||
srv := http.Server{Handler: h}
|
srv := http.Server{Handler: h}
|
||||||
cfg.Start.Then(func(ctx context.Context) error {
|
mrun.OnStart(ctx, func(mctx.Context) error {
|
||||||
srv.Addr = *addr
|
srv.Addr = listener.Addr().String()
|
||||||
kv := mlog.KV{"addr": *addr}
|
mrun.Thread(ctx, func() error {
|
||||||
log := m.Log(cfg, kv)
|
if err := srv.Serve(listener); err != http.ErrServerClosed {
|
||||||
log.Info("listening")
|
logger.Error("error serving listener", merr.KV(err))
|
||||||
go func() {
|
return err
|
||||||
err := srv.ListenAndServe()
|
}
|
||||||
// TODO the listening log should happen here, somehow, now that we
|
return nil
|
||||||
// know the actual address being listened on
|
})
|
||||||
log.Fatal("http server fataled", mlog.ErrKV(err))
|
|
||||||
}()
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO shutdown logic
|
mrun.OnStop(ctx, func(innerCtx mctx.Context) error {
|
||||||
|
logger.Info("shutting down server")
|
||||||
|
if err := srv.Shutdown(context.Context(innerCtx)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return mrun.Wait(ctx, innerCtx.Done())
|
||||||
|
})
|
||||||
|
|
||||||
return &srv
|
return &srv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,51 @@
|
|||||||
package mhttp
|
package mhttp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
. "testing"
|
. "testing"
|
||||||
|
|
||||||
|
"github.com/mediocregopher/mediocre-go-lib/mctx"
|
||||||
|
"github.com/mediocregopher/mediocre-go-lib/mlog"
|
||||||
|
"github.com/mediocregopher/mediocre-go-lib/mrun"
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mtest/massert"
|
"github.com/mediocregopher/mediocre-go-lib/mtest/massert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestMListenAndServe(t *T) {
|
||||||
|
ctx := mctx.ChildOf(mctx.New(), "test")
|
||||||
|
mlog.CtxSet(ctx, mlog.From(ctx).WithMaxLevel(mlog.DebugLevel))
|
||||||
|
|
||||||
|
h := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
io.Copy(rw, r.Body)
|
||||||
|
})
|
||||||
|
|
||||||
|
srv := MListenAndServe(ctx, h)
|
||||||
|
if err := mrun.Start(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
body := bytes.NewBufferString("HELLO")
|
||||||
|
resp, err := http.Post("http://"+srv.Addr, "text/plain", body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
respBody, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if string(respBody) != "HELLO" {
|
||||||
|
t.Fatalf("unexpected respBody: %q", respBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mrun.Stop(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAddXForwardedFor(t *T) {
|
func TestAddXForwardedFor(t *T) {
|
||||||
assertXFF := func(prev []string, ipStr, expected string) massert.Assertion {
|
assertXFF := func(prev []string, ipStr, expected string) massert.Assertion {
|
||||||
r := httptest.NewRequest("GET", "/", nil)
|
r := httptest.NewRequest("GET", "/", nil)
|
||||||
|
Loading…
Reference in New Issue
Block a user