From bca2b1493873bcaa7964b55dc9a31a8680aacf84 Mon Sep 17 00:00:00 2001
From: Jeevanandam M
Date: Sun, 22 Jul 2018 00:50:16 -0700
Subject: [PATCH 1/2] code optimize and cleanup
---
aah.go | 15 ++++----
access_log.go | 2 +-
bind.go | 2 +-
dump.go | 2 +-
error.go | 3 +-
event.go | 2 +-
http_engine.go | 19 +++-------
http_engine_test.go | 87 ++++++++++++++++++++-------------------------
render.go | 36 +++++--------------
render_test.go | 2 +-
reply.go | 7 ++--
router.go | 19 +++++-----
security.go | 4 +--
util.go | 2 +-
view.go | 5 ++-
15 files changed, 81 insertions(+), 126 deletions(-)
diff --git a/aah.go b/aah.go
index 92d65f71..ce052ee6 100644
--- a/aah.go
+++ b/aah.go
@@ -54,7 +54,6 @@ type BuildInfo struct {
func newApp() *app {
aahApp := &app{
vfs: new(vfs.VFS),
- mu: new(sync.Mutex),
}
aahApp.he = &HTTPEngine{
@@ -70,7 +69,7 @@ func newApp() *app {
aahApp.eventStore = &EventStore{
a: aahApp,
subscribers: make(map[string]EventCallbacks),
- mu: new(sync.Mutex),
+ mu: sync.RWMutex{},
}
return aahApp
@@ -90,6 +89,7 @@ type app struct {
initialized bool
hotReload bool
authSchemeExists bool
+ redirect bool
pid int
httpMaxHdrBytes int
importPath string
@@ -128,8 +128,6 @@ type app struct {
logger log.Loggerer
accessLog *accessLogger
dumpLog *dumpLogger
-
- mu *sync.Mutex
}
func (a *app) Init(importPath string) error {
@@ -283,8 +281,6 @@ func (a *app) Profile() string {
}
func (a *app) SetProfile(profile string) error {
- a.mu.Lock()
- defer a.mu.Unlock()
if err := a.Config().SetProfile(profilePrefix + profile); err != nil {
return err
}
@@ -335,8 +331,6 @@ func (a *app) NewChildLogger(fields log.Fields) log.Loggerer {
}
func (a *app) SetTLSConfig(tlsCfg *tls.Config) {
- a.mu.Lock()
- defer a.mu.Unlock()
a.tlsCfg = tlsCfg
}
@@ -434,6 +428,8 @@ func (a *app) initConfigValues() (err error) {
return err
}
+ a.redirect = cfg.BoolDefault("server.redirect.enable", false)
+
readTimeout := cfg.StringDefault("server.timeout.read", "90s")
writeTimeout := cfg.StringDefault("server.timeout.write", "90s")
if !isValidTimeUnit(readTimeout, "s", "m") || !isValidTimeUnit(writeTimeout, "s", "m") {
@@ -589,7 +585,8 @@ func (a *app) aahRecover() {
// ServeHTTP method implementation of http.Handler interface.
func (a *app) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer a.aahRecover()
- if a.he.doRedirect(w, r) {
+ if a.redirect {
+ a.he.doRedirect(w, r)
return
}
diff --git a/access_log.go b/access_log.go
index b9b453b4..cd50a7ec 100644
--- a/access_log.go
+++ b/access_log.go
@@ -228,7 +228,7 @@ func (al *accessLog) GetResponseHdr(hdrKey string) string {
func (al *accessLog) GetQueryString() string {
queryStr := al.Request.URL().Query().Encode()
- if ess.IsStrEmpty(queryStr) {
+ if len(queryStr) == 0 {
return "-"
}
return `"` + queryStr + `"`
diff --git a/bind.go b/bind.go
index 150ed973..8c883cf1 100644
--- a/bind.go
+++ b/bind.go
@@ -100,7 +100,7 @@ func BindMiddleware(ctx *Context, m *Middleware) {
// Note: Query parameter takes precedence of all.
if locale := firstNonZeroString(
ctx.Req.QueryValue(ctx.a.bindMgr.keyQueryParamName),
- ctx.Req.PathValue(ctx.a.bindMgr.keyPathParamName)); !ess.IsStrEmpty(locale) {
+ ctx.Req.PathValue(ctx.a.bindMgr.keyPathParamName)); len(locale) > 0 {
ctx.Req.SetLocale(ahttp.NewLocale(locale))
}
}
diff --git a/dump.go b/dump.go
index 949efc01..a25e288a 100644
--- a/dump.go
+++ b/dump.go
@@ -77,7 +77,7 @@ func (d *dumpLogger) Dump(ctx *Context) {
// Request
uri := fmt.Sprintf("%s://%s%s", ctx.Req.Scheme, ctx.Req.Host, ctx.Req.Path)
- if qs := ctx.Req.URL().RawQuery; !ess.IsStrEmpty(qs) {
+ if qs := ctx.Req.URL().RawQuery; len(qs) > 0 {
uri += "?" + qs
}
diff --git a/error.go b/error.go
index 19b40892..b2dd9f01 100644
--- a/error.go
+++ b/error.go
@@ -11,7 +11,6 @@ import (
"net/http"
"aahframework.org/ahttp.v0"
- "aahframework.org/essentials.v0"
)
// aah errors
@@ -161,7 +160,7 @@ func (er *errorManager) Handle(ctx *Context) {
// in the aah. It writes the response based on HTTP Content-Type.
func (er *errorManager) DefaultHandler(ctx *Context, err *Error) bool {
ct := ctx.Reply().ContType
- if ess.IsStrEmpty(ct) {
+ if len(ct) == 0 {
ct = ctx.detectContentType().Mime
if ctx.a.viewMgr == nil && ct == ahttp.ContentTypeHTML.Mime {
ct = ahttp.ContentTypePlainText.Mime
diff --git a/event.go b/event.go
index 5f5ce124..7a496668 100644
--- a/event.go
+++ b/event.go
@@ -177,7 +177,7 @@ func (a *app) EventStore() *EventStore {
// EventStore type holds all the events belongs to aah application.
type EventStore struct {
a *app
- mu *sync.Mutex
+ mu sync.RWMutex
subscribers map[string]EventCallbacks
}
diff --git a/http_engine.go b/http_engine.go
index c267bb85..11070a9a 100644
--- a/http_engine.go
+++ b/http_engine.go
@@ -14,7 +14,6 @@ import (
"aahframework.org/ahttp.v0"
"aahframework.org/ainsp.v0"
"aahframework.org/aruntime.v0"
- "aahframework.org/essentials.v0"
"aahframework.org/log.v0"
"aahframework.org/security.v0"
"aahframework.org/security.v0/authc"
@@ -73,14 +72,14 @@ func (e *HTTPEngine) Handle(w http.ResponseWriter, r *http.Request) {
ctx := e.ctxPool.Get().(*Context)
defer e.releaseContext(ctx)
- ctx.Req, ctx.Res = ahttp.AcquireRequest(r), ahttp.AcquireResponseWriter(w)
- ctx.Set(reqStartTimeKey, time.Now())
-
// Record access log
if e.a.accessLogEnabled {
+ ctx.Set(reqStartTimeKey, time.Now())
defer e.a.accessLog.Log(ctx)
}
+ ctx.Req, ctx.Res = ahttp.AcquireRequest(r), ahttp.AcquireResponseWriter(w)
+
// Recovery handling
defer e.handleRecovery(ctx)
@@ -319,7 +318,7 @@ func (e *HTTPEngine) writeReply(ctx *Context) {
}
// Check ContentType and detect it if need be
- if ess.IsStrEmpty(re.ContType) {
+ if len(re.ContType) == 0 {
re.ContentType(ctx.detectContentType().String())
}
ctx.Res.Header().Set(ahttp.HeaderContentType, re.ContType)
@@ -433,12 +432,8 @@ const (
nonwww = "non-www"
)
-func (e *HTTPEngine) doRedirect(w http.ResponseWriter, r *http.Request) bool {
+func (e *HTTPEngine) doRedirect(w http.ResponseWriter, r *http.Request) {
cfg := e.a.Config()
- if !cfg.BoolDefault("server.redirect.enable", false) {
- return false
- }
-
redirectTo := cfg.StringDefault("server.redirect.to", nonwww)
redirectCode := cfg.IntDefault("server.redirect.code", http.StatusMovedPermanently)
host := ahttp.Host(r)
@@ -447,14 +442,10 @@ func (e *HTTPEngine) doRedirect(w http.ResponseWriter, r *http.Request) bool {
case www:
if host[:3] != www {
http.Redirect(w, r, ahttp.Scheme(r)+"://www."+host+r.URL.RequestURI(), redirectCode)
- return true
}
case nonwww:
if host[:3] == www {
http.Redirect(w, r, ahttp.Scheme(r)+"://"+host[4:]+r.URL.RequestURI(), redirectCode)
- return true
}
}
-
- return false
}
diff --git a/http_engine_test.go b/http_engine_test.go
index 3fe18452..7d4842e6 100644
--- a/http_engine_test.go
+++ b/http_engine_test.go
@@ -164,7 +164,7 @@ func TestHTTPEngineTestRequests(t *testing.T) {
assert.Nil(t, err)
assert.Equal(t, 200, resp.StatusCode)
assert.Equal(t, "application/json; charset=utf-8", resp.Header.Get(ahttp.HeaderContentType))
- assert.Equal(t, "134", resp.Header.Get(ahttp.HeaderContentLength))
+ assert.Equal(t, "135", resp.Header.Get(ahttp.HeaderContentLength))
assert.True(t, strings.HasPrefix(responseBody(resp), `)]}',`))
// GET Binary bytes - /binary-bytes
@@ -221,7 +221,6 @@ func TestHTTPEngineTestRequests(t *testing.T) {
func TestServerRedirect(t *testing.T) {
a := newApp()
a.cfg = config.NewEmpty()
- a.he.doRedirect(nil, nil)
// www redirect
t.Log("www redirect")
@@ -236,11 +235,10 @@ func TestServerRedirect(t *testing.T) {
`)
type redirectTestCase struct {
- label string
- fromURL string
- didItHappen bool
- status int
- location string
+ label string
+ fromURL string
+ status int
+ location string
}
runtestcase := func(testcases []redirectTestCase) {
@@ -248,8 +246,7 @@ func TestServerRedirect(t *testing.T) {
t.Run(tc.label, func(t *testing.T) {
w := httptest.NewRecorder()
r := httptest.NewRequest(ahttp.MethodGet, tc.fromURL, nil)
- didItHappen := a.he.doRedirect(w, r)
- assert.Equal(t, tc.didItHappen, didItHappen)
+ a.he.doRedirect(w, r)
assert.Equal(t, tc.status, w.Code)
assert.Equal(t, tc.location, w.Header().Get(ahttp.HeaderLocation))
})
@@ -258,32 +255,28 @@ func TestServerRedirect(t *testing.T) {
testcases := []redirectTestCase{
{
- label: "www domain",
- fromURL: "http://aahframework.org/home.html?rt=login",
- didItHappen: true,
- status: http.StatusTemporaryRedirect,
- location: "http://www.aahframework.org/home.html?rt=login",
+ label: "www domain",
+ fromURL: "http://aahframework.org/home.html?rt=login",
+ status: http.StatusTemporaryRedirect,
+ location: "http://www.aahframework.org/home.html?rt=login",
},
{
- label: "www subdomain",
- fromURL: "http://docs.aahframework.org",
- didItHappen: true,
- status: http.StatusTemporaryRedirect,
- location: "http://www.docs.aahframework.org/",
+ label: "www subdomain",
+ fromURL: "http://docs.aahframework.org",
+ status: http.StatusTemporaryRedirect,
+ location: "http://www.docs.aahframework.org/",
},
{
- label: "www domain already correct",
- fromURL: "http://www.aahframework.org",
- didItHappen: false,
- status: http.StatusOK,
- location: "",
+ label: "www domain already correct",
+ fromURL: "http://www.aahframework.org",
+ status: http.StatusOK,
+ location: "",
},
{
- label: "www subdomain already correct",
- fromURL: "http://www.docs.aahframework.org",
- didItHappen: false,
- status: http.StatusOK,
- location: "",
+ label: "www subdomain already correct",
+ fromURL: "http://www.docs.aahframework.org",
+ status: http.StatusOK,
+ location: "",
},
}
@@ -301,32 +294,28 @@ func TestServerRedirect(t *testing.T) {
testcases = []redirectTestCase{
{
- label: "non-www domain",
- fromURL: "http://www.aahframework.org/home.html?rt=login",
- didItHappen: true,
- status: http.StatusMovedPermanently,
- location: "http://aahframework.org/home.html?rt=login",
+ label: "non-www domain",
+ fromURL: "http://www.aahframework.org/home.html?rt=login",
+ status: http.StatusMovedPermanently,
+ location: "http://aahframework.org/home.html?rt=login",
},
{
- label: "non-www subdomain",
- fromURL: "http://www.docs.aahframework.org",
- didItHappen: true,
- status: http.StatusMovedPermanently,
- location: "http://docs.aahframework.org/",
+ label: "non-www subdomain",
+ fromURL: "http://www.docs.aahframework.org",
+ status: http.StatusMovedPermanently,
+ location: "http://docs.aahframework.org/",
},
{
- label: "non-www domain already correct",
- fromURL: "http://aahframework.org",
- didItHappen: false,
- status: http.StatusOK,
- location: "",
+ label: "non-www domain already correct",
+ fromURL: "http://aahframework.org",
+ status: http.StatusOK,
+ location: "",
},
{
- label: "non-www subdomain already correct",
- fromURL: "http://docs.aahframework.org",
- didItHappen: false,
- status: http.StatusOK,
- location: "",
+ label: "non-www subdomain already correct",
+ fromURL: "http://docs.aahframework.org",
+ status: http.StatusOK,
+ location: "",
},
}
diff --git a/render.go b/render.go
index 57ff3db4..4804a5f3 100644
--- a/render.go
+++ b/render.go
@@ -1,5 +1,5 @@
// Copyright (c) Jeevanandam M. (https://github.com/jeevatkm)
-// go-aah/aah source code and usage is governed by a MIT style
+// aahframework.org/aah source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.
package aah
@@ -83,13 +83,7 @@ type jsonRender struct {
// Render method writes JSON into HTTP response.
func (j jsonRender) Render(w io.Writer) error {
- jsonBytes, err := JSONMarshal(j.Data)
- if err != nil {
- return err
- }
-
- _, err = w.Write(jsonBytes)
- return err
+ return json.NewEncoder(w).Encode(j.Data)
}
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
@@ -104,12 +98,12 @@ type jsonpRender struct {
// Render method writes JSONP into HTTP response.
func (j jsonpRender) Render(w io.Writer) error {
- jsonBytes, err := JSONMarshal(j.Data)
+ jsonBytes, err := json.Marshal(j.Data)
if err != nil {
return err
}
- if ess.IsStrEmpty(j.Callback) {
+ if len(j.Callback) == 0 {
_, err = w.Write(jsonBytes)
} else {
_, err = fmt.Fprintf(w, "%s(%s);", j.Callback, jsonBytes)
@@ -128,17 +122,10 @@ type secureJSONRender struct {
}
func (s secureJSONRender) Render(w io.Writer) error {
- jsonBytes, err := JSONMarshal(s.Data)
- if err != nil {
- return err
- }
-
- if _, err = w.Write([]byte(s.Prefix)); err != nil {
+ if _, err := w.Write([]byte(s.Prefix)); err != nil {
return err
}
-
- _, err = w.Write(jsonBytes)
- return err
+ return json.NewEncoder(w).Encode(s.Data)
}
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
@@ -152,17 +139,10 @@ type xmlRender struct {
// Render method writes XML into HTTP response.
func (x xmlRender) Render(w io.Writer) error {
- xmlBytes, err := xml.Marshal(x.Data)
- if err != nil {
- return err
- }
-
- if _, err = w.Write(xmlHeaderBytes); err != nil {
+ if _, err := w.Write(xmlHeaderBytes); err != nil {
return err
}
-
- _, err = w.Write(xmlBytes)
- return err
+ return xml.NewEncoder(w).Encode(x.Data)
}
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
diff --git a/render_test.go b/render_test.go
index 889c2342..00ee8693 100644
--- a/render_test.go
+++ b/render_test.go
@@ -50,7 +50,7 @@ func TestRenderJSON(t *testing.T) {
err := json1.Render(buf)
assert.FailOnError(t, err, "")
assert.Equal(t, `{"Name":"John","Age":28,"Address":"this is my street"}`,
- buf.String())
+ strings.TrimSpace(buf.String()))
}
func TestRenderFailureXML(t *testing.T) {
diff --git a/reply.go b/reply.go
index 9efb1214..3813e222 100644
--- a/reply.go
+++ b/reply.go
@@ -13,7 +13,6 @@ import (
"sync"
"aahframework.org/ahttp.v0"
- "aahframework.org/essentials.v0"
)
var (
@@ -144,7 +143,7 @@ func (r *Reply) ServiceUnavailable() *Reply {
// By default aah framework try to determine response 'Content-Type' from
// 'ahttp.Request.AcceptContentType()'.
func (r *Reply) ContentType(contentType string) *Reply {
- if ess.IsStrEmpty(r.ContType) {
+ if len(r.ContType) == 0 {
r.ContType = strings.ToLower(contentType)
}
return r
@@ -320,7 +319,7 @@ func (r *Reply) Render(rdr Render) *Reply {
//
// Note: It overwrites existing header value if it's present.
func (r *Reply) Header(key, value string) *Reply {
- if ess.IsStrEmpty(value) {
+ if len(value) == 0 {
if key == ahttp.HeaderContentType {
return r.ContentType("")
}
@@ -380,7 +379,7 @@ func (r *Reply) DisableGzip() *Reply {
// IsContentTypeSet method returns true if Content-Type is set otherwise
// false.
func (r *Reply) IsContentTypeSet() bool {
- return !ess.IsStrEmpty(r.ContType)
+ return len(r.ContType) > 0
}
// Body method returns the response body buffer.
diff --git a/router.go b/router.go
index 3cc46966..a2256f23 100644
--- a/router.go
+++ b/router.go
@@ -13,7 +13,6 @@ import (
"strings"
"aahframework.org/ahttp.v0"
- "aahframework.org/essentials.v0"
"aahframework.org/log.v0"
"aahframework.org/router.v0"
"aahframework.org/valpar.v0"
@@ -118,7 +117,7 @@ func handleCORSPreflight(ctx *Context) {
ctx.Reply().Header(ahttp.HeaderAccessControlAllowCredentials, "true")
}
- if !ess.IsStrEmpty(cors.MaxAge) {
+ if len(cors.MaxAge) > 0 {
ctx.Reply().Header(ahttp.HeaderAccessControlMaxAge, cors.MaxAge)
}
@@ -198,17 +197,19 @@ func handleRoute(ctx *Context) flowResult {
}
// Apply route constraints
- if errs := valpar.ValidateValues(ctx.Req.PathParams, ctx.route.Constraints); len(errs) > 0 {
- ctx.Log().Errorf("Route constraints failed: %s", errs)
- ctx.Reply().BadRequest().Error(newErrorWithData(router.ErrRouteConstraintFailed, http.StatusBadRequest, errs))
- return flowAbort
+ if len(ctx.route.Constraints) > 0 {
+ if errs := valpar.ValidateValues(ctx.Req.PathParams, ctx.route.Constraints); len(errs) > 0 {
+ ctx.Log().Errorf("Route constraints failed: %s", errs)
+ ctx.Reply().BadRequest().Error(newErrorWithData(router.ErrRouteConstraintFailed, http.StatusBadRequest, errs))
+ return flowAbort
+ }
}
return flowCont
}
func appendAnchorLink(routePath, anchorLink string) string {
- if ess.IsStrEmpty(anchorLink) {
+ if len(anchorLink) == 0 {
return routePath
}
return routePath + "#" + anchorLink
@@ -225,7 +226,7 @@ func getRouteNameAndAnchorLink(routeName string) (string, string) {
}
func composeRouteURL(domain *router.Domain, routePath, anchorLink string) string {
- if ess.IsStrEmpty(domain.Port) {
+ if len(domain.Port) == 0 {
routePath = fmt.Sprintf("//%s%s", domain.Host, routePath)
} else {
routePath = fmt.Sprintf("//%s:%s%s", domain.Host, domain.Port, routePath)
@@ -327,7 +328,7 @@ func handleRtsOptionsMna(ctx *Context, domain *router.Domain, rts bool) error {
}
func processAllowedMethods(reply *Reply, allowed, prefix string) bool {
- if !ess.IsStrEmpty(allowed) {
+ if len(allowed) > 0 {
allowed += ", " + ahttp.MethodOptions
reply.Header(ahttp.HeaderAllow, allowed)
reply.ctx.Log().Debugf("%sAllowed HTTP Methods: %s", prefix, allowed)
diff --git a/security.go b/security.go
index ccb68ec5..f69219e0 100644
--- a/security.go
+++ b/security.go
@@ -161,7 +161,7 @@ func doFormAuth(authScheme scheme.Schemer, ctx *Context) flowResult {
ctx.e.publishOnPostAuthEvent(ctx)
rt := ctx.Req.FormValue("_rt") // redirect to requested URL
- if formAuth.IsAlwaysToDefaultTarget || ess.IsStrEmpty(rt) {
+ if formAuth.IsAlwaysToDefaultTarget || len(rt) == 0 {
ctx.Reply().Redirect(formAuth.DefaultTargetURL)
} else {
ctx.Log().Debugf("Redirecting to URL found in param '_rt': %s", rt)
@@ -375,7 +375,7 @@ func AntiCSRFMiddleware(ctx *Context, m *Middleware) {
return
}
- if ess.IsStrEmpty(referer.String()) {
+ if len(referer.String()) == 0 {
ctx.Log().Warnf("anticsrf: No referer %s", ctx.Req.Referer)
ctx.Reply().Forbidden().Error(newError(anticsrf.ErrNoReferer, http.StatusForbidden))
return
diff --git a/util.go b/util.go
index d93c2359..fa90b11c 100644
--- a/util.go
+++ b/util.go
@@ -229,7 +229,7 @@ func reason2String(reasons []*authz.Reason) string {
// addQueryString method adds the given query string key value pair appropriately
func addQueryString(u, k, v string) string {
- if ess.IsStrEmpty(u) {
+ if len(u) == 0 {
return "?" + k + "=" + v
}
if idx := strings.IndexByte(u, '?'); idx == -1 {
diff --git a/view.go b/view.go
index d3fe6806..e47a5fc6 100644
--- a/view.go
+++ b/view.go
@@ -12,7 +12,6 @@ import (
"strings"
"aahframework.org/ahttp.v0"
- "aahframework.org/essentials.v0"
"aahframework.org/security.v0"
"aahframework.org/view.v0"
)
@@ -151,7 +150,7 @@ func (vm *viewManager) resolve(ctx *Context) {
return
}
- if ess.IsStrEmpty(htmlRdr.Layout) && vm.defaultLayoutEnabled {
+ if len(htmlRdr.Layout) == 0 && vm.defaultLayoutEnabled {
htmlRdr.Layout = vm.defaultTmplLayout
}
@@ -172,7 +171,7 @@ func (vm *viewManager) resolve(ctx *Context) {
var tmplPath, tmplName string
// If user not provided the template info, auto resolve by convention
- if ess.IsStrEmpty(htmlRdr.Filename) {
+ if len(htmlRdr.Filename) == 0 {
tmplName = ctx.action.Name + vm.fileExt
tmplPath = filepath.Join(ctx.controller.Namespace, ctx.controller.NoSuffixName)
} else {
From c8d9a4f71bbe865d197e0baf25357d9dc1e6b386 Mon Sep 17 00:00:00 2001
From: Jeevanandam M
Date: Sun, 22 Jul 2018 01:38:40 -0700
Subject: [PATCH 2/2] version bump and readme update for v0.11.1
---
README.md | 4 ++--
version.go | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 04811672..b83f450a 100644
--- a/README.md
+++ b/README.md
@@ -4,12 +4,12 @@
Visit aah's official website https://aahframework.org to learn more
-
+
### News
- * `v0.11.0` [released](https://docs.aahframework.org/release-notes.html) and tagged on Jul 06, 2018.
+ * `v0.11.1` [released](https://docs.aahframework.org/release-notes.html) and tagged on Jul 22, 2018.
### Stargazers over time
diff --git a/version.go b/version.go
index b6034610..471e9ced 100644
--- a/version.go
+++ b/version.go
@@ -5,4 +5,4 @@
package aah
// Version no. of aah framework
-const Version = "0.11.0"
+const Version = "0.11.1"