diff --git a/context/configuration.go b/context/configuration.go index 43ffec3e..c67a87cb 100644 --- a/context/configuration.go +++ b/context/configuration.go @@ -4,6 +4,11 @@ package context +// ConfigurationReadOnly can be implemented +// by Configuration, it's being used inside the Context. +// All methods that it contains should be "safe" to be called by the context +// at "serve time". A configuration field may be missing when it's not +// safe or its useless to be called from a request handler. type ConfigurationReadOnly interface { // GetVHost returns the non-exported vhost config field. // diff --git a/context/gzip_response_writer.go b/context/gzip_response_writer.go index 2a199480..a1db2d20 100644 --- a/context/gzip_response_writer.go +++ b/context/gzip_response_writer.go @@ -85,6 +85,10 @@ type GzipResponseWriter struct { var _ ResponseWriter = &GzipResponseWriter{} +// BeginGzipResponse accepts a ResponseWriter +// and prepares the new gzip response writer. +// It's being called per-handler, when caller decide +// to change the response writer type. func (w *GzipResponseWriter) BeginGzipResponse(underline ResponseWriter) { w.ResponseWriter = underline w.gzipWriter = acquireGzipWriter(w.ResponseWriter) @@ -92,6 +96,8 @@ func (w *GzipResponseWriter) BeginGzipResponse(underline ResponseWriter) { w.disabled = false } +// EndResponse called right before the contents of this +// response writer are flushed to the client. func (w *GzipResponseWriter) EndResponse() { releaseGzipResponseWriter(w) w.ResponseWriter.EndResponse() @@ -104,6 +110,8 @@ func (w *GzipResponseWriter) Write(contents []byte) (int, error) { return len(w.chunks), nil } +// FlushResponse validates the response headers in order to be compatible with the gzip written data +// and writes the data to the underline ResponseWriter. func (w *GzipResponseWriter) FlushResponse() { if w.disabled { w.ResponseWriter.Write(w.chunks) @@ -128,7 +136,7 @@ func (w *GzipResponseWriter) ResetBody() { w.chunks = w.chunks[0:0] } -// Disable, disables the gzip compression for the next .Write's data, +// Disable turns of the gzip compression for the next .Write's data, // if called then the contents are being written in plain form. func (w *GzipResponseWriter) Disable() { w.disabled = true diff --git a/context/handler.go b/context/handler.go index c8468dd1..8d0bc79a 100644 --- a/context/handler.go +++ b/context/handler.go @@ -4,6 +4,23 @@ package context +// A Handler responds to an HTTP request. +// It writes reply headers and data to the Context.ResponseWriter() and then return. +// Returning signals that the request is finished; +// it is not valid to use the Context after or concurrently with the completion of the Handler call. +// +// Depending on the HTTP client software, HTTP protocol version, +// and any intermediaries between the client and the Iris server, +// it may not be possible to read from the Context.Request().Body after writing to the context.ResponseWriter(). +// Cautious handlers should read the Context.Request().Body first, and then reply. +// +// Except for reading the body, handlers should not modify the provided Context. +// +// If Handler panics, the server (the caller of Handler) assumes that the effect of the panic was isolated to the active request. +// It recovers the panic, logs a stack trace to the server error log, and hangs up the connection. type Handler func(Context) +// Handlers is just a type of slice of []Handler. +// +// See `Handler` for more. type Handlers []Handler diff --git a/core/host/proxy_test.go b/core/host/proxy_test.go index cecb8e54..42d8fbf3 100644 --- a/core/host/proxy_test.go +++ b/core/host/proxy_test.go @@ -18,7 +18,7 @@ func TestProxy(t *testing.T) { unexpectedRoute := "unexpected" // proxySrv := iris.New() - u, err := url.Parse("https://localhost") + u, err := url.Parse("https://localhost:4444") if err != nil { t.Fatalf("%v while parsing url", err) } @@ -31,7 +31,7 @@ func TestProxy(t *testing.T) { // proxySrv.Downgrade(p.ServeHTTP) // go proxySrv.Run(iris.Addr(":80"), iris.WithoutBanner, iris.WithoutInterruptHandler) - go host.NewProxy(":80", u).ListenAndServe() + go host.NewProxy(":1193", u).ListenAndServe() // should be localhost/127.0.0.1:80 but travis throws permission denied. app := iris.New() app.Get("/", func(ctx context.Context) { @@ -46,14 +46,14 @@ func TestProxy(t *testing.T) { ctx.WriteString(unexpectedRoute) }) - l, err := net.Listen("tcp", "localhost:443") + l, err := net.Listen("tcp", "localhost:4444") // should be localhost/127.0.0.1:443 but travis throws permission denied. if err != nil { t.Fatalf("%v while creating tcp4 listener for new tls local test listener", err) } // main server go app.Run(iris.Listener(httptest.NewLocalTLSListener(l)), iris.WithoutBanner) - e := httptest.NewInsecure(t, httptest.URL("http://localhost")) + e := httptest.NewInsecure(t, httptest.URL("http://localhost:1193")) e.GET("/").Expect().Status(iris.StatusOK).Body().Equal(expectedIndex) e.GET("/about").Expect().Status(iris.StatusOK).Body().Equal(expectedAbout) e.GET("/notfound").Expect().Status(iris.StatusNotFound).Body().Equal(unexpectedRoute) diff --git a/core/memstore/memstore_test.go b/core/memstore/memstore_test.go index 68d89719..bec4ec23 100644 --- a/core/memstore/memstore_test.go +++ b/core/memstore/memstore_test.go @@ -24,7 +24,7 @@ func TestMuttable(t *testing.T) { // map - p.Set("map", map[string]myTestObject{"key 1": myTestObject{"value 1"}, "key 2": myTestObject{"value 2"}}) + p.Set("map", map[string]myTestObject{"key 1": {"value 1"}, "key 2": {"value 2"}}) vMap := p.Get("map").(map[string]myTestObject) vMap["key 1"] = myTestObject{"modified"} @@ -60,7 +60,7 @@ func TestImmutable(t *testing.T) { } // map - p.SetImmutable("map", map[string]myTestObject{"key 1": myTestObject{"value 1"}, "key 2": myTestObject{"value 2"}}) + p.SetImmutable("map", map[string]myTestObject{"key 1": {"value 1"}, "key 2": {"value 2"}}) vMap := p.Get("map").(map[string]myTestObject) vMap["key 1"] = myTestObject{"modified"} diff --git a/core/router/api_builder.go b/core/router/api_builder.go index 04d4f60f..c5377e3c 100644 --- a/core/router/api_builder.go +++ b/core/router/api_builder.go @@ -62,6 +62,8 @@ func (r *repository) getAll() []*Route { return r.routes } +// RoutesProvider should be implemented by +// iteral which contains the registered routes. type RoutesProvider interface { // api builder GetRoutes() []*Route GetRoute(routeName string) *Route @@ -177,6 +179,8 @@ func (rb *APIBuilder) Party(relativePath string, handlers ...context.Handler) Pa } } +// Macros returns the macro map which is responsible +// to register custom macro functions for all routes. func (rb *APIBuilder) Macros() *macro.MacroMap { return rb.macros } diff --git a/core/router/handler.go b/core/router/handler.go index 4c907982..a40ca02b 100644 --- a/core/router/handler.go +++ b/core/router/handler.go @@ -70,6 +70,8 @@ func (h *routerHandler) addRoute(method, subdomain, path string, handlers contex return nil } +// NewDefaultHandler returns the handler which is responsible +// to map the request with a route (aka mux implementation). func NewDefaultHandler() RequestHandler { h := &routerHandler{} return h diff --git a/core/router/mime.go b/core/router/mime.go index 386e770e..16403fb7 100644 --- a/core/router/mime.go +++ b/core/router/mime.go @@ -588,7 +588,7 @@ func TypeByExtension(ext string) (typ string) { return typ } -// TypeByFilename, saem as TypeByExtension +// TypeByFilename same as TypeByExtension // but receives a filename path instead. func TypeByFilename(fullFilename string) string { ext := filepath.Ext(fullFilename) diff --git a/core/router/route.go b/core/router/route.go index 5dc026da..5e80acab 100644 --- a/core/router/route.go +++ b/core/router/route.go @@ -12,6 +12,9 @@ import ( "github.com/kataras/iris/core/router/macro" ) +// Route contains the information about a registered Route. +// If any of the following fields are changed then the +// caller should Refresh the router. type Route struct { Name string // "userRoute" Method string // "GET" @@ -24,6 +27,11 @@ type Route struct { FormattedPath string } +// NewRoute returns a new route based on its method, +// subdomain, the path (unparsed or original), +// handlers and the macro container which all routes should share. +// It parses the path based on the "macros", +// handlers are being changed to validate the macros at serve time, if needed. func NewRoute(method, subdomain, unparsedPath string, handlers context.Handlers, macros *macro.MacroMap) (*Route, error) { diff --git a/core/router/router.go b/core/router/router.go index 94d7fe9f..5c2624fe 100644 --- a/core/router/router.go +++ b/core/router/router.go @@ -12,6 +12,12 @@ import ( "github.com/kataras/iris/core/errors" ) +// Router is the "director". +// Caller should provide a request handler (router implementation or root handler). +// Router is responsible to build the received request handler and run it +// to serve requests, based on the received context.Pool. +// +// User can refresh the router with `RefreshRouter` whenever a route's field is changed by him. type Router struct { mu sync.Mutex // for Downgrade, WrapRouter & BuildRouter, // not indeed but we don't to risk its usage by third-parties.