diff --git a/README.md b/README.md
index 85b98927..60de9f3d 100644
--- a/README.md
+++ b/README.md
@@ -211,128 +211,15 @@ id: 1234; page: 1; name: manu; message: this_is_great
 
 ### Upload files
 
-#### Single file
-
-Detail [example code](_examples/http_request/upload-file/main.go).
+- [single file upload](_examples/http_request/upload-file/main.go)
+- [multi file upload](_examples/http_request/upload-files)
 
 ```go
 const maxSize = 5 << 20 // 5MB
 
-func main() {
-    app.Post("/upload", func(ctx iris.Context) {
-        // Get the file from the request.
-        file, info, err := ctx.FormFile("file")
-        if err != nil {
-            ctx.StatusCode(iris.StatusInternalServerError)
-            ctx.HTML("Error while uploading: <b>" + err.Error() + "</b>")
-            return
-        }
-
-        defer file.Close()
-        fname := info.Filename
-
-        // Create a file with the same name
-        // assuming that you have a folder named 'uploads'
-        out, err := os.OpenFile("./uploads/"+fname,
-            os.O_WRONLY|os.O_CREATE, 0666)
-
-        if err != nil {
-            ctx.StatusCode(iris.StatusInternalServerError)
-            ctx.HTML("Error while uploading: <b>" + err.Error() + "</b>")
-            return
-        }
-        defer out.Close()
-
-        io.Copy(out, file)
-    })
-
-    // start the server at http://localhost:8080 with post limit at 5 MB
-    // (defaults to 32MB, read below).
-    app.Run(iris.Addr(":8080"), iris.WithPostMaxMemory(maxSize))
-}
-```
-
-```bash
-curl -X POST http://localhost:8080/upload \
-  -F "file=@./myfile.zip" \
-  -H "Content-Type: multipart/form-data"
-```
-
-* The default post max size is 32MB,
-you can extend it to read more data using the `iris.WithPostMaxMemory(maxSize)` configurator at `app.Run`,
-note that this will not be enough for your needs, read below.
-
-* The faster way to check the size is using the `ctx.GetContentLength()` which returns the whole request's size
-(plus a logical number like 2MB or even 10MB for the rest of the size like headers). You can create a
-middleware to adapt this to any necessary handler.
-
-```go
-myLimiter := func(ctx iris.Context) {
-    if ctx.GetContentLength() > maxSize { // + 2 << 20 {
-        ctx.StatusCode(iris.StatusRequestEntityTooLarge)
-        return
-    }
-    ctx.Next()
-}
-
-app.Post("/upload", myLimiter, myUploadHandler)
-```
-
-* Most clients will set the "Content-Length" header (like browsers) but it's always better to make sure that any client
-can't send data that your server can't or doesn't want to handle. This can be happen using
-the `app.Use(LimitRequestBodySize(maxSize))` (as app or route middleware)
-or the `ctx.SetMaxRequestBodySize(maxSize)` to limit the request based on a customized logic inside a particular handler, they're the same,
-read below.
-
-* You can force-limit the request body size inside a handler using the `ctx.SetMaxRequestBodySize(maxSize)`,
-this will force the connection to close if the incoming data are larger (most clients will receive it as "connection reset"),
-use that to make sure that the client will not send data that your server can't or doesn't want to accept, as a fallback.
-
-```go
-app.Post("/upload", iris.LimitRequestBodySize(maxSize), myUploadHandler)
-```
-
-OR
-
-```go
-app.Post("/upload", func(ctx iris.Context){
-    ctx.SetMaxRequestBodySize(maxSize)
-
-    // [...]
-})
-```
-
-* Another way is to receive the data and check the second return value's `Size` value of the `ctx.FormFile`, i.e `info.Size`, this will give you
-the exact file size, not the whole incoming request data length.
-
-```go
-app.Post("/upload", func(ctx iris.Context){
-    file, info, err := ctx.FormFile("file")
-    if err != nil {
-        ctx.StatusCode(iris.StatusInternalServerError)
-        ctx.HTML("Error while uploading: <b>" + err.Error() + "</b>")
-        return
-    }
-
-    defer file.Close()
-
-    if info.Size > maxSize {
-        ctx.StatusCode(iris.StatusRequestEntityTooLarge)
-        return
-    }
-
-    // [...]
-})
-```
-
-#### Multiple files (easy way)
-
-See the detail [example code](_examples/http_request/upload-files).
-
-```go
 func main() {
     app := iris.Default()
-    app.Post("/upload", func(ctx iris.Context) {
+    app.Post("/upload", iris.LimitRequestBodySize(maxSize), func(ctx iris.Context) {
         //
         // UploadFormFiles
         // uploads any number of incoming files ("multiple" property on the form input).
@@ -365,56 +252,6 @@ func beforeSave(ctx iris.Context, file *multipart.FileHeader) {
 }
 ```
 
-#### Multiple files (manual way)
-
-```go
-app.Post("/upload_manual", func(ctx iris.Context) {
-    r := ctx.Request()
-    // Get the max post value size passed via iris.WithPostMaxMemory.
-    maxSize := ctx.Application().ConfigurationReadOnly().GetPostMaxMemory()
-
-    err := r.ParseMultipartForm(maxSize)
-    if err != nil {
-        ctx.StatusCode(iris.StatusInternalServerError)
-        ctx.WriteString(err.Error())
-        return
-    }
-
-    form := r.MultipartForm
-
-    files := form.File["files[]"]
-    failures := 0
-    for _, file := range files {
-        _, err = saveUploadedFile(file, "./uploads")
-        if err != nil {
-            failures++
-            ctx.Writef("failed to upload: %s\n", file.Filename)
-        }
-    }
-    ctx.Writef("%d files uploaded", len(files)-failures)
-})
-```
-
-```go
-func saveUploadedFile(fh *multipart.FileHeader, destDirectory string) (int64, error) {
-    src, err := fh.Open()
-    if err != nil {
-        return 0, err
-    }
-    defer src.Close()
-
-    out, err := os.OpenFile(filepath.Join(destDirectory, fh.Filename),
-        os.O_WRONLY|os.O_CREATE, os.FileMode(0666))
-
-    if err != nil {
-        return 0, err
-    }
-    defer out.Close()
-
-    return io.Copy(out, src)
-}
-```
-
 How to `curl`:
 
 ```bash
@@ -585,6 +422,8 @@ func main() {
 
 Iris uses [**go-playground/validator.v9**](https://github.com/go-playground/validator) for validation. Check the full docs on tags usage [here](http://godoc.org/gopkg.in/go-playground/validator.v9#hdr-Baked_In_Validators_and_Tags).
 
+Example [detail code](_examples/http_request/read-json-struct-validation/main.go).
+
 Note that you need to set the corresponding binding tag on all fields you want to bind. For example, when binding from JSON, set `json:"fieldname"`.
 
 ```go
@@ -660,79 +499,48 @@ func main() {
                 fmt.Println(err.Value())
                 fmt.Println(err.Param())
                 fmt.Println()
-
-                // Or collect these as json objects
-                // and send back to the client the collected errors via ctx.JSON
-                // {
-                // 	"namespace":        err.Namespace(),
-                // 	"field":            err.Field(),
-                // 	"struct_namespace": err.StructNamespace(),
-                // 	"struct_field":     err.StructField(),
-                // 	"tag":              err.Tag(),
-                // 	"actual_tag":       err.ActualTag(),
-                // 	"kind":             err.Kind().String(),
-                // 	"type":             err.Type().String(),
-                // 	"value":            fmt.Sprintf("%v", err.Value()),
-                // 	"param":            err.Param(),
-                // }
             }
 
-            // from here you can create your own error messages in whatever language you wish.
             return
         }
 
         // save user to database.
     })
 
-    // use Postman or whatever to do a POST request
-    // to the http://localhost:8080/user with RAW BODY:
-    /*
-        {
-            "fname": "",
-            "lname": "",
-            "age": 45,
-            "email": "mail@example.com",
-            "favColor": "#000",
-            "addresses": [{
-                "street": "Eavesdown Docks",
-                "planet": "Persphone",
-                "phone": "none",
-                "city": "Unknown"
-            }]
-        }
-    */
-    // Content-Type to application/json (optionally but good practise).
-    // This request will fail due to the empty `User.FirstName` (fname in json)
-    // and `User.LastName` (lname in json).
-    // Check your iris' application terminal output.
-    app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
+    app.Run(iris.Addr(":8080"))
 }
 
-// UserStructLevelValidation contains custom struct level validations that don't always
-// make sense at the field validation level. For Example this function validates that either
-// FirstName or LastName exist; could have done that with a custom field validation but then
-// would have had to add it to both fields duplicating the logic + overhead, this way it's
-// only validated once.
-//
-// NOTE: you may ask why wouldn't I just do this outside of validator, because doing this way
-// hooks right into validator and you can combine with validation tags and still have a
-// common error output format.
 func UserStructLevelValidation(sl validator.StructLevel) {
-
     user := sl.Current().Interface().(User)
 
     if len(user.FirstName) == 0 && len(user.LastName) == 0 {
         sl.ReportError(user.FirstName, "FirstName", "fname", "fnameorlname", "")
         sl.ReportError(user.LastName, "LastName", "lname", "fnameorlname", "")
     }
-
-    // plus can to more, even with different tag than "fnameorlname".
 }
 ```
 
-## Testing
+```json
+{
+    "fname": "",
+    "lname": "",
+    "age": 45,
+    "email": "mail@example.com",
+    "favColor": "#000",
+    "addresses": [{
+        "street": "Eavesdown Docks",
+        "planet": "Persphone",
+        "phone": "none",
+        "city": "Unknown"
+    }]
+}
+```
 
-First, let's write a simple application which will make use of the HTTP Cookies.
+### Cookies
+
+> Are you looking about [http sessions instead?](_examples/sessions)
+
+Let's write a simple application which will make use of the HTTP Cookies.
 
 ```sh
 $ cat _examples/cookies/basic/main.go
@@ -795,9 +603,7 @@ func main() {
 * `ctx.Request().Cookie(name)` is also available, it's the `net/http` approach
 * Learn more about path parameter's types by clicking [here](_examples/routing/dynamic-path/main.go#L31).
 
-### httptest
-
-Next, is the critical part of this section, the **HTTP Testing**.
+### Testing
 
 Iris offers an incredible support for the [httpexpect](github.com/iris-contrib/httpexpect), a Testing Framework for web applications. However, you are able to use the standard Go's `net/http/httptest` package as well but in this example we will use the `kataras/iris/httptest`.