diff --git a/content/ru/_index.html b/content/ru/_index.html
new file mode 100644
index 000000000..85c54d4f2
--- /dev/null
+++ b/content/ru/_index.html
@@ -0,0 +1,77 @@
++++
+title = "Gin Web Framework"
+linkTitle = "Gin Web Framework"
++++
+
+{{< blocks/cover title="Gin Web Framework" image_anchor="top" height="full" color="orange" >}}
+
+
}}">
+ Подробнее
+
+
+ Скачать
+
+
Самый быстрый полнофункциональный веб-фреймворк для Go. Кристально чистый.
+
+ {{< blocks/link-down color="info" >}}
+
+{{< /blocks/cover >}}
+
+
+{{% blocks/lead color="white" %}}
+
+**Что такое Gin?**
+
+Gin - это веб-фреймворк, написанный на языке Golang.
+
+В нем реализован API, похожий на Martini, но производительность в 40 раз выше, чем у Martini.
+
+Если вам нужна производительность и продуктивность, Gin вам понравится.
+
+{{% /blocks/lead %}}
+
+{{< blocks/section color="light" >}}
+
+{{% blocks/feature icon="fa fa-tachometer-alt" title="Fast" %}}
+Маршрутизация на основе радиксного дерева, малый объем памяти. Никаких отражений. Предсказуемая производительность API.
+{{% /blocks/feature %}}
+
+{{% blocks/feature icon="fa fa-bars" title="Middleware support" %}}
+Входящий HTTP-запрос может быть обработан цепочкой промежуточного ПО (Middleware) и конечным действием.
+Например: Логгер, авторизация, GZIP и, наконец, публикация сообщения в БД.
+{{% /blocks/feature %}}
+
+{{% blocks/feature icon="fa fa-life-ring" title="Crash-free" %}}
+Gin может поймать панику, возникшую во время HTTP-запроса, и восстановить ее. Таким образом, ваш сервер будет всегда доступен. Также можно сообщить об этой панике, например, в Sentry!
+{{% /blocks/feature %}}
+
+{{< /blocks/section >}}
+
+{{< blocks/section color="white" >}}
+
+{{% blocks/feature icon="fa fa-check-circle" title="JSON validation" %}}
+Gin может анализировать и проверять JSON-запросы, например, на наличие необходимых значений.
+{{% /blocks/feature %}}
+
+{{% blocks/feature icon="fa fa-users-cog" title="Routes grouping" %}}
+Организуйте свои маршруты лучше. Требуется и не требуется авторизация, разные версии API. Кроме того, группы могут быть вложены бесконечно без снижения производительности.
+{{% /blocks/feature %}}
+
+
+{{% blocks/feature icon="fa fa-briefcase" title="Error management" %}}
+Gin обеспечивает удобный способ сбора всех ошибок, возникших во время HTTP-запроса. В конечном итоге промежуточное ПО (Middleware) может записывать их в файл журнала, в базу данных и отправлять через сеть.
+{{% /blocks/feature %}}
+
+{{< /blocks/section >}}
+
+{{< blocks/section color="info" >}}
+
+{{% blocks/feature icon="fa fa-images" title="Rendering built-in" %}}
+Gin предоставляет простой в использовании API для рендеринга JSON, XML и HTML.
+{{% /blocks/feature %}}
+
+{{% blocks/feature icon="fa fa-code" title="Extendable" %}}
+Создать новое промежуточное программное обеспечение очень просто, просто посмотрите пример кода.
+{{% /blocks/feature %}}
+
+{{< /blocks/section >}}
diff --git a/content/ru/blog/_index.md b/content/ru/blog/_index.md
new file mode 100644
index 000000000..bfe08e93d
--- /dev/null
+++ b/content/ru/blog/_index.md
@@ -0,0 +1,13 @@
+---
+title: "Blog"
+linkTitle: "Blog"
+menu:
+ main:
+ weight: 30
+---
+
+
+This is the **blog** section. It has two categories: News and Releases.
+
+Files in these directories will be listed in reverse chronological order.
+
diff --git a/content/ru/blog/news/_index.md b/content/ru/blog/news/_index.md
new file mode 100644
index 000000000..3263a4f27
--- /dev/null
+++ b/content/ru/blog/news/_index.md
@@ -0,0 +1,8 @@
+
+---
+title: "Новости"
+linkTitle: "News"
+weight: 20
+---
+
+
diff --git a/content/ru/blog/news/how-to-build-one-effective-middleware.md b/content/ru/blog/news/how-to-build-one-effective-middleware.md
new file mode 100644
index 000000000..03b4fb4cc
--- /dev/null
+++ b/content/ru/blog/news/how-to-build-one-effective-middleware.md
@@ -0,0 +1,143 @@
+---
+title: "Как создать эффективное промежуточное программное обеспечение? (Middleware)"
+linkTitle: "How to build one effective middleware?"
+date: 2019-02-26
+---
+
+## Constituent parts
+
+Промежуточное ПО (Middleware) состоит из двух частей:
+
+ - первая часть - это то, что выполняется один раз, когда вы инициализируете промежуточное ПО. В ней вы устанавливаете все глобальные объекты, логики и т. д. Все это происходит один раз за время жизни приложения.
+
+ - Вторая часть - это то, что выполняется при каждом запросе. Например, в промежуточном ПО для работы с базами данных вы просто вводите свой "глобальный" объект базы данных в контекст. Как только он окажется внутри контекста, вы сможете получить его из других промежуточных модулей и из вашей функции-обработчика.
+
+```go
+func funcName(params string) gin.HandlerFunc {
+ // <---
+ // This is part one
+ // --->
+ // The following code is an example
+ if err := check(params); err != nil {
+ panic(err)
+ }
+
+ return func(c *gin.Context) {
+ // <---
+ // This is part two
+ // --->
+ // The following code is an example
+ c.Set("TestVar", params)
+ c.Next()
+ }
+}
+```
+
+## Процесс выполнения
+
+Во-первых, у нас есть следующий пример кода:
+
+```go
+func main() {
+ router := gin.Default()
+
+ router.Use(globalMiddleware())
+
+ router.GET("/rest/n/api/*some", mid1(), mid2(), handler)
+
+ router.Run()
+}
+
+func globalMiddleware() gin.HandlerFunc {
+ fmt.Println("globalMiddleware...1")
+
+ return func(c *gin.Context) {
+ fmt.Println("globalMiddleware...2")
+ c.Next()
+ fmt.Println("globalMiddleware...3")
+ }
+}
+
+func handler(c *gin.Context) {
+ fmt.Println("exec handler.")
+}
+
+func mid1() gin.HandlerFunc {
+ fmt.Println("mid1...1")
+
+ return func(c *gin.Context) {
+
+ fmt.Println("mid1...2")
+ c.Next()
+ fmt.Println("mid1...3")
+ }
+}
+
+func mid2() gin.HandlerFunc {
+ fmt.Println("mid2...1")
+
+ return func(c *gin.Context) {
+ fmt.Println("mid2...2")
+ c.Next()
+ fmt.Println("mid2...3")
+ }
+}
+```
+
+Согласно [Составные части](#Constituent-parts), когда мы запускаем процесс джина, **часть первая** будет выполняться первой и выведет следующую информацию:
+
+```go
+globalMiddleware...1
+mid1...1
+mid2...1
+```
+
+And init order is:
+
+```go
+globalMiddleware...1
+ |
+ v
+mid1...1
+ |
+ v
+mid2...1
+```
+
+Когда мы выполним один запрос `curl -v localhost:8080/rest/n/api/some`, **часть вторая** выполнит свое промежуточное ПО и выведет следующую информацию:
+
+```go
+globalMiddleware...2
+mid1...2
+mid2...2
+exec handler.
+mid2...3
+mid1...3
+globalMiddleware...3
+```
+
+Другими словами, порядок выполнения таков:
+
+```go
+globalMiddleware...2
+ |
+ v
+mid1...2
+ |
+ v
+mid2...2
+ |
+ v
+exec handler.
+ |
+ v
+mid2...3
+ |
+ v
+mid1...3
+ |
+ v
+globalMiddleware...3
+```
+
+
diff --git a/content/ru/blog/releases/_index.md b/content/ru/blog/releases/_index.md
new file mode 100644
index 000000000..c045332fe
--- /dev/null
+++ b/content/ru/blog/releases/_index.md
@@ -0,0 +1,8 @@
+
+---
+title: "Релизы"
+linkTitle: "Releases"
+weight: 20
+---
+
+
diff --git a/content/ru/blog/releases/release13.md b/content/ru/blog/releases/release13.md
new file mode 100644
index 000000000..43f4656f4
--- /dev/null
+++ b/content/ru/blog/releases/release13.md
@@ -0,0 +1,29 @@
+---
+title: "Gin 1.3.0 is released"
+linkTitle: "Gin 1.3.0 is released"
+date: 2018-08-14
+---
+
+### CHANGELOG
+
+- [NEW] Add [`func (*Context) QueryMap`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.QueryMap), [`func (*Context) GetQueryMap`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.GetQueryMap), [`func (*Context) PostFormMap`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.PostFormMap) and [`func (*Context) GetPostFormMap`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.GetPostFormMap) to support `type map[string]string` as query string or form parameters, see [#1383](https://github.com/gin-gonic/gin/pull/1383)
+- [NEW] Add [`func (*Context) AsciiJSON`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.AsciiJSON), see [#1358](https://github.com/gin-gonic/gin/pull/1358)
+- [NEW] Add `Pusher()` in [`type ResponseWriter`](https://pkg.go.dev/github.com/gin-gonic/gin#ResponseWriter) for supporting http2 push, see [#1273](https://github.com/gin-gonic/gin/pull/1273)
+- [NEW] Add [`func (*Context) DataFromReader`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.DataFromReader) for serving dynamic data, see [#1304](https://github.com/gin-gonic/gin/pull/1304)
+- [NEW] Add [`func (*Context) ShouldBindBodyWith`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.ShouldBindBodyWith) allowing to call binding multiple times, see [#1341](https://github.com/gin-gonic/gin/pull/1341)
+- [NEW] Support pointers in form binding, see [#1336](https://github.com/gin-gonic/gin/pull/1336)
+- [NEW] Add [`func (*Context) JSONP`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.JSONP), see [#1333](https://github.com/gin-gonic/gin/pull/1333)
+- [NEW] Support default value in form binding, see [#1138](https://github.com/gin-gonic/gin/pull/1138)
+- [NEW] Expose validator engine in [`type StructValidator`](https://pkg.go.dev/github.com/gin-gonic/gin/binding#StructValidator), see [#1277](https://github.com/gin-gonic/gin/pull/1277)
+- [NEW] Add [`func (*Context) ShouldBind`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.ShouldBind), [`func (*Context) ShouldBindQuery`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.ShouldBindQuery) and [`func (*Context) ShouldBindJSON`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.ShouldBindJSON), see [#1047](https://github.com/gin-gonic/gin/pull/1047)
+- [NEW] Add support for `time.Time` location in form binding, see [#1117](https://github.com/gin-gonic/gin/pull/1117)
+- [NEW] Add [`func (*Context) BindQuery`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.BindQuery), see [#1029](https://github.com/gin-gonic/gin/pull/1029)
+- [NEW] Make [jsonite](https://github.com/json-iterator/go) optional with build tags, see [#1026](https://github.com/gin-gonic/gin/pull/1026)
+- [NEW] Show query string in logger, see [#999](https://github.com/gin-gonic/gin/pull/999)
+- [NEW] Add [`func (*Context) SecureJSON`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.SecureJSON), see [#987](https://github.com/gin-gonic/gin/pull/987) and [#993](https://github.com/gin-gonic/gin/pull/993)
+- [DEPRECATE] `func (*Context) GetCookie` for [`func (*Context) Cookie`](https://pkg.go.dev/github.com/gin-gonic/gin#Context.Cookie)
+- [FIX] Don't display color tags if [`func DisableConsoleColor`](https://pkg.go.dev/github.com/gin-gonic/gin#DisableConsoleColor) called, see [#1072](https://github.com/gin-gonic/gin/pull/1072)
+- [FIX] Gin Mode `""` when calling [`func Mode`](https://pkg.go.dev/github.com/gin-gonic/gin#Mode) now returns `const DebugMode`, see [#1250](https://github.com/gin-gonic/gin/pull/1250)
+- [FIX] `Flush()` now doesn't overwrite `responseWriter` status code, see [#1460](https://github.com/gin-gonic/gin/pull/1460)
+
+
diff --git a/content/ru/blog/releases/release14.md b/content/ru/blog/releases/release14.md
new file mode 100644
index 000000000..23fd64829
--- /dev/null
+++ b/content/ru/blog/releases/release14.md
@@ -0,0 +1,66 @@
+---
+title: "Gin 1.4.0 is released"
+linkTitle: "Gin 1.4.0 is released"
+date: 2019-05-08
+---
+
+### CHANGELOG
+
+#### Feature
+
+- [NEW] Support for [Go Modules](https://github.com/golang/go/wiki/Modules) [#1569](https://github.com/gin-gonic/gin/pull/1569)
+- [NEW] Refactor of form mapping multipart request [#1829](https://github.com/gin-gonic/gin/pull/1829)
+- [NEW] Supporting file binding [#1264](https://github.com/gin-gonic/gin/pull/1264)
+- [NEW] Add support for mapping arrays [#1797](https://github.com/gin-gonic/gin/pull/1797)
+- [NEW] Make context.Keys available as LogFormatterParams [#1779](https://github.com/gin-gonic/gin/pull/1779)
+- [NEW] Use internal/json for Marshal/Unmarshal [#1791](https://github.com/gin-gonic/gin/pull/1791)
+- [NEW] Support mapping time.Duration [#1794](https://github.com/gin-gonic/gin/pull/1794)
+- [NEW] Refactor form mappings [#1749](https://github.com/gin-gonic/gin/pull/1749)
+- [NEW] Added flag to context.Stream indicates if client disconnected in middle of stream [#1252](https://github.com/gin-gonic/gin/pull/1252)
+- [NEW] Extend context.File to allow for the content-dispositon attachments via a new method context.Attachment [#1260](https://github.com/gin-gonic/gin/pull/1260)
+- [NEW] Add prefix from X-Forwarded-Prefix in redirectTrailingSlash [#1238](https://github.com/gin-gonic/gin/pull/1238)
+- [NEW] Add context.HandlerNames() [#1729](https://github.com/gin-gonic/gin/pull/1729)
+- [NEW] Add response size to LogFormatterParams [#1752](https://github.com/gin-gonic/gin/pull/1752)
+- [NEW] Allow ignoring field on form mapping [#1733](https://github.com/gin-gonic/gin/pull/1733)
+- [NEW] Add a function to force color in console output. [#1724](https://github.com/gin-gonic/gin/pull/1724)
+- [NEW] Binding for URL Params [#1694](https://github.com/gin-gonic/gin/pull/1694)
+- [NEW] Add LoggerWithFormatter method [#1677](https://github.com/gin-gonic/gin/pull/1677)
+- [NEW] RunFd method to run http.Server through a file descriptor [#1609](https://github.com/gin-gonic/gin/pull/1609)
+- [NEW] Yaml binding support [#1618](https://github.com/gin-gonic/gin/pull/1618)
+- [NEW] Add PureJSON renderer [#694](https://github.com/gin-gonic/gin/pull/694)
+- [NEW] Set default time format in form binding [#1487](https://github.com/gin-gonic/gin/pull/1487)
+- [NEW] Upgrade dependency libraries [#1491](https://github.com/gin-gonic/gin/pull/1491)
+
+#### Bug fix
+
+- [FIX] Truncate Latency precision in long running request [#1830](https://github.com/gin-gonic/gin/pull/1830)
+- [FIX] IsTerm flag should not be affected by DisableConsoleColor method. [#1802](https://github.com/gin-gonic/gin/pull/1802)
+- [FIX] Readme updates [#1793](https://github.com/gin-gonic/gin/pull/1793) [#1788](https://github.com/gin-gonic/gin/pull/1788) [1789](https://github.com/gin-gonic/gin/pull/1789)
+- [FIX] StaticFS: Fixed Logging two log lines on 404. [#1805](https://github.com/gin-gonic/gin/pull/1805), [#1804](https://github.com/gin-gonic/gin/pull/1804)
+- [FIX] Moved [examples](https://github.com/gin-gonic/examples) to stand alone Repo [#1775](https://github.com/gin-gonic/gin/pull/1775)
+- [FIX] Support HTTP content negotiation wildcards [#1112](https://github.com/gin-gonic/gin/pull/1112)
+- [FIX] Pass MaxMultipartMemory when FormFile is called [#1600](https://github.com/gin-gonic/gin/pull/1600)
+- [FIX] LoadHTML* tests [#1559](https://github.com/gin-gonic/gin/pull/1559)
+- [FIX] Removed use of sync.pool from HandleContext [#1565](https://github.com/gin-gonic/gin/pull/1565)
+- [FIX] Format output log to os.Stderr [#1571](https://github.com/gin-gonic/gin/pull/1571)
+- [FIX] Make logger use a yellow background and a darkgray text for legibility [#1570](https://github.com/gin-gonic/gin/pull/1570)
+- [FIX] Remove sensitive request information from panic log. [#1370](https://github.com/gin-gonic/gin/pull/1370)
+- [FIX] log.Println() does not print timestamp [#829](https://github.com/gin-gonic/gin/pull/829) [#1560](https://github.com/gin-gonic/gin/pull/1560)
+- [FIX] Add missing copyright and update if/else [#1497](https://github.com/gin-gonic/gin/pull/1497)
+- [FIX] Update msgpack usage [#1498](https://github.com/gin-gonic/gin/pull/1498)
+- [FIX] Use protobuf on render [#1496](https://github.com/gin-gonic/gin/pull/1496)
+- [FIX] Add support for Protobuf format response [#1479](https://github.com/gin-gonic/gin/pull/1479)
+- [FIX] Add BindXML and ShouldBindXML [#1485](https://github.com/gin-gonic/gin/pull/1485)
+- [FIX] CI testing updates [#1671](https://github.com/gin-gonic/gin/pull/1671) [#1670](https://github.com/gin-gonic/gin/pull/1670) [#1682](https://github.com/gin-gonic/gin/pull/1682) [#1669](https://github.com/gin-gonic/gin/pull/1669)
+- [FIX] StaticFS(): Send 404 when path does not exist [#1663](https://github.com/gin-gonic/gin/pull/1663)
+- [FIX] Handle nil body for JSON binding [#1638](https://github.com/gin-gonic/gin/pull/1638)
+- [FIX] Support bind uri param [#1612](https://github.com/gin-gonic/gin/pull/1612)
+- [FIX] recovery: fix issue with syscall import on google app engine [#1640](https://github.com/gin-gonic/gin/pull/1640)
+- [FIX] Make sure the debug log contains line breaks [#1650](https://github.com/gin-gonic/gin/pull/1650)
+- [FIX] Panic stack trace being printed during recovery of broken pipe [#1089](https://github.com/gin-gonic/gin/pull/1089) [#1259](https://github.com/gin-gonic/gin/pull/1259)
+- [FIX] Context.Next() - recheck len of handlers on every iteration. [#1745](https://github.com/gin-gonic/gin/pull/1745)
+- [FIX] Fix all errcheck warnings [#1739](https://github.com/gin-gonic/gin/pull/1739) [#1653](https://github.com/gin-gonic/gin/pull/1653)
+- [FIX] Change color methods to public in the defaultLogger. [#1771](https://github.com/gin-gonic/gin/pull/1771)
+- [FIX] Update writeHeaders method to use http.Header.Set [#1722](https://github.com/gin-gonic/gin/pull/1722)
+- [FIX] context.Copy() race condition [#1020](https://github.com/gin-gonic/gin/pull/1020)
+
diff --git a/content/ru/blog/releases/release15.md b/content/ru/blog/releases/release15.md
new file mode 100644
index 000000000..e4593b3ce
--- /dev/null
+++ b/content/ru/blog/releases/release15.md
@@ -0,0 +1,47 @@
+---
+title: "Gin 1.5.0 is released"
+linkTitle: "Gin 1.5.0 is released"
+date: 2019-11-28
+---
+
+### CHANGELOG
+
+#### Feature
+
+- [NEW] Now you can parse the inline lowercase start structure [#1893](https://github.com/gin-gonic/gin/pull/1893)
+- [NEW] **[Break-Backward]** Hold matched route full path in the Context [#1826](https://github.com/gin-gonic/gin/pull/1826)
+- [NEW] Add context param query cache [#1450](https://github.com/gin-gonic/gin/pull/1450)
+- [NEW] Add support of multipart multi files [#1949](https://github.com/gin-gonic/gin/pull/1949)
+- [NEW] Support bind http header param [#1957](https://github.com/gin-gonic/gin/pull/1957)
+- [NEW] Support bind unix time [#1980](https://github.com/gin-gonic/gin/pull/1980)
+- [NEW] Support negative Content-Length in DataFromReader [#1981](https://github.com/gin-gonic/gin/pull/1981)
+- [NEW] Add DisallowUnknownFields() in gin.Context.BindJSON() [#2028](https://github.com/gin-gonic/gin/pull/2028)
+- [NEW] Use specific `net.Listener` with Engine.RunListener() [#2023](https://github.com/gin-gonic/gin/pull/2023)
+
+#### Bug fix
+
+- [FIX] Use DefaultWriter and DefaultErrorWriter for debug messages [#1891](https://github.com/gin-gonic/gin/pull/1891)
+- [FIX] Some code improvements [#1909](https://github.com/gin-gonic/gin/pull/1909)
+- [FIX] Use encode replace json marshal increase json encoder speed [#1546](https://github.com/gin-gonic/gin/pull/1546)
+- [FIX] Fix context.Params race condition on Copy() [#1841](https://github.com/gin-gonic/gin/pull/1841)
+- [FIX] Improve GetQueryMap performance [#1918](https://github.com/gin-gonic/gin/pull/1918)
+- [FIX] Improve get post data [#1920](https://github.com/gin-gonic/gin/pull/1920)
+- [FIX] Use context instead of x/net/context [#1922](https://github.com/gin-gonic/gin/pull/1922)
+- [FIX] Attempt to fix PostForm cache bug [#1931](https://github.com/gin-gonic/gin/pull/1931)
+- [FIX] **[Break-Backward]** Drop support for go1.8 and go1.9 [#1933](https://github.com/gin-gonic/gin/pull/1933)
+- [FIX] Bugfix for the FullPath feature [#1919](https://github.com/gin-gonic/gin/pull/1919)
+- [FIX] Gin1.5 bytes.Buffer to strings.Builder [#1939](https://github.com/gin-gonic/gin/pull/1939)
+- [FIX] Upgrade github.com/ugorji/go/codec [#1969](https://github.com/gin-gonic/gin/pull/1969)
+- [FIX] Simplify code [#2004](https://github.com/gin-gonic/gin/pull/2004)
+- [FIX] Identify terminal on a RISC-V architecture for auto-colored logs [#2019](https://github.com/gin-gonic/gin/pull/2019)
+- [FIX] **[Break-Backward]** Context.JSONP() now expects a semicolon (;) at the end [#2007](https://github.com/gin-gonic/gin/pull/2007)
+- [FIX] **[Break-Backward]** Upgrade validator version to v9 [#1015](https://github.com/gin-gonic/gin/pull/1015)
+- [FIX] Fix some typo [#2079](https://github.com/gin-gonic/gin/pull/2079) [#2080](https://github.com/gin-gonic/gin/pull/2080)
+- [FIX] Relocate binding body tests [#2086](https://github.com/gin-gonic/gin/pull/2086)
+- [FIX] Use Writer in Context.Status [#1606](https://github.com/gin-gonic/gin/pull/1606)
+- [FIX] `Engine.RunUnix()` now returns the error if it can't change the file mode [#2093](https://github.com/gin-gonic/gin/pull/2093)
+- [FIX] `RouterGroup.StaticFS()` leaked files. Now it closes them. [#2118](https://github.com/gin-gonic/gin/pull/2118)
+- [FIX] `Context.Request.FormFile` leaked file, now it closes it [#2114](https://github.com/gin-gonic/gin/pull/2114)
+- [FIX] Ignore walking on `form:"-"` mapping [#1943](https://github.com/gin-gonic/gin/pull/1943)
+- [REFACTOR] **[Break-Backward]** Use encode replace json marshal increase json encoder speed [#1546 ](https://github.com/gin-gonic/gin/pull/1546)
+
diff --git a/content/ru/blog/releases/release16.md b/content/ru/blog/releases/release16.md
new file mode 100644
index 000000000..539997c96
--- /dev/null
+++ b/content/ru/blog/releases/release16.md
@@ -0,0 +1,60 @@
+---
+title: "Gin 1.6.0 is released"
+linkTitle: "Gin 1.6.0 is released"
+date: 2020-03-22
+---
+
+### CHANGELOG
+
+#### BREAKING
+ * chore(performance): Improve performance for adding RemoveExtraSlash flag [#2159](https://github.com/gin-gonic/gin/pull/2159)
+ * drop support govendor [#2148](https://github.com/gin-gonic/gin/pull/2148)
+ * Added support for SameSite cookie flag [#1615](https://github.com/gin-gonic/gin/pull/1615)
+
+#### FEATURES
+ * add yaml negotitation [#2220](https://github.com/gin-gonic/gin/pull/2220)
+ * FileFromFS [#2112](https://github.com/gin-gonic/gin/pull/2112)
+
+#### BUGFIXES
+ * Unix Socket Handling [#2280](https://github.com/gin-gonic/gin/pull/2280)
+ * Use json marshall in context json to fix breaking new line issue. Fixes #2209 [#2228](https://github.com/gin-gonic/gin/pull/2228)
+ * fix accept incoming network connections [#2216](https://github.com/gin-gonic/gin/pull/2216)
+ * Fixed a bug in the calculation of the maximum number of parameters [#2166](https://github.com/gin-gonic/gin/pull/2166)
+ * [FIX] allow empty headers on DataFromReader [#2121](https://github.com/gin-gonic/gin/pull/2121)
+ * Add mutex for protect Context.Keys map [#1391](https://github.com/gin-gonic/gin/pull/1391)
+
+#### ENHANCEMENTS
+ * Add mitigation for log injection [#2277](https://github.com/gin-gonic/gin/pull/2277)
+ * tree: range over nodes values [#2229](https://github.com/gin-gonic/gin/pull/2229)
+ * tree: remove duplicate assignment [#2222](https://github.com/gin-gonic/gin/pull/2222)
+ * chore: upgrade go-isatty and json-iterator/go [#2215](https://github.com/gin-gonic/gin/pull/2215)
+ * path: sync code with httprouter [#2212](https://github.com/gin-gonic/gin/pull/2212)
+ * Use zero-copy approach to convert types between string and byte slice [#2206](https://github.com/gin-gonic/gin/pull/2206)
+ * Reuse bytes when cleaning the URL paths [#2179](https://github.com/gin-gonic/gin/pull/2179)
+ * tree: remove one else statement [#2177](https://github.com/gin-gonic/gin/pull/2177)
+ * tree: sync httprouter update (#2173) (#2172) [#2171](https://github.com/gin-gonic/gin/pull/2171)
+ * tree: sync part httprouter codes and reduce if/else [#2163](https://github.com/gin-gonic/gin/pull/2163)
+ * use http method constant [#2155](https://github.com/gin-gonic/gin/pull/2155)
+ * upgrade go-validator to v10 [#2149](https://github.com/gin-gonic/gin/pull/2149)
+ * Refactor redirect request in gin.go [#1970](https://github.com/gin-gonic/gin/pull/1970)
+ * Add build tag nomsgpack [#1852](https://github.com/gin-gonic/gin/pull/1852)
+
+#### DOCS
+ * docs(path): improve comments [#2223](https://github.com/gin-gonic/gin/pull/2223)
+ * Renew README to fit the modification of SetCookie method [#2217](https://github.com/gin-gonic/gin/pull/2217)
+ * Fix spelling [#2202](https://github.com/gin-gonic/gin/pull/2202)
+ * Remove broken link from README. [#2198](https://github.com/gin-gonic/gin/pull/2198)
+ * Update docs on Context.Done(), Context.Deadline() and Context.Err() [#2196](https://github.com/gin-gonic/gin/pull/2196)
+ * Update validator to v10 [#2190](https://github.com/gin-gonic/gin/pull/2190)
+ * upgrade go-validator to v10 for README [#2189](https://github.com/gin-gonic/gin/pull/2189)
+ * Update to currently output [#2188](https://github.com/gin-gonic/gin/pull/2188)
+ * Fix "Custom Validators" example [#2186](https://github.com/gin-gonic/gin/pull/2186)
+ * Add project to README [#2165](https://github.com/gin-gonic/gin/pull/2165)
+ * docs(benchmarks): for gin v1.5 [#2153](https://github.com/gin-gonic/gin/pull/2153)
+ * Changed wording for clarity in README.md [#2122](https://github.com/gin-gonic/gin/pull/2122)
+
+#### MISC
+ * ci support go1.14 [#2262](https://github.com/gin-gonic/gin/pull/2262)
+ * chore: upgrade depend version [#2231](https://github.com/gin-gonic/gin/pull/2231)
+ * Drop support go1.10 [#2147](https://github.com/gin-gonic/gin/pull/2147)
+ * fix comment in `mode.go` [#2129](https://github.com/gin-gonic/gin/pull/2129)
diff --git a/content/ru/docs/_index.md b/content/ru/docs/_index.md
new file mode 100644
index 000000000..b9876b7d0
--- /dev/null
+++ b/content/ru/docs/_index.md
@@ -0,0 +1,24 @@
+---
+название: "Документация"
+linkTitle: "Документация"
+вес: 20
+menu:
+ main:
+ вес: 20
+---
+
+## Что такое Gin?
+
+Gin - это HTTP-веб-фреймворк, написанный на языке Go (Golang). В нем реализован API, похожий на Martini, но с производительностью в 40 раз выше, чем у Martini. Если вам нужна потрясающая производительность, купите себе Gin.
+
+## Как использовать Gin?
+
+Мы приводим [примеры] использования API (https://github.com/gin-gonic/examples) и список известных пользователей [Gin](./users).
+
+## Как внести свой вклад в развитие Gin?
+
+* Помогайте людям на дискуссионных форумах.
+* Расскажите нам о своих успехах в использовании Gin
+* Расскажите нам, как мы можем улучшить Gin, и помогите нам в этом.
+* Внести вклад в существующую библиотеку
+
diff --git a/content/ru/docs/benchmarks/_index.md b/content/ru/docs/benchmarks/_index.md
new file mode 100644
index 000000000..c512f9258
--- /dev/null
+++ b/content/ru/docs/benchmarks/_index.md
@@ -0,0 +1,47 @@
+---
+title: "Контрольные показатели"
+draft: false
+weight: 3
+---
+
+Gin использует пользовательскую версию [HttpRouter](https://github.com/julienschmidt/httprouter).
+
+[Посмотреть все контрольные показатели](https://github.com/gin-gonic/gin/blob/master/BENCHMARKS.md)
+
+| Benchmark name | (1) | (2) | (3) | (4) |
+| ------------------------------ | ---------:| ---------------:| ------------:| ---------------:|
+| BenchmarkGin_GithubAll | **43550** | **27364 ns/op** | **0 B/op** | **0 allocs/op** |
+| BenchmarkAce_GithubAll | 40543 | 29670 ns/op | 0 B/op | 0 allocs/op |
+| BenchmarkAero_GithubAll | 57632 | 20648 ns/op | 0 B/op | 0 allocs/op |
+| BenchmarkBear_GithubAll | 9234 | 216179 ns/op | 86448 B/op | 943 allocs/op |
+| BenchmarkBeego_GithubAll | 7407 | 243496 ns/op | 71456 B/op | 609 allocs/op |
+| BenchmarkBone_GithubAll | 420 | 2922835 ns/op | 720160 B/op | 8620 allocs/op |
+| BenchmarkChi_GithubAll | 7620 | 238331 ns/op | 87696 B/op | 609 allocs/op |
+| BenchmarkDenco_GithubAll | 18355 | 64494 ns/op | 20224 B/op | 167 allocs/op |
+| BenchmarkEcho_GithubAll | 31251 | 38479 ns/op | 0 B/op | 0 allocs/op |
+| BenchmarkGocraftWeb_GithubAll | 4117 | 300062 ns/op | 131656 B/op | 1686 allocs/op |
+| BenchmarkGoji_GithubAll | 3274 | 416158 ns/op | 56112 B/op | 334 allocs/op |
+| BenchmarkGojiv2_GithubAll | 1402 | 870518 ns/op | 352720 B/op | 4321 allocs/op |
+| BenchmarkGoJsonRest_GithubAll | 2976 | 401507 ns/op | 134371 B/op | 2737 allocs/op |
+| BenchmarkGoRestful_GithubAll | 410 | 2913158 ns/op | 910144 B/op | 2938 allocs/op |
+| BenchmarkGorillaMux_GithubAll | 346 | 3384987 ns/op | 251650 B/op | 1994 allocs/op |
+| BenchmarkGowwwRouter_GithubAll | 10000 | 143025 ns/op | 72144 B/op | 501 allocs/op |
+| BenchmarkHttpRouter_GithubAll | 55938 | 21360 ns/op | 0 B/op | 0 allocs/op |
+| BenchmarkHttpTreeMux_GithubAll | 10000 | 153944 ns/op | 65856 B/op | 671 allocs/op |
+| BenchmarkKocha_GithubAll | 10000 | 106315 ns/op | 23304 B/op | 843 allocs/op |
+| BenchmarkLARS_GithubAll | 47779 | 25084 ns/op | 0 B/op | 0 allocs/op |
+| BenchmarkMacaron_GithubAll | 3266 | 371907 ns/op | 149409 B/op | 1624 allocs/op |
+| BenchmarkMartini_GithubAll | 331 | 3444706 ns/op | 226551 B/op | 2325 allocs/op |
+| BenchmarkPat_GithubAll | 273 | 4381818 ns/op | 1483152 B/op | 26963 allocs/op |
+| BenchmarkPossum_GithubAll | 10000 | 164367 ns/op | 84448 B/op | 609 allocs/op |
+| BenchmarkR2router_GithubAll | 10000 | 160220 ns/op | 77328 B/op | 979 allocs/op |
+| BenchmarkRivet_GithubAll | 14625 | 82453 ns/op | 16272 B/op | 167 allocs/op |
+| BenchmarkTango_GithubAll | 6255 | 279611 ns/op | 63826 B/op | 1618 allocs/op |
+| BenchmarkTigerTonic_GithubAll | 2008 | 687874 ns/op | 193856 B/op | 4474 allocs/op |
+| BenchmarkTraffic_GithubAll | 355 | 3478508 ns/op | 820744 B/op | 14114 allocs/op |
+| BenchmarkVulcan_GithubAll | 6885 | 193333 ns/op | 19894 B/op | 609 allocs/op |
+
+- (1): Общее количество повторений, достигнутое за постоянное время, большее количество означает более уверенный результат
+- (2): Длительность одного повторения (ns/op), меньше - лучше
+- (3): Память кучи (B/op), меньше - лучше
+- (4): Среднее количество выделений за повтор (allocs/op), ниже - лучше
diff --git a/content/ru/docs/deployment/_index.md b/content/ru/docs/deployment/_index.md
new file mode 100644
index 000000000..ac691d84a
--- /dev/null
+++ b/content/ru/docs/deployment/_index.md
@@ -0,0 +1,31 @@
+---
+title: "Deployment"
+draft: false
+weight: 6
+---
+
+Проекты Gin могут быть легко развернуты на любом облачном провайдере.
+
+## [Koyeb](https://www.koyeb.com)
+
+Koyeb - это удобная для разработчиков бессерверная платформа для глобального развертывания приложений с развертыванием на основе git, шифрованием TLS, встроенным автомасштабированием, глобальной пограничной сетью и встроенным сервисом mesh & discovery.
+
+Следуйте руководству Koyeb [Guide to deploy your Gin projects](https://www.koyeb.com/tutorials/deploy-go-gin-on-koyeb).
+
+## [Qovery](https://www.qovery.com)
+
+Qovery предоставляет бесплатный облачный хостинг с базами данных, SSL, глобальной CDN и автоматическим развертыванием с помощью Git.
+
+Следуйте руководству Qovery, чтобы [развернуть свой проект Gin](https://docs.qovery.com/guides/tutorial/deploy-gin-with-postgresql/).
+
+## [Render](https://render.com)
+
+Render - это современная облачная платформа, которая предлагает встроенную поддержку Go, полностью управляемый SSL, базы данных, деплой с нулевым временем простоя, HTTP/2 и поддержку websocket.
+
+Следуйте рекомендациям Render [руководство по развертыванию проектов Gin](https://render.com/docs/deploy-go-gin).
+
+## [Google App Engine](https://cloud.google.com/appengine/)
+
+В GAE есть два способа развертывания Go-приложений. Стандартная среда проще в использовании, но менее настраиваема и не допускает [syscalls](https://github.com/gin-gonic/gin/issues/1639) по соображениям безопасности. В гибком окружении можно запускать любые фреймворки и библиотеки.
+
+Узнать больше и выбрать предпочтительную среду можно на сайте [Go on Google App Engine](https://cloud.google.com/appengine/docs/go/).
diff --git a/content/ru/docs/examples/_index.md b/content/ru/docs/examples/_index.md
new file mode 100644
index 000000000..df13529a2
--- /dev/null
+++ b/content/ru/docs/examples/_index.md
@@ -0,0 +1,7 @@
+---
+название: "Примеры"
+черновик: false
+вес: 6
+---
+
+Раздел содержит список использования api.
diff --git a/content/ru/docs/examples/ascii-json.md b/content/ru/docs/examples/ascii-json.md
new file mode 100644
index 000000000..9eb014880
--- /dev/null
+++ b/content/ru/docs/examples/ascii-json.md
@@ -0,0 +1,25 @@
+---
+название: "AsciiJSON"
+черновик: false
+---
+
+Использование AsciiJSON для генерации ASCII-единственного JSON с экранированными не-ASCII символами.
+
+```go
+func main() {
+ r := gin.Default()
+
+ r.GET("/someJSON", func(c *gin.Context) {
+ data := map[string]interface{}{
+ "lang": "GO语言",
+ "tag": "
",
+ }
+
+ // will output : {"lang":"GO\u8bed\u8a00","tag":"\u003cbr\u003e"}
+ c.AsciiJSON(http.StatusOK, data)
+ })
+
+ // Listen and serve on 0.0.0.0:8080
+ r.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/bind-body-into-dirrerent-structs.md b/content/ru/docs/examples/bind-body-into-dirrerent-structs.md
new file mode 100644
index 000000000..008769777
--- /dev/null
+++ b/content/ru/docs/examples/bind-body-into-dirrerent-structs.md
@@ -0,0 +1,61 @@
+---
+название: "Попытайтесь связать тело в разных структурах"
+draft: false
+---
+
+Обычные методы для связывания тела запроса (request body) потребляют `c.Request.Body` и их
+не могут быть вызваны несколько раз.
+
+```go
+type formA struct {
+ Foo string `json:"foo" xml:"foo" binding:"required"`
+}
+
+type formB struct {
+ Bar string `json:"bar" xml:"bar" binding:"required"`
+}
+
+func SomeHandler(c *gin.Context) {
+ objA := formA{}
+ objB := formB{}
+ // This c.ShouldBind consumes c.Request.Body and it cannot be reused.
+ if errA := c.ShouldBind(&objA); errA == nil {
+ c.String(http.StatusOK, `the body should be formA`)
+ // Always an error is occurred by this because c.Request.Body is EOF now.
+ } else if errB := c.ShouldBind(&objB); errB == nil {
+ c.String(http.StatusOK, `the body should be formB`)
+ } else {
+ ...
+ }
+}
+```
+
+Для этого можно использовать `c.ShouldBindBodyWith`.
+
+```go
+func SomeHandler(c *gin.Context) {
+ objA := formA{}
+ objB := formB{}
+ // This reads c.Request.Body and stores the result into the context.
+ if errA := c.ShouldBindBodyWith(&objA, binding.JSON); errA == nil {
+ c.String(http.StatusOK, `the body should be formA`)
+ // At this time, it reuses body stored in the context.
+ } else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil {
+ c.String(http.StatusOK, `the body should be formB JSON`)
+ // And it can accepts other formats
+ } else if errB2 := c.ShouldBindBodyWith(&objB, binding.XML); errB2 == nil {
+ c.String(http.StatusOK, `the body should be formB XML`)
+ } else {
+ ...
+ }
+}
+```
+
+* `c.ShouldBindBodyWith` сохраняет тело в контексте перед привязкой. Это
+небольшое влияние на производительность, поэтому не стоит использовать этот метод, если вы
+достаточно вызвать привязку сразу.
+* Эта возможность необходима только для некоторых форматов - `JSON`, `XML`, `MsgPack`,
+`ProtoBuf`. Для других форматов, `Query`, `Form`, `FormPost`, `FormMultipart`,
+могут быть вызваны `c.ShouldBind()` многократно без ущерба для
+производительности (см. [#1341](https://github.com/gin-gonic/gin/pull/1341)).
+
diff --git a/content/ru/docs/examples/bind-form-data-request-with-custom-struct.md b/content/ru/docs/examples/bind-form-data-request-with-custom-struct.md
new file mode 100644
index 000000000..4567d90ee
--- /dev/null
+++ b/content/ru/docs/examples/bind-form-data-request-with-custom-struct.md
@@ -0,0 +1,77 @@
+---
+название: "Связывание запроса формы-данных с пользовательской структурой"
+черновик: false
+---
+
+Следующий пример с использованием пользовательской структуры:
+
+```go
+type StructA struct {
+ FieldA string `form:"field_a"`
+}
+
+type StructB struct {
+ NestedStruct StructA
+ FieldB string `form:"field_b"`
+}
+
+type StructC struct {
+ NestedStructPointer *StructA
+ FieldC string `form:"field_c"`
+}
+
+type StructD struct {
+ NestedAnonyStruct struct {
+ FieldX string `form:"field_x"`
+ }
+ FieldD string `form:"field_d"`
+}
+
+func GetDataB(c *gin.Context) {
+ var b StructB
+ c.Bind(&b)
+ c.JSON(200, gin.H{
+ "a": b.NestedStruct,
+ "b": b.FieldB,
+ })
+}
+
+func GetDataC(c *gin.Context) {
+ var b StructC
+ c.Bind(&b)
+ c.JSON(200, gin.H{
+ "a": b.NestedStructPointer,
+ "c": b.FieldC,
+ })
+}
+
+func GetDataD(c *gin.Context) {
+ var b StructD
+ c.Bind(&b)
+ c.JSON(200, gin.H{
+ "x": b.NestedAnonyStruct,
+ "d": b.FieldD,
+ })
+}
+
+func main() {
+ r := gin.Default()
+ r.GET("/getb", GetDataB)
+ r.GET("/getc", GetDataC)
+ r.GET("/getd", GetDataD)
+
+ r.Run()
+}
+```
+
+Результаты при использовании `curl`:
+
+```
+$ curl "http://localhost:8080/getb?field_a=hello&field_b=world"
+{"a":{"FieldA":"hello"},"b":"world"}
+$ curl "http://localhost:8080/getc?field_a=hello&field_c=world"
+{"a":{"FieldA":"hello"},"c":"world"}
+$ curl "http://localhost:8080/getd?field_x=hello&field_d=world"
+{"d":"world","x":{"FieldX":"hello"}}
+```
+
diff --git a/content/ru/docs/examples/bind-html-checkbox.md b/content/ru/docs/examples/bind-html-checkbox.md
new file mode 100644
index 000000000..8950b1699
--- /dev/null
+++ b/content/ru/docs/examples/bind-html-checkbox.md
@@ -0,0 +1,45 @@
+---
+title: "Привязка html-флажков"
+draft: false
+---
+
+Смотрите [подробную информацию](https://github.com/gin-gonic/gin/issues/129#issuecomment-124260092)
+
+```go
+...
+
+type myForm struct {
+ Colors []string `form:"colors[]"`
+}
+
+...
+
+func formHandler(c *gin.Context) {
+ var fakeForm myForm
+ c.ShouldBind(&fakeForm)
+ c.JSON(200, gin.H{"color": fakeForm.Colors})
+}
+
+...
+
+```
+
+```html
+
+```
+
+Результат:
+
+```sh
+{"color":["red","green","blue"]}
+```
+
diff --git a/content/ru/docs/examples/bind-query-or-post.md b/content/ru/docs/examples/bind-query-or-post.md
new file mode 100644
index 000000000..c013c89ca
--- /dev/null
+++ b/content/ru/docs/examples/bind-query-or-post.md
@@ -0,0 +1,48 @@
+---
+title: "Связать строку запроса или данные поста"
+черновик: false
+---
+
+Смотрите [подробную информацию](https://github.com/gin-gonic/gin/issues/742#issuecomment-264681292).
+
+```go
+package main
+
+import (
+ "log"
+ "time"
+
+ "github.com/gin-gonic/gin"
+)
+
+type Person struct {
+ Name string `form:"name"`
+ Address string `form:"address"`
+ Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
+}
+
+func main() {
+ route := gin.Default()
+ route.GET("/testing", startPage)
+ route.Run(":8085")
+}
+
+func startPage(c *gin.Context) {
+ var person Person
+ // If `GET`, only `Form` binding engine (`query`) used.
+ // If `POST`, first checks the `content-type` for `JSON` or `XML`, then uses `Form` (`form-data`).
+ // See more at https://github.com/gin-gonic/gin/blob/master/binding/binding.go#L48
+ if c.ShouldBind(&person) == nil {
+ log.Println(person.Name)
+ log.Println(person.Address)
+ log.Println(person.Birthday)
+ }
+
+ c.String(200, "Success")
+}
+```
+
+Тестирование:
+```sh
+$ curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15"
+```
diff --git a/content/ru/docs/examples/bind-single-binary-with-template.md b/content/ru/docs/examples/bind-single-binary-with-template.md
new file mode 100644
index 000000000..a01a567c7
--- /dev/null
+++ b/content/ru/docs/examples/bind-single-binary-with-template.md
@@ -0,0 +1,45 @@
+---
+title: "Создание единого бинарного файла с помощью шаблонов"
+draft: false
+---
+## Использование стороннего пакета
+
+Вы можете использовать сторонний пакет для сборки сервера в единый бинарник, содержащий шаблоны, используя [go-assets](https://github.com/jessevdk/go-assets).
+
+```go
+func main() {
+ r := gin.New()
+
+ t, err := loadTemplate()
+ if err != nil {
+ panic(err)
+ }
+ r.SetHTMLTemplate(t)
+
+ r.GET("/", func(c *gin.Context) {
+ c.HTML(http.StatusOK, "/html/index.tmpl", nil)
+ })
+ r.Run(":8080")
+}
+
+// loadTemplate loads templates embedded by go-assets-builder
+func loadTemplate() (*template.Template, error) {
+ t := template.New("")
+ for name, file := range Assets.Files {
+ if file.IsDir() || !strings.HasSuffix(name, ".tmpl") {
+ continue
+ }
+ h, err := ioutil.ReadAll(file)
+ if err != nil {
+ return nil, err
+ }
+ t, err = t.New(name).Parse(string(h))
+ if err != nil {
+ return nil, err
+ }
+ }
+ return t, nil
+}
+```
+
+Полный пример находится в каталоге [assets-in-binary/example01](https://github.com/gin-gonic/examples/tree/master/assets-in-binary/example01).
diff --git a/content/ru/docs/examples/bind-uri.md b/content/ru/docs/examples/bind-uri.md
new file mode 100644
index 000000000..654911691
--- /dev/null
+++ b/content/ru/docs/examples/bind-uri.md
@@ -0,0 +1,37 @@
+---
+Заголовок: "Связывание Uri"
+draft: false
+---
+
+Смотрите [подробную информацию](https://github.com/gin-gonic/gin/issues/846).
+
+```go
+package main
+
+import "github.com/gin-gonic/gin"
+
+type Person struct {
+ ID string `uri:"id" binding:"required,uuid"`
+ Name string `uri:"name" binding:"required"`
+}
+
+func main() {
+ route := gin.Default()
+ route.GET("/:name/:id", func(c *gin.Context) {
+ var person Person
+ if err := c.ShouldBindUri(&person); err != nil {
+ c.JSON(400, gin.H{"msg": err.Error()})
+ return
+ }
+ c.JSON(200, gin.H{"name": person.Name, "uuid": person.ID})
+ })
+ route.Run(":8088")
+}
+```
+
+Тестирование:
+
+```sh
+$ curl -v localhost:8088/thinkerou/987fbc97-4bed-5078-9f07-9141ba07c9f3
+$ curl -v localhost:8088/thinkerou/not-uuid
+```
diff --git a/content/ru/docs/examples/binding-and-validation.md b/content/ru/docs/examples/binding-and-validation.md
new file mode 100644
index 000000000..2f7d35e62
--- /dev/null
+++ b/content/ru/docs/examples/binding-and-validation.md
@@ -0,0 +1,118 @@
+---
+Заголовок: "Связывание и проверка моделей"
+черновик: false
+---
+
+Чтобы привязать тело запроса к типу, используйте привязку к модели. В настоящее время мы поддерживаем привязку JSON, XML, YAML и стандартных значений формы (foo=bar&boo=baz).
+
+Для валидации Gin использует [**go-playground/validator/v10**](https://github.com/go-playground/validator). Ознакомьтесь с полной документацией по использованию тегов [здесь](https://pkg.go.dev/github.com/go-playground/validator/v10#hdr-Baked_In_Validators_and_Tags).
+
+Обратите внимание, что вам необходимо установить соответствующий тег привязки для всех полей, которые вы хотите привязать. Например, при привязке из JSON установите `json: "fieldname"`.
+
+Кроме того, Gin предоставляет два набора методов для привязки:
+- **Type** - Must bind
+ - **Методы** - `Bind`, `BindJSON`, `BindXML`, `BindQuery`, `BindYAML`
+ - **Поведение** - Эти методы используют `MustBindWith` под капотом. Если произошла ошибка связывания, запрос прерывается с помощью `c.AbortWithError(400, err).SetType(ErrorTypeBind)`. При этом код состояния ответа принимает значение 400, а заголовок `Content-Type` устанавливается на `text/plain; charset=utf-8`. Обратите внимание, что если вы попытаетесь установить код ответа после этого, то это приведет к предупреждению `[GIN-debug] [WARNING] Заголовки уже были записаны. Хотелось отменить код статуса 400 на 422`. Если вы хотите получить больший контроль над поведением, используйте эквивалентный метод `ShouldBind`.
+- **Тип** - Should bind
+ - **Методы** - `ShouldBind`, `ShouldBindJSON`, `ShouldBindXML`, `ShouldBindQuery`, `ShouldBindYAML`
+ - **Поведение** - Эти методы используют `ShouldBindWith` под капотом. Если произошла ошибка связывания, возвращается ошибка, и разработчик обязан обработать запрос и ошибку соответствующим образом.
+
+При использовании Bind-метода Gin пытается определить связующее звено в зависимости от заголовка Content-Type. Если вы уверены, что именно вы связываете, вы можете использовать `MustBindWith` или `ShouldBindWith`.
+
+Вы также можете указать, что определенные поля являются обязательными. Если поле украшено `binding: "required"` и при привязке имеет пустое значение, будет возвращена ошибка.
+
+```go
+// Binding from JSON
+type Login struct {
+ User string `form:"user" json:"user" xml:"user" binding:"required"`
+ Password string `form:"password" json:"password" xml:"password" binding:"required"`
+}
+
+func main() {
+ router := gin.Default()
+
+ // Example for binding JSON ({"user": "manu", "password": "123"})
+ router.POST("/loginJSON", func(c *gin.Context) {
+ var json Login
+ if err := c.ShouldBindJSON(&json); err != nil {
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+ return
+ }
+
+ if json.User != "manu" || json.Password != "123" {
+ c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
+ return
+ }
+
+ c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
+ })
+
+ // Example for binding XML (
+ //
+ //
+ // manu
+ // 123
+ // )
+ router.POST("/loginXML", func(c *gin.Context) {
+ var xml Login
+ if err := c.ShouldBindXML(&xml); err != nil {
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+ return
+ }
+
+ if xml.User != "manu" || xml.Password != "123" {
+ c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
+ return
+ }
+
+ c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
+ })
+
+ // Example for binding a HTML form (user=manu&password=123)
+ router.POST("/loginForm", func(c *gin.Context) {
+ var form Login
+ // This will infer what binder to use depending on the content-type header.
+ if err := c.ShouldBind(&form); err != nil {
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+ return
+ }
+
+ if form.User != "manu" || form.Password != "123" {
+ c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
+ return
+ }
+
+ c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
+ })
+
+ // Listen and serve on 0.0.0.0:8080
+ router.Run(":8080")
+}
+```
+
+### Пример запроса
+
+```sh
+$ curl -v -X POST \
+ http://localhost:8080/loginJSON \
+ -H 'content-type: application/json' \
+ -d '{ "user": "manu" }'
+> POST /loginJSON HTTP/1.1
+> Host: localhost:8080
+> User-Agent: curl/7.51.0
+> Accept: */*
+> content-type: application/json
+> Content-Length: 18
+>
+* upload completely sent off: 18 out of 18 bytes
+< HTTP/1.1 400 Bad Request
+< Content-Type: application/json; charset=utf-8
+< Date: Fri, 04 Aug 2017 03:51:31 GMT
+< Content-Length: 100
+<
+{"error":"Key: 'Login.Password' Error:Field validation for 'Password' failed on the 'required' tag"}
+```
+
+### Пропустить валидацию
+
+При выполнении приведенного выше примера с помощью указанной выше команды `curl` возвращается ошибка. Потому что в примере используется `привязка: "required"` для `Password`. Если использовать `binding:"-"` для `Password`, то при повторном запуске приведенного выше примера ошибка не возникнет.
diff --git a/content/ru/docs/examples/controlling-log-output-coloring.md b/content/ru/docs/examples/controlling-log-output-coloring.md
new file mode 100644
index 000000000..248c10818
--- /dev/null
+++ b/content/ru/docs/examples/controlling-log-output-coloring.md
@@ -0,0 +1,44 @@
+---
+title: "Управление раскраской вывода журнала"
+draft: false
+---
+
+По умолчанию логи, выводимые на консоль, должны быть окрашены в зависимости от обнаруженного TTY.
+
+Никогда не окрашивать журналы:
+
+```go
+func main() {
+ // Disable log's color
+ gin.DisableConsoleColor()
+
+ // Creates a gin router with default middleware:
+ // logger and recovery (crash-free) middleware
+ router := gin.Default()
+
+ router.GET("/ping", func(c *gin.Context) {
+ c.String(200, "pong")
+ })
+
+ router.Run(":8080")
+}
+```
+
+Всегда окрашивайте журналы в разные цвета:
+
+```go
+func main() {
+ // Force log's color
+ gin.ForceConsoleColor()
+
+ // Creates a gin router with default middleware:
+ // logger and recovery (crash-free) middleware
+ router := gin.Default()
+
+ router.GET("/ping", func(c *gin.Context) {
+ c.String(200, "pong")
+ })
+
+ router.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/cookie.md b/content/ru/docs/examples/cookie.md
new file mode 100644
index 000000000..7cf85e3ca
--- /dev/null
+++ b/content/ru/docs/examples/cookie.md
@@ -0,0 +1,31 @@
+---
+Название: "Установка и получение cookie"
+черновик: false
+---
+
+```go
+import (
+ "fmt"
+
+ "github.com/gin-gonic/gin"
+)
+
+func main() {
+
+ router := gin.Default()
+
+ router.GET("/cookie", func(c *gin.Context) {
+
+ cookie, err := c.Cookie("gin_cookie")
+
+ if err != nil {
+ cookie = "NotSet"
+ c.SetCookie("gin_cookie", "test", 3600, "/", "localhost", false, true)
+ }
+
+ fmt.Printf("Cookie value: %s \n", cookie)
+ })
+
+ router.Run()
+}
+```
diff --git a/content/ru/docs/examples/custom-http-config.md b/content/ru/docs/examples/custom-http-config.md
new file mode 100644
index 000000000..b6f84b975
--- /dev/null
+++ b/content/ru/docs/examples/custom-http-config.md
@@ -0,0 +1,33 @@
+---
+Название: "Пользовательская конфигурация HTTP"
+черновик: false
+---
+
+Используйте `http.ListenAndServe()` напрямую, например, так:
+
+```go
+import "net/http"
+
+func main() {
+ router := gin.Default()
+ http.ListenAndServe(":8080", router)
+}
+```
+or
+
+```go
+import "net/http"
+
+func main() {
+ router := gin.Default()
+
+ s := &http.Server{
+ Addr: ":8080",
+ Handler: router,
+ ReadTimeout: 10 * time.Second,
+ WriteTimeout: 10 * time.Second,
+ MaxHeaderBytes: 1 << 20,
+ }
+ s.ListenAndServe()
+}
+```
diff --git a/content/ru/docs/examples/custom-log-format.md b/content/ru/docs/examples/custom-log-format.md
new file mode 100644
index 000000000..00613371b
--- /dev/null
+++ b/content/ru/docs/examples/custom-log-format.md
@@ -0,0 +1,38 @@
+---
+Название: "Пользовательский файл журнала"
+черновик: false
+---
+
+Например:
+
+```go
+func main() {
+ router := gin.New()
+ // LoggerWithFormatter middleware will write the logs to gin.DefaultWriter
+ // By default gin.DefaultWriter = os.Stdout
+ router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
+ // your custom format
+ return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
+ param.ClientIP,
+ param.TimeStamp.Format(time.RFC1123),
+ param.Method,
+ param.Path,
+ param.Request.Proto,
+ param.StatusCode,
+ param.Latency,
+ param.Request.UserAgent(),
+ param.ErrorMessage,
+ )
+ }))
+ router.Use(gin.Recovery())
+ router.GET("/ping", func(c *gin.Context) {
+ c.String(200, "pong")
+ })
+ router.Run(":8080")
+}
+```
+
+**Образец вывода**
+```
+::1 - [Fri, 07 Dec 2018 17:04:38 JST] "GET /ping HTTP/1.1 200 122.767µs "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36" "
+```
diff --git a/content/ru/docs/examples/custom-middleware.md b/content/ru/docs/examples/custom-middleware.md
new file mode 100644
index 000000000..2ae281da3
--- /dev/null
+++ b/content/ru/docs/examples/custom-middleware.md
@@ -0,0 +1,43 @@
+---
+название: "Custom Middleware"
+черновик: false
+---
+
+```go
+func Logger() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ t := time.Now()
+
+ // Set example variable
+ c.Set("example", "12345")
+
+ // before request
+
+ c.Next()
+
+ // after request
+ latency := time.Since(t)
+ log.Print(latency)
+
+ // access the status we are sending
+ status := c.Writer.Status()
+ log.Println(status)
+ }
+}
+
+func main() {
+ r := gin.New()
+ r.Use(Logger())
+
+ r.GET("/test", func(c *gin.Context) {
+ example := c.MustGet("example").(string)
+
+ // it would print: "12345"
+ log.Println(example)
+ })
+
+ // Listen and serve on 0.0.0.0:8080
+ r.Run(":8080")
+}
+```
+
diff --git a/content/ru/docs/examples/custom-validators.md b/content/ru/docs/examples/custom-validators.md
new file mode 100644
index 000000000..53790bf18
--- /dev/null
+++ b/content/ru/docs/examples/custom-validators.md
@@ -0,0 +1,67 @@
+---
+название: "Пользовательские валидаторы"
+draft: false
+---
+
+Также можно зарегистрировать пользовательские валидаторы. Смотрите [пример кода](https://github.com/gin-gonic/examples/tree/master/struct-lvl-validations).
+
+```go
+package main
+
+import (
+ "net/http"
+ "time"
+
+ "github.com/gin-gonic/gin"
+ "github.com/gin-gonic/gin/binding"
+ "github.com/go-playground/validator/v10"
+)
+
+// Booking contains binded and validated data.
+type Booking struct {
+ CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
+ CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn,bookabledate" time_format:"2006-01-02"`
+}
+
+var bookableDate validator.Func = func(fl validator.FieldLevel) bool {
+ date, ok := fl.Field().Interface().(time.Time)
+ if ok {
+ today := time.Now()
+ if today.After(date) {
+ return false
+ }
+ }
+ return true
+}
+
+func main() {
+ route := gin.Default()
+
+ if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
+ v.RegisterValidation("bookabledate", bookableDate)
+ }
+
+ route.GET("/bookable", getBookable)
+ route.Run(":8085")
+}
+
+func getBookable(c *gin.Context) {
+ var b Booking
+ if err := c.ShouldBindWith(&b, binding.Query); err == nil {
+ c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"})
+ } else {
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+ }
+}
+```
+
+```sh
+$ curl "localhost:8085/bookable?check_in=2118-04-16&check_out=2118-04-17"
+{"message":"Booking dates are valid!"}
+
+$ curl "localhost:8085/bookable?check_in=2118-03-10&check_out=2118-03-09"
+{"error":"Key: 'Booking.CheckOut' Error:Field validation for 'CheckOut' failed on the 'gtfield' tag"}
+```
+
+[Валидации уровня структуры](https://github.com/go-playground/validator/releases/tag/v8.7) также могут быть зарегистрированы таким образом.
+Смотрите пример [struct-lvl-validation](https://github.com/gin-gonic/examples/tree/master/struct-lvl-validations), чтобы узнать больше.
diff --git a/content/ru/docs/examples/define-format-for-the-log-of-routes.md b/content/ru/docs/examples/define-format-for-the-log-of-routes.md
new file mode 100644
index 000000000..214f502fa
--- /dev/null
+++ b/content/ru/docs/examples/define-format-for-the-log-of-routes.md
@@ -0,0 +1,44 @@
+---
+Заголовок: "Определить формат для журнала маршрутов".
+черновик: false
+---
+
+По умолчанию журнал маршрутов имеет следующий вид:
+```
+[GIN-debug] POST /foo --> main.main.func1 (3 handlers)
+[GIN-debug] GET /bar --> main.main.func2 (3 handlers)
+[GIN-debug] GET /status --> main.main.func3 (3 handlers)
+```
+
+Если вы хотите записывать эту информацию в заданном формате (например, JSON, значения ключей или что-то еще), то вы можете определить этот формат с помощью `gin.DebugPrintRouteFunc`.
+В примере ниже мы ведем лог всех маршрутов с помощью стандартного пакета лога, но вы можете использовать другие инструменты лога, которые подходят для ваших нужд.
+```go
+import (
+ "log"
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+)
+
+func main() {
+ r := gin.Default()
+ gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
+ log.Printf("endpoint %v %v %v %v\n", httpMethod, absolutePath, handlerName, nuHandlers)
+ }
+
+ r.POST("/foo", func(c *gin.Context) {
+ c.JSON(http.StatusOK, "foo")
+ })
+
+ r.GET("/bar", func(c *gin.Context) {
+ c.JSON(http.StatusOK, "bar")
+ })
+
+ r.GET("/status", func(c *gin.Context) {
+ c.JSON(http.StatusOK, "ok")
+ })
+
+ // Listen and Server in http://0.0.0.0:8080
+ r.Run()
+}
+```
diff --git a/content/ru/docs/examples/goroutines-inside-a-middleware.md b/content/ru/docs/examples/goroutines-inside-a-middleware.md
new file mode 100644
index 000000000..da91a0ea4
--- /dev/null
+++ b/content/ru/docs/examples/goroutines-inside-a-middleware.md
@@ -0,0 +1,35 @@
+---
+Заголовок: "Гороутины внутри промежуточного ПО"
+черновик: false
+---
+
+При запуске новых Goroutines внутри промежуточного ПО или обработчика, вы **НЕ ДОЛЖНЫ** использовать оригинальный контекст внутри него, вы должны использовать копию, доступную только для чтения.
+
+```go
+func main() {
+ r := gin.Default()
+
+ r.GET("/long_async", func(c *gin.Context) {
+ // create copy to be used inside the goroutine
+ cCp := c.Copy()
+ go func() {
+ // simulate a long task with time.Sleep(). 5 seconds
+ time.Sleep(5 * time.Second)
+
+ // note that you are using the copied context "cCp", IMPORTANT
+ log.Println("Done! in path " + cCp.Request.URL.Path)
+ }()
+ })
+
+ r.GET("/long_sync", func(c *gin.Context) {
+ // simulate a long task with time.Sleep(). 5 seconds
+ time.Sleep(5 * time.Second)
+
+ // since we are NOT using a goroutine, we do not have to copy the context
+ log.Println("Done! in path " + c.Request.URL.Path)
+ })
+
+ // Listen and serve on 0.0.0.0:8080
+ r.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/graceful-restart-or-stop.md b/content/ru/docs/examples/graceful-restart-or-stop.md
new file mode 100644
index 000000000..2f5caca7b
--- /dev/null
+++ b/content/ru/docs/examples/graceful-restart-or-stop.md
@@ -0,0 +1,85 @@
+---
+Заголовок: "Благодатный перезапуск или остановка"
+черновик: false
+---
+
+Вы хотите произвести плавный перезапуск или остановку вашего веб-сервера?
+Есть несколько способов сделать это.
+
+Мы можем использовать [fvbock/endless](https://github.com/fvbock/endless) для замены стандартного `ListenAndServe`. Более подробную информацию см. в выпуске [#296](https://github.com/gin-gonic/gin/issues/296).
+
+```go
+router := gin.Default()
+router.GET("/", handler)
+// [...]
+endless.ListenAndServe(":4242", router)
+```
+
+Альтернатива бесконечности:
+
+* [manners](https://github.com/braintree/manners): Вежливый HTTP-сервер Go, который изящно завершает работу.
+* [graceful](https://github.com/tylerb/graceful): Graceful - это пакет Go, позволяющий изящно завершить работу сервера http.Handler.
+* [grace](https://github.com/facebookgo/grace): Graceful restart & zero downtime deploy для Go-серверов.
+
+Если вы используете Go 1.8, возможно, вам не понадобится эта библиотека! Лучше используйте встроенный метод http.Server [Shutdown()](https://golang.org/pkg/net/http/#Server.Shutdown) для изящного завершения работы. Посмотрите полный пример [graceful-shutdown](https://github.com/gin-gonic/examples/tree/master/graceful-shutdown) с gin.
+
+```go
+// +build go1.8
+
+package main
+
+import (
+ "context"
+ "log"
+ "net/http"
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+
+ "github.com/gin-gonic/gin"
+)
+
+func main() {
+ router := gin.Default()
+ router.GET("/", func(c *gin.Context) {
+ time.Sleep(5 * time.Second)
+ c.String(http.StatusOK, "Welcome Gin Server")
+ })
+
+ srv := &http.Server{
+ Addr: ":8080",
+ Handler: router.Handler(),
+ }
+
+ go func() {
+ // service connections
+ if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+ log.Fatalf("listen: %s\n", err)
+ }
+ }()
+
+ // Wait for interrupt signal to gracefully shutdown the server with
+ // a timeout of 5 seconds.
+ quit := make(chan os.Signal, 1)
+ // kill (no param) default send syscall.SIGTERM
+ // kill -2 is syscall.SIGINT
+ // kill -9 is syscall. SIGKILL but can"t be catch, so don't need add it
+ signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
+ <-quit
+ log.Println("Shutdown Server ...")
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+ if err := srv.Shutdown(ctx); err != nil {
+ log.Fatal("Server Shutdown:", err)
+ }
+ // catching ctx.Done(). timeout of 5 seconds.
+ select {
+ case <-ctx.Done():
+ log.Println("timeout of 5 seconds.")
+ }
+ log.Println("Server exiting")
+}
+```
+
diff --git a/content/ru/docs/examples/grouping-routes.md b/content/ru/docs/examples/grouping-routes.md
new file mode 100644
index 000000000..6e23d2e6a
--- /dev/null
+++ b/content/ru/docs/examples/grouping-routes.md
@@ -0,0 +1,28 @@
+---
+Заголовок: "Группировка маршрутов"
+черновик: false
+---
+
+```go
+func main() {
+ router := gin.Default()
+
+ // Simple group: v1
+ v1 := router.Group("/v1")
+ {
+ v1.POST("/login", loginEndpoint)
+ v1.POST("/submit", submitEndpoint)
+ v1.POST("/read", readEndpoint)
+ }
+
+ // Simple group: v2
+ v2 := router.Group("/v2")
+ {
+ v2.POST("/login", loginEndpoint)
+ v2.POST("/submit", submitEndpoint)
+ v2.POST("/read", readEndpoint)
+ }
+
+ router.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/html-rendering.md b/content/ru/docs/examples/html-rendering.md
new file mode 100644
index 000000000..d489dda4e
--- /dev/null
+++ b/content/ru/docs/examples/html-rendering.md
@@ -0,0 +1,150 @@
+---
+Заголовок: "HTML-рендеринг"
+draft: false
+---
+
+Использование LoadHTMLGlob() или LoadHTMLFiles()
+
+```go
+func main() {
+ router := gin.Default()
+ router.LoadHTMLGlob("templates/*")
+ //router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")
+ router.GET("/index", func(c *gin.Context) {
+ c.HTML(http.StatusOK, "index.tmpl", gin.H{
+ "title": "Main website",
+ })
+ })
+ router.Run(":8080")
+}
+```
+
+templates/index.tmpl
+
+```html
+
+
+ {{ .title }}
+
+
+```
+
+Использование шаблонов с одинаковыми именами в разных каталогах
+
+```go
+func main() {
+ router := gin.Default()
+ router.LoadHTMLGlob("templates/**/*")
+ router.GET("/posts/index", func(c *gin.Context) {
+ c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
+ "title": "Posts",
+ })
+ })
+ router.GET("/users/index", func(c *gin.Context) {
+ c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
+ "title": "Users",
+ })
+ })
+ router.Run(":8080")
+}
+```
+
+templates/posts/index.tmpl
+
+```html
+{{ define "posts/index.tmpl" }}
+
+ {{ .title }}
+
+Using posts/index.tmpl
+
+{{ end }}
+```
+
+templates/users/index.tmpl
+
+```html
+{{ define "users/index.tmpl" }}
+
+ {{ .title }}
+
+Using users/index.tmpl
+
+{{ end }}
+```
+
+### Пользовательский рендерер шаблонов
+
+Вы также можете использовать собственный рендерер html-шаблонов
+
+```go
+import "html/template"
+
+func main() {
+ router := gin.Default()
+ html := template.Must(template.ParseFiles("file1", "file2"))
+ router.SetHTMLTemplate(html)
+ router.Run(":8080")
+}
+```
+
+### Пользовательские разделители
+
+Вы можете использовать пользовательские разделители
+
+```go
+ r := gin.Default()
+ r.Delims("{[{", "}]}")
+ r.LoadHTMLGlob("/path/to/templates")
+```
+
+### Пользовательские функции шаблона
+
+Смотрите подробный [пример кода](https://github.com/gin-gonic/examples/tree/master/template).
+
+main.go
+
+```go
+import (
+ "fmt"
+ "html/template"
+ "net/http"
+ "time"
+
+ "github.com/gin-gonic/gin"
+)
+
+func formatAsDate(t time.Time) string {
+ year, month, day := t.Date()
+ return fmt.Sprintf("%d/%02d/%02d", year, month, day)
+}
+
+func main() {
+ router := gin.Default()
+ router.Delims("{[{", "}]}")
+ router.SetFuncMap(template.FuncMap{
+ "formatAsDate": formatAsDate,
+ })
+ router.LoadHTMLFiles("./testdata/template/raw.tmpl")
+
+ router.GET("/raw", func(c *gin.Context) {
+ c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{
+ "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
+ })
+ })
+
+ router.Run(":8080")
+}
+
+```
+
+raw.tmpl
+
+```sh
+Date: {[{.now | formatAsDate}]}
+```
+
+Result:
+```sh
+Date: 2017/07/01
+```
diff --git a/content/ru/docs/examples/http-method.md b/content/ru/docs/examples/http-method.md
new file mode 100644
index 000000000..de7199323
--- /dev/null
+++ b/content/ru/docs/examples/http-method.md
@@ -0,0 +1,25 @@
+---
+Заголовок: "Использование метода HTTP"
+draft: false
+---
+
+```go
+func main() {
+ // Creates a gin router with default middleware:
+ // logger and recovery (crash-free) middleware
+ router := gin.Default()
+
+ router.GET("/someGet", getting)
+ router.POST("/somePost", posting)
+ router.PUT("/somePut", putting)
+ router.DELETE("/someDelete", deleting)
+ router.PATCH("/somePatch", patching)
+ router.HEAD("/someHead", head)
+ router.OPTIONS("/someOptions", options)
+
+ // By default it serves on :8080 unless a
+ // PORT environment variable was defined.
+ router.Run()
+ // router.Run(":3000") for a hard coded port
+}
+```
diff --git a/content/ru/docs/examples/http2-server-push.md b/content/ru/docs/examples/http2-server-push.md
new file mode 100644
index 000000000..22130a359
--- /dev/null
+++ b/content/ru/docs/examples/http2-server-push.md
@@ -0,0 +1,51 @@
+---
+Заголовок: "HTTP2 server push"
+черновик: false
+---
+
+http.Pusher поддерживается только **go1.8+**. Подробную информацию смотрите в [golang blog](https://blog.golang.org/h2push).
+
+```go
+package main
+
+import (
+ "html/template"
+ "log"
+
+ "github.com/gin-gonic/gin"
+)
+
+var html = template.Must(template.New("https").Parse(`
+
+
+ Https Test
+
+
+
+ Welcome, Ginner!
+
+
+`))
+
+func main() {
+ r := gin.Default()
+ r.Static("/assets", "./assets")
+ r.SetHTMLTemplate(html)
+
+ r.GET("/", func(c *gin.Context) {
+ if pusher := c.Writer.Pusher(); pusher != nil {
+ // use pusher.Push() to do server push
+ if err := pusher.Push("/assets/app.js", nil); err != nil {
+ log.Printf("Failed to push: %v", err)
+ }
+ }
+ c.HTML(200, "https", gin.H{
+ "status": "success",
+ })
+ })
+
+ // Listen and Serve in https://127.0.0.1:8080
+ r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key")
+}
+```
+
diff --git a/content/ru/docs/examples/jsonp.md b/content/ru/docs/examples/jsonp.md
new file mode 100644
index 000000000..b5c75a17c
--- /dev/null
+++ b/content/ru/docs/examples/jsonp.md
@@ -0,0 +1,25 @@
+---
+Заголовок: "JSONP"
+черновик: false
+---
+
+Использование JSONP для запроса данных с сервера в другом домене. Добавьте обратный вызов в тело ответа, если существует обратный вызов параметра запроса.
+
+```go
+func main() {
+ r := gin.Default()
+
+ r.GET("/JSONP?callback=x", func(c *gin.Context) {
+ data := map[string]interface{}{
+ "foo": "bar",
+ }
+
+ //callback is x
+ // Will output : x({\"foo\":\"bar\"})
+ c.JSONP(http.StatusOK, data)
+ })
+
+ // Listen and serve on 0.0.0.0:8080
+ r.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/map-as-querystring-or-postform.md b/content/ru/docs/examples/map-as-querystring-or-postform.md
new file mode 100644
index 000000000..dd11f2416
--- /dev/null
+++ b/content/ru/docs/examples/map-as-querystring-or-postform.md
@@ -0,0 +1,31 @@
+---
+Заголовок: "Структура данных Map виде строки запроса или параметров постформы"
+draft: false
+---
+
+```sh
+POST /post?ids[a]=1234&ids[b]=hello HTTP/1.1
+Content-Type: application/x-www-form-urlencoded
+
+names[first]=thinkerou&names[second]=tianou
+```
+
+```go
+func main() {
+ router := gin.Default()
+
+ router.POST("/post", func(c *gin.Context) {
+
+ ids := c.QueryMap("ids")
+ names := c.PostFormMap("names")
+
+ fmt.Printf("ids: %v; names: %v", ids, names)
+ })
+ router.Run(":8080")
+}
+```
+
+```sh
+ids: map[b:hello a:1234], names: map[second:tianou first:thinkerou]
+```
+
diff --git a/content/ru/docs/examples/multipart-urlencoded-binding.md b/content/ru/docs/examples/multipart-urlencoded-binding.md
new file mode 100644
index 000000000..1486ec109
--- /dev/null
+++ b/content/ru/docs/examples/multipart-urlencoded-binding.md
@@ -0,0 +1,41 @@
+---
+Заголовок: "Связка Multipart/Urlencoded"
+draft: false
+---
+
+```go
+package main
+
+import (
+ "github.com/gin-gonic/gin"
+)
+
+type LoginForm struct {
+ User string `form:"user" binding:"required"`
+ Password string `form:"password" binding:"required"`
+}
+
+func main() {
+ router := gin.Default()
+ router.POST("/login", func(c *gin.Context) {
+ // you can bind multipart form with explicit binding declaration:
+ // c.ShouldBindWith(&form, binding.Form)
+ // or you can simply use autobinding with ShouldBind method:
+ var form LoginForm
+ // in this case proper binding will be automatically selected
+ if c.ShouldBind(&form) == nil {
+ if form.User == "user" && form.Password == "password" {
+ c.JSON(200, gin.H{"status": "you are logged in"})
+ } else {
+ c.JSON(401, gin.H{"status": "unauthorized"})
+ }
+ }
+ })
+ router.Run(":8080")
+}
+```
+
+Тестирование:
+```sh
+$ curl -v --form user=user --form password=password http://localhost:8080/login
+```
diff --git a/content/ru/docs/examples/multipart-urlencoded-form.md b/content/ru/docs/examples/multipart-urlencoded-form.md
new file mode 100644
index 000000000..b9e4b6b6f
--- /dev/null
+++ b/content/ru/docs/examples/multipart-urlencoded-form.md
@@ -0,0 +1,23 @@
+---
+Заголовок: "Форма Multipart/Urlencoded"
+draft: false
+---
+
+```go
+func main() {
+ router := gin.Default()
+
+ router.POST("/form_post", func(c *gin.Context) {
+ message := c.PostForm("message")
+ nick := c.DefaultPostForm("nick", "anonymous")
+
+ c.JSON(200, gin.H{
+ "status": "posted",
+ "message": message,
+ "nick": nick,
+ })
+ })
+ router.Run(":8080")
+}
+```
+
diff --git a/content/ru/docs/examples/multiple-template.md b/content/ru/docs/examples/multiple-template.md
new file mode 100644
index 000000000..6f3f0b3ea
--- /dev/null
+++ b/content/ru/docs/examples/multiple-template.md
@@ -0,0 +1,6 @@
+---
+Заголовок: "Несколько HTML темплейтов"
+черновик: false
+---
+
+Gin позволяет по умолчанию использовать только один html.Template. Проверьте [a multitemplate render](https://github.com/gin-contrib/multitemplate) для использования таких возможностей, как go 1.6 `block template`.
diff --git a/content/ru/docs/examples/only-bind-query-string.md b/content/ru/docs/examples/only-bind-query-string.md
new file mode 100644
index 000000000..ffae2c6fc
--- /dev/null
+++ b/content/ru/docs/examples/only-bind-query-string.md
@@ -0,0 +1,37 @@
+---
+Заголовок: "Только связывание строки запроса"
+draft: false
+---
+
+Функция `ShouldBindQuery` связывает только параметры запроса, но не данные поста. См. [подробную информацию](https://github.com/gin-gonic/gin/issues/742#issuecomment-315953017).
+
+```go
+package main
+
+import (
+ "log"
+
+ "github.com/gin-gonic/gin"
+)
+
+type Person struct {
+ Name string `form:"name"`
+ Address string `form:"address"`
+}
+
+func main() {
+ route := gin.Default()
+ route.Any("/testing", startPage)
+ route.Run(":8085")
+}
+
+func startPage(c *gin.Context) {
+ var person Person
+ if c.ShouldBindQuery(&person) == nil {
+ log.Println("====== Only Bind By Query String ======")
+ log.Println(person.Name)
+ log.Println(person.Address)
+ }
+ c.String(200, "Success")
+}
+```
diff --git a/content/ru/docs/examples/param-in-path.md b/content/ru/docs/examples/param-in-path.md
new file mode 100644
index 000000000..4cecad160
--- /dev/null
+++ b/content/ru/docs/examples/param-in-path.md
@@ -0,0 +1,27 @@
+---
+Заголовок: "Параметры в path"
+черновик: false
+---
+
+```go
+func main() {
+ router := gin.Default()
+
+ // This handler will match /user/john but will not match /user/ or /user
+ router.GET("/user/:name", func(c *gin.Context) {
+ name := c.Param("name")
+ c.String(http.StatusOK, "Hello %s", name)
+ })
+
+ // However, this one will match /user/john/ and also /user/john/send
+ // If no other routers match /user/john, it will redirect to /user/john/
+ router.GET("/user/:name/*action", func(c *gin.Context) {
+ name := c.Param("name")
+ action := c.Param("action")
+ message := name + " is " + action
+ c.String(http.StatusOK, message)
+ })
+
+ router.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/pure-json.md b/content/ru/docs/examples/pure-json.md
new file mode 100644
index 000000000..cf2b94346
--- /dev/null
+++ b/content/ru/docs/examples/pure-json.md
@@ -0,0 +1,30 @@
+---
+Заголовок: "PureJSON"
+черновик: false
+---
+
+Обычно JSON заменяет специальные HTML-символы их юникодными сущностями, например, `<` становится `\u003c`. Если вы хотите кодировать такие символы буквально, вы можете использовать PureJSON.
+Эта функция недоступна в Go 1.6 и ниже.
+
+```go
+func main() {
+ r := gin.Default()
+
+ // Serves unicode entities
+ r.GET("/json", func(c *gin.Context) {
+ c.JSON(200, gin.H{
+ "html": "Hello, world!",
+ })
+ })
+
+ // Serves literal characters
+ r.GET("/purejson", func(c *gin.Context) {
+ c.PureJSON(200, gin.H{
+ "html": "Hello, world!",
+ })
+ })
+
+ // listen and serve on 0.0.0.0:8080
+ r.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/query-and-post-form.md b/content/ru/docs/examples/query-and-post-form.md
new file mode 100644
index 000000000..0942d484f
--- /dev/null
+++ b/content/ru/docs/examples/query-and-post-form.md
@@ -0,0 +1,32 @@
+---
+Заголовок: "Форма для запросов и сообщений"
+draft: false
+---
+
+```sh
+POST /post?id=1234&page=1 HTTP/1.1
+Content-Type: application/x-www-form-urlencoded
+
+name=manu&message=this_is_great
+```
+
+```go
+func main() {
+ router := gin.Default()
+
+ router.POST("/post", func(c *gin.Context) {
+
+ id := c.Query("id")
+ page := c.DefaultQuery("page", "0")
+ name := c.PostForm("name")
+ message := c.PostForm("message")
+
+ fmt.Printf("id: %s; page: %s; name: %s; message: %s", id, page, name, message)
+ })
+ router.Run(":8080")
+}
+```
+
+```sh
+id: 1234; page: 1; name: manu; message: this_is_great
+```
diff --git a/content/ru/docs/examples/querystring-param.md b/content/ru/docs/examples/querystring-param.md
new file mode 100644
index 000000000..80f4920ad
--- /dev/null
+++ b/content/ru/docs/examples/querystring-param.md
@@ -0,0 +1,20 @@
+---
+Заголовок: "Параметры строки запроса"
+draft: false
+---
+
+```go
+func main() {
+ router := gin.Default()
+
+ // Query string parameters are parsed using the existing underlying request object.
+ // The request responds to a url matching: /welcome?firstname=Jane&lastname=Doe
+ router.GET("/welcome", func(c *gin.Context) {
+ firstname := c.DefaultQuery("firstname", "Guest")
+ lastname := c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname")
+
+ c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
+ })
+ router.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/redirects.md b/content/ru/docs/examples/redirects.md
new file mode 100644
index 000000000..a941d5c4d
--- /dev/null
+++ b/content/ru/docs/examples/redirects.md
@@ -0,0 +1,32 @@
+---
+Заголовок: "Перенаправления"
+черновик: false
+---
+
+Создать HTTP-перенаправление очень просто. Поддерживаются как внутренние, так и внешние расположения.
+
+```go
+r.GET("/test", func(c *gin.Context) {
+ c.Redirect(http.StatusMovedPermanently, "http://www.google.com/")
+})
+```
+
+Выдача HTTP-перенаправления из POST. См. выпуск: [#444](https://github.com/gin-gonic/gin/issues/444)
+
+```go
+r.POST("/test", func(c *gin.Context) {
+ c.Redirect(http.StatusFound, "/foo")
+})
+```
+
+Выдавая перенаправление Router, используйте `HandleContext`, как показано ниже.
+
+``` go
+r.GET("/test", func(c *gin.Context) {
+ c.Request.URL.Path = "/test2"
+ r.HandleContext(c)
+})
+r.GET("/test2", func(c *gin.Context) {
+ c.JSON(200, gin.H{"hello": "world"})
+})
+```
diff --git a/content/ru/docs/examples/rendering.md b/content/ru/docs/examples/rendering.md
new file mode 100644
index 000000000..1bb3e6844
--- /dev/null
+++ b/content/ru/docs/examples/rendering.md
@@ -0,0 +1,54 @@
+---
+Заголовок: "Рендеринг XML/JSON/YAML/ProtoBuf"
+черновик: false
+---
+
+```go
+func main() {
+ r := gin.Default()
+
+ // gin.H is a shortcut for map[string]interface{}
+ r.GET("/someJSON", func(c *gin.Context) {
+ c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
+ })
+
+ r.GET("/moreJSON", func(c *gin.Context) {
+ // You also can use a struct
+ var msg struct {
+ Name string `json:"user"`
+ Message string
+ Number int
+ }
+ msg.Name = "Lena"
+ msg.Message = "hey"
+ msg.Number = 123
+ // Note that msg.Name becomes "user" in the JSON
+ // Will output : {"user": "Lena", "Message": "hey", "Number": 123}
+ c.JSON(http.StatusOK, msg)
+ })
+
+ r.GET("/someXML", func(c *gin.Context) {
+ c.XML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
+ })
+
+ r.GET("/someYAML", func(c *gin.Context) {
+ c.YAML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
+ })
+
+ r.GET("/someProtoBuf", func(c *gin.Context) {
+ reps := []int64{int64(1), int64(2)}
+ label := "test"
+ // The specific definition of protobuf is written in the testdata/protoexample file.
+ data := &protoexample.Test{
+ Label: &label,
+ Reps: reps,
+ }
+ // Note that data becomes binary data in the response
+ // Will output protoexample.Test protobuf serialized data
+ c.ProtoBuf(http.StatusOK, data)
+ })
+
+ // Listen and serve on 0.0.0.0:8080
+ r.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/run-multiple-service.md b/content/ru/docs/examples/run-multiple-service.md
new file mode 100644
index 000000000..2c581c247
--- /dev/null
+++ b/content/ru/docs/examples/run-multiple-service.md
@@ -0,0 +1,84 @@
+---
+название: "Запустить несколько сервисов"
+черновик: false
+---
+
+Посмотрите [вопрос](https://github.com/gin-gonic/gin/issues/346) и попробуйте следующий пример:
+
+```go
+package main
+
+import (
+ "log"
+ "net/http"
+ "time"
+
+ "github.com/gin-gonic/gin"
+ "golang.org/x/sync/errgroup"
+)
+
+var (
+ g errgroup.Group
+)
+
+func router01() http.Handler {
+ e := gin.New()
+ e.Use(gin.Recovery())
+ e.GET("/", func(c *gin.Context) {
+ c.JSON(
+ http.StatusOK,
+ gin.H{
+ "code": http.StatusOK,
+ "message": "Welcome server 01",
+ },
+ )
+ })
+
+ return e
+}
+
+func router02() http.Handler {
+ e := gin.New()
+ e.Use(gin.Recovery())
+ e.GET("/", func(c *gin.Context) {
+ c.JSON(
+ http.StatusOK,
+ gin.H{
+ "code": http.StatusOK,
+ "message": "Welcome server 02",
+ },
+ )
+ })
+
+ return e
+}
+
+func main() {
+ server01 := &http.Server{
+ Addr: ":8080",
+ Handler: router01(),
+ ReadTimeout: 5 * time.Second,
+ WriteTimeout: 10 * time.Second,
+ }
+
+ server02 := &http.Server{
+ Addr: ":8081",
+ Handler: router02(),
+ ReadTimeout: 5 * time.Second,
+ WriteTimeout: 10 * time.Second,
+ }
+
+ g.Go(func() error {
+ return server01.ListenAndServe()
+ })
+
+ g.Go(func() error {
+ return server02.ListenAndServe()
+ })
+
+ if err := g.Wait(); err != nil {
+ log.Fatal(err)
+ }
+}
+```
+
diff --git a/content/ru/docs/examples/secure-json.md b/content/ru/docs/examples/secure-json.md
new file mode 100644
index 000000000..56ab23230
--- /dev/null
+++ b/content/ru/docs/examples/secure-json.md
@@ -0,0 +1,25 @@
+---
+название: "SecureJSON"
+черновик: false
+---
+
+Использование SecureJSON для предотвращения перехвата json. По умолчанию добавляет `"while(1),"` в тело ответа, если заданная структура представляет собой массив значений.
+
+```go
+func main() {
+ r := gin.Default()
+
+ // You can also use your own secure json prefix
+ // r.SecureJsonPrefix(")]}',\n")
+
+ r.GET("/someJSON", func(c *gin.Context) {
+ names := []string{"lena", "austin", "foo"}
+
+ // Will output : while(1);["lena","austin","foo"]
+ c.SecureJSON(http.StatusOK, names)
+ })
+
+ // Listen and serve on 0.0.0.0:8080
+ r.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/security-headers.md b/content/ru/docs/examples/security-headers.md
new file mode 100644
index 000000000..c6092216f
--- /dev/null
+++ b/content/ru/docs/examples/security-headers.md
@@ -0,0 +1,75 @@
+---
+название: "Заголовки безопасности"
+черновик: false
+---
+
+Важно использовать заголовки безопасности, чтобы защитить ваше веб-приложение от распространенных уязвимостей. Этот пример показывает, как добавить заголовки безопасности в ваше приложение Gin, а также как избежать атак, связанных с инъекцией заголовков хоста (SSRF, Open Redirection).
+
+```go
+package main
+
+import (
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+)
+
+func main() {
+ r := gin.Default()
+
+ expectedHost := "localhost:8080"
+
+ // Setup Security Headers
+ r.Use(func(c *gin.Context) {
+ if c.Request.Host != expectedHost {
+ c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid host header"})
+ return
+ }
+ c.Header("X-Frame-Options", "DENY")
+ c.Header("Content-Security-Policy", "default-src 'self'; connect-src *; font-src *; script-src-elem * 'unsafe-inline'; img-src * data:; style-src * 'unsafe-inline';")
+ c.Header("X-XSS-Protection", "1; mode=block")
+ c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
+ c.Header("Referrer-Policy", "strict-origin")
+ c.Header("X-Content-Type-Options", "nosniff")
+ c.Header("Permissions-Policy", "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()")
+ c.Next()
+ })
+
+ r.GET("/ping", func(c *gin.Context) {
+ c.JSON(200, gin.H{
+ "message": "pong",
+ })
+ })
+
+ r.Run() // listen and serve on 0.0.0.0:8080
+}
+```
+
+Вы можете проверить его с помощью `curl`:
+
+```bash
+// Проверка заголовок
+
+curl localhost:8080/ping -I
+
+HTTP/1.1 404 Not Found
+Content-Security-Policy: default-src 'self'; connect-src *; font-src *; script-src-elem * 'unsafe-inline'; img-src * data:; style-src * 'unsafe-inline';
+Content-Type: text/plain
+Permissions-Policy: geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()
+Referrer-Policy: strict-origin
+Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
+X-Content-Type-Options: nosniff
+X-Frame-Options: DENY
+X-Xss-Protection: 1; mode=block
+Date: Sat, 30 Mar 2024 08:20:44 GMT
+Content-Length: 18
+
+// Проверка инъекции в заголовок хоста
+
+curl localhost:8080/ping -I -H "Host:neti.ee"
+
+HTTP/1.1 400 Bad Request
+Content-Type: application/json; charset=utf-8
+Date: Sat, 30 Mar 2024 08:21:09 GMT
+Content-Length: 31
+```
\ No newline at end of file
diff --git a/content/ru/docs/examples/serving-data-from-reader.md b/content/ru/docs/examples/serving-data-from-reader.md
new file mode 100644
index 000000000..af201e164
--- /dev/null
+++ b/content/ru/docs/examples/serving-data-from-reader.md
@@ -0,0 +1,28 @@
+---
+Заголовок: "Манипуляция данных от читателя"
+draft: false
+---
+
+```go
+func main() {
+ router := gin.Default()
+ router.GET("/someDataFromReader", func(c *gin.Context) {
+ response, err := http.Get("https://raw.githubusercontent.com/gin-gonic/logo/master/color.png")
+ if err != nil || response.StatusCode != http.StatusOK {
+ c.Status(http.StatusServiceUnavailable)
+ return
+ }
+
+ reader := response.Body
+ contentLength := response.ContentLength
+ contentType := response.Header.Get("Content-Type")
+
+ extraHeaders := map[string]string{
+ "Content-Disposition": `attachment; filename="gopher.png"`,
+ }
+
+ c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
+ })
+ router.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/serving-static-files.md b/content/ru/docs/examples/serving-static-files.md
new file mode 100644
index 000000000..308edc0a9
--- /dev/null
+++ b/content/ru/docs/examples/serving-static-files.md
@@ -0,0 +1,16 @@
+---
+Заголовок: "Использование статических файлов"
+draft: false
+---
+
+```go
+func main() {
+ router := gin.Default()
+ router.Static("/assets", "./assets")
+ router.StaticFS("/more_static", http.Dir("my_file_system"))
+ router.StaticFile("/favicon.ico", "./resources/favicon.ico")
+
+ // Listen and serve on 0.0.0.0:8080
+ router.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/support-lets-encrypt.md b/content/ru/docs/examples/support-lets-encrypt.md
new file mode 100644
index 000000000..c7812db31
--- /dev/null
+++ b/content/ru/docs/examples/support-lets-encrypt.md
@@ -0,0 +1,60 @@
+---
+Заголовок: "Поддержка Let's Encrypt"
+черновик: false
+---
+
+пример для 1-строчных HTTPS-серверов LetsEncrypt.
+
+```go
+package main
+
+import (
+ "log"
+
+ "github.com/gin-gonic/autotls"
+ "github.com/gin-gonic/gin"
+)
+
+func main() {
+ r := gin.Default()
+
+ // Ping handler
+ r.GET("/ping", func(c *gin.Context) {
+ c.String(200, "pong")
+ })
+
+ log.Fatal(autotls.Run(r, "example1.com", "example2.com"))
+}
+```
+
+пример для пользовательского менеджера автосертификации.
+
+```go
+package main
+
+import (
+ "log"
+
+ "github.com/gin-gonic/autotls"
+ "github.com/gin-gonic/gin"
+ "golang.org/x/crypto/acme/autocert"
+)
+
+func main() {
+ r := gin.Default()
+
+ // Ping handler
+ r.GET("/ping", func(c *gin.Context) {
+ c.String(200, "pong")
+ })
+
+ m := autocert.Manager{
+ Prompt: autocert.AcceptTOS,
+ HostPolicy: autocert.HostWhitelist("example1.com", "example2.com"),
+ Cache: autocert.DirCache("/var/www/.cache"),
+ }
+
+ log.Fatal(autotls.RunWithManager(r, &m))
+}
+```
+
diff --git a/content/ru/docs/examples/upload-file/_index.md b/content/ru/docs/examples/upload-file/_index.md
new file mode 100644
index 000000000..442a9edb9
--- /dev/null
+++ b/content/ru/docs/examples/upload-file/_index.md
@@ -0,0 +1,6 @@
+---
+название: "Загрузить файлы"
+draft: false
+---
+
+Раздел содержит список использования api загрузки файлов.
diff --git a/content/ru/docs/examples/upload-file/multiple-file.md b/content/ru/docs/examples/upload-file/multiple-file.md
new file mode 100644
index 000000000..d3b486079
--- /dev/null
+++ b/content/ru/docs/examples/upload-file/multiple-file.md
@@ -0,0 +1,37 @@
+---
+title: "Multiple files"
+draft: false
+---
+
+Смотрите подробности [пример кода](https://github.com/gin-gonic/examples/tree/master/upload-file/multiple).
+
+```go
+func main() {
+ router := gin.Default()
+ // Set a lower memory limit for multipart forms (default is 32 MiB)
+ router.MaxMultipartMemory = 8 << 20 // 8 MiB
+ router.POST("/upload", func(c *gin.Context) {
+ // Multipart form
+ form, _ := c.MultipartForm()
+ files := form.File["upload[]"]
+
+ for _, file := range files {
+ log.Println(file.Filename)
+
+ // Upload the file to specific dst.
+ c.SaveUploadedFile(file, dst)
+ }
+ c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
+ })
+ router.Run(":8080")
+}
+```
+
+Как тестировать с помощью `curl`:
+
+```sh
+curl -X POST http://localhost:8080/upload \
+ -F "upload[]=@/Users/appleboy/test1.zip" \
+ -F "upload[]=@/Users/appleboy/test2.zip" \
+ -H "Content-Type: multipart/form-data"
+```
diff --git a/content/ru/docs/examples/upload-file/single-file.md b/content/ru/docs/examples/upload-file/single-file.md
new file mode 100644
index 000000000..7c84d6e34
--- /dev/null
+++ b/content/ru/docs/examples/upload-file/single-file.md
@@ -0,0 +1,36 @@
+---
+title: "Single file"
+draft: false
+---
+Ссылки на проблему [#774](https://github.com/gin-gonic/gin/issues/774) и деталь [пример кода](https://github.com/gin-gonic/examples/tree/master/upload-file/single).
+
+`file.Filename` **НЕ ДОЛЖНО** быть доверенным. См. [`Content-Disposition` на MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#Directives) и [#1693](https://github.com/gin-gonic/gin/issues/1693)
+
+> Имя файла всегда необязательно и не должно использоваться приложением вслепую: информация о пути должна быть удалена, и должно быть выполнено преобразование к правилам файловой системы сервера.
+
+```go
+func main() {
+ router := gin.Default()
+ // Set a lower memory limit for multipart forms (default is 32 MiB)
+ router.MaxMultipartMemory = 8 << 20 // 8 MiB
+ router.POST("/upload", func(c *gin.Context) {
+ // single file
+ file, _ := c.FormFile("file")
+ log.Println(file.Filename)
+
+ // Upload the file to specific dst.
+ c.SaveUploadedFile(file, dst)
+
+ c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
+ })
+ router.Run(":8080")
+}
+```
+
+Как тестировать с помощью `curl`:
+
+```sh
+curl -X POST http://localhost:8080/upload \
+ -F "file=@/Users/appleboy/test.zip" \
+ -H "Content-Type: multipart/form-data"
+```
diff --git a/content/ru/docs/examples/using-basicauth-middleware.md b/content/ru/docs/examples/using-basicauth-middleware.md
new file mode 100644
index 000000000..6b83d49c9
--- /dev/null
+++ b/content/ru/docs/examples/using-basicauth-middleware.md
@@ -0,0 +1,41 @@
+---
+Заголовок: "Использование промежуточного ПО BasicAuth"
+черновик: false
+---
+
+```go
+// simulate some private data
+var secrets = gin.H{
+ "foo": gin.H{"email": "foo@bar.com", "phone": "123433"},
+ "austin": gin.H{"email": "austin@example.com", "phone": "666"},
+ "lena": gin.H{"email": "lena@guapa.com", "phone": "523443"},
+}
+
+func main() {
+ r := gin.Default()
+
+ // Group using gin.BasicAuth() middleware
+ // gin.Accounts is a shortcut for map[string]string
+ authorized := r.Group("/admin", gin.BasicAuth(gin.Accounts{
+ "foo": "bar",
+ "austin": "1234",
+ "lena": "hello2",
+ "manu": "4321",
+ }))
+
+ // /admin/secrets endpoint
+ // hit "localhost:8080/admin/secrets
+ authorized.GET("/secrets", func(c *gin.Context) {
+ // get user, it was set by the BasicAuth middleware
+ user := c.MustGet(gin.AuthUserKey).(string)
+ if secret, ok := secrets[user]; ok {
+ c.JSON(http.StatusOK, gin.H{"user": user, "secret": secret})
+ } else {
+ c.JSON(http.StatusOK, gin.H{"user": user, "secret": "NO SECRET :("})
+ }
+ })
+
+ // Listen and serve on 0.0.0.0:8080
+ r.Run(":8080")
+}
+```
diff --git a/content/ru/docs/examples/using-middleware.md b/content/ru/docs/examples/using-middleware.md
new file mode 100644
index 000000000..00e1e4147
--- /dev/null
+++ b/content/ru/docs/examples/using-middleware.md
@@ -0,0 +1,43 @@
+---
+Заголовок: "Использование промежуточного ПО"
+черновик: false
+---
+
+```go
+func main() {
+ // Creates a router without any middleware by default
+ r := gin.New()
+
+ // Global middleware
+ // Logger middleware will write the logs to gin.DefaultWriter even if you set with GIN_MODE=release.
+ // By default gin.DefaultWriter = os.Stdout
+ r.Use(gin.Logger())
+
+ // Recovery middleware recovers from any panics and writes a 500 if there was one.
+ r.Use(gin.Recovery())
+
+ // Per route middleware, you can add as many as you desire.
+ r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
+
+ // Authorization group
+ // authorized := r.Group("/", AuthRequired())
+ // exactly the same as:
+ authorized := r.Group("/")
+ // per group middleware! in this case we use the custom created
+ // AuthRequired() middleware just in the "authorized" group.
+ authorized.Use(AuthRequired())
+ {
+ authorized.POST("/login", loginEndpoint)
+ authorized.POST("/submit", submitEndpoint)
+ authorized.POST("/read", readEndpoint)
+
+ // nested group
+ testing := authorized.Group("testing")
+ testing.GET("/analytics", analyticsEndpoint)
+ }
+
+ // Listen and serve on 0.0.0.0:8080
+ r.Run(":8080")
+}
+```
+
diff --git a/content/ru/docs/examples/without-middleware.md b/content/ru/docs/examples/without-middleware.md
new file mode 100644
index 000000000..e4884ecaa
--- /dev/null
+++ b/content/ru/docs/examples/without-middleware.md
@@ -0,0 +1,17 @@
+---
+Заголовок: "Без промежуточного ПО по умолчанию"
+draft: false
+---
+
+Используйте
+
+```go
+r := gin.New()
+```
+
+место
+
+```go
+// Default With the Logger and Recovery middleware already attached
+r := gin.Default()
+```
diff --git a/content/ru/docs/examples/write-log.md b/content/ru/docs/examples/write-log.md
new file mode 100644
index 000000000..c42f21c75
--- /dev/null
+++ b/content/ru/docs/examples/write-log.md
@@ -0,0 +1,25 @@
+---
+Заголовок: "Как записать файл журнала"
+draft: false
+---
+
+```go
+func main() {
+ // Disable Console Color, you don't need console color when writing the logs to file.
+ gin.DisableConsoleColor()
+
+ // Logging to a file.
+ f, _ := os.Create("gin.log")
+ gin.DefaultWriter = io.MultiWriter(f)
+
+ // Use the following code if you need to write the logs to file and console at the same time.
+ // gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
+
+ router := gin.Default()
+ router.GET("/ping", func(c *gin.Context) {
+ c.String(200, "pong")
+ })
+
+ router.Run(":8080")
+}
+```
diff --git a/content/ru/docs/faq/_index.md b/content/ru/docs/faq/_index.md
new file mode 100644
index 000000000..1e0345a1a
--- /dev/null
+++ b/content/ru/docs/faq/_index.md
@@ -0,0 +1,8 @@
+---
+Заголовок: "FAQ"
+черновик: false
+вес: 9
+---
+
+TODO: записать некоторые часто задаваемые вопросы из вкладки GitHub Issue.
+
diff --git a/content/ru/docs/features/_index.md b/content/ru/docs/features/_index.md
new file mode 100644
index 000000000..08607d579
--- /dev/null
+++ b/content/ru/docs/features/_index.md
@@ -0,0 +1,17 @@
+---
+Заголовок: "Особенности"
+черновик: false
+вес: 4
+---
+
+## Стабильные возможности Gin v1:
+
+- Маршрутизатор с нулевым распределением.
+
+- По-прежнему самый быстрый http-маршрутизатор и фреймворк. От маршрутизации до написания.
+
+- Полный набор модульных тестов.
+
+- Проверено в бою.
+
+- API заморожен, новые релизы не сломают ваш код.
diff --git a/content/ru/docs/introduction/_index.md b/content/ru/docs/introduction/_index.md
new file mode 100644
index 000000000..1e93bee72
--- /dev/null
+++ b/content/ru/docs/introduction/_index.md
@@ -0,0 +1,49 @@
+---
+Заголовок: "Введение"
+черновик: false
+вес: 1
+---
+
+Gin - это веб-фреймворк, написанный на языке Go (Golang). В нем реализован мартини-подобный API с гораздо лучшей производительностью, до 40 раз быстрее благодаря [httprouter](https://github.com/julienschmidt/httprouter). Если вам нужна производительность и хорошая продуктивность, вам понравится Gin.
+
+В этом разделе мы расскажем о том, что такое Gin, какие проблемы он решает и как он может помочь вашему проекту.
+
+Если же вы уже готовы использовать Gin в своем проекте, посетите [Quickstart](https://gin-gonic.com/docs/quickstart/).
+
+## Особенности
+
+### Быстрый
+
+Маршрутизация на основе радиксного дерева, малый объем памяти. Никаких отражений. Предсказуемая производительность API.
+
+### Поддержка промежуточного ПО
+
+Входящий HTTP-запрос может быть обработан цепочкой промежуточных программ и завершен конечным действием.
+Например: Логгер, Авторизация, GZIP и, наконец, публикация сообщения в БД.
+
+### Защита от сбоев
+
+Gin может поймать панику, возникшую во время HTTP-запроса, и восстановить ее. Таким образом, ваш сервер будет всегда доступен. В качестве примера - можно также сообщить об этой панике в Sentry!
+
+Переведено с помощью DeepL.com (бесплатная версия)
+
+### Проверка JSON
+
+Gin может анализировать и проверять JSON-запрос - например, проверять наличие необходимых значений.
+
+### Группировка маршрутов
+
+Организуйте свои маршруты лучше. Требуемая и необязательная авторизация, разные версии API... Кроме того, группы могут быть неограниченно вложены друг в друга без снижения производительности.
+
+### Управление ошибками
+
+Gin предоставляет удобный способ сбора всех ошибок, возникших во время HTTP-запроса. В конечном итоге промежуточное ПО может записывать их в лог-файл, в базу данных или отправлять по сети.
+
+### Рендеринг встроенный
+
+Gin предоставляет простой в использовании API для рендеринга JSON, XML и HTML.
+
+### Расширяемость
+
+Создать новое промежуточное ПО очень просто, просто посмотрите примеры кодов.
+
diff --git a/content/ru/docs/jsoniter/_index.md b/content/ru/docs/jsoniter/_index.md
new file mode 100644
index 000000000..0d88e1de7
--- /dev/null
+++ b/content/ru/docs/jsoniter/_index.md
@@ -0,0 +1,13 @@
+---
+название: "Jsoniter"
+черновик: false
+вес: 5
+---
+
+## Сборка с [jsoniter](https://github.com/json-iterator/go)
+
+Gin использует `encoding/json` как пакет json по умолчанию, но вы можете изменить его на [jsoniter](https://github.com/json-iterator/go), собирая из других тегов.
+
+``sh
+$ go build -tags=jsoniter .
+```
diff --git a/content/ru/docs/quickstart/_index.md b/content/ru/docs/quickstart/_index.md
new file mode 100644
index 000000000..080171f06
--- /dev/null
+++ b/content/ru/docs/quickstart/_index.md
@@ -0,0 +1,87 @@
+---
+название: "Быстрый старт"
+черновик: false
+вес: 2
+---
+
+В этом кратком руководстве мы извлечем уроки из сегментов кода и узнаем, как:
+
+## Требования
+
+- Go 1.16 или выше
+
+## Установка
+
+Чтобы установить пакет Gin, необходимо сначала установить Go и настроить рабочее пространство Go.
+
+1. Скачайте и установите его:
+
+```sh
+$ go get -u github.com/gin-gonic/gin
+```
+
+2. Импортируйте его в свой код:
+
+```go
+import "github.com/gin-gonic/gin"
+```
+
+3. (Необязательно) Импортируйте `net/http`. Это необходимо, например, при использовании таких констант, как `http.StatusOK`.
+
+```go
+import "net/http"
+```
+
+1. Создайте папку проекта и `cd` в ней
+
+```sh
+$ mkdir -p $GOPATH/src/github.com/myusername/project && cd "$_"
+```
+
+2. Скопируйте начальный шаблон в свой проект
+
+```sh
+$ curl https://raw.githubusercontent.com/gin-gonic/examples/master/basic/main.go > main.go
+```
+
+3. Запустите свой проект
+
+```sh
+$ go run main.go
+```
+
+## Начало работы
+
+> Не знаете, как написать и выполнить код Go? [Нажмите здесь](https://golang.org/doc/code.html).
+
+Сначала создайте файл с именем `example.go`:
+
+```sh
+# assume the following codes in example.go file
+$ touch example.go
+```
+
+Затем поместите следующий код в файл `example.go`:
+
+```go
+package main
+
+import "github.com/gin-gonic/gin"
+
+func main() {
+ r := gin.Default()
+ r.GET("/ping", func(c *gin.Context) {
+ c.JSON(200, gin.H{
+ "message": "pong",
+ })
+ })
+ r.Run() // listen and serve on 0.0.0.0:8080
+}
+```
+
+И вы можете запустить код с помощью `go run example.go`:
+
+```sh
+# run example.go and visit 0.0.0.0:8080/ping on browser
+$ go run example.go
+```
diff --git a/content/ru/docs/testing/_index.md b/content/ru/docs/testing/_index.md
new file mode 100644
index 000000000..f175db7e2
--- /dev/null
+++ b/content/ru/docs/testing/_index.md
@@ -0,0 +1,89 @@
+---
+название: "Тестирование"
+черновик: false
+вес: 7
+---
+
+## Как написать тестовый пример для Gin?
+
+Пакет `net/http/httptest` является предпочтительным способом для тестирования HTTP.
+
+```go
+package main
+
+import "github.com/gin-gonic/gin"
+
+type User struct {
+ Username string `json:"username"`
+ Gender string `json:"gender"`
+}
+
+func setupRouter() *gin.Engine {
+ r := gin.Default()
+ r.GET("/ping", func(c *gin.Context) {
+ c.String(200, "pong")
+ })
+ return r
+}
+
+func postUser(r *gin.Engine) *gin.Engine {
+ r.POST("/user/add", func(c *gin.Context) {
+ var user User
+ c.BindJSON(&user)
+ c.JSON(200, user)
+ })
+ return r
+}
+
+func main() {
+ r := setupRouter()
+ r = postUser(r)
+ r.Run(":8080")
+}
+```
+
+Тест для примера кода, приведенного выше:
+
+```go
+package main
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestPingRoute(t *testing.T) {
+ router := setupRouter()
+
+ w := httptest.NewRecorder()
+ req, _ := http.NewRequest("GET", "/ping", nil)
+ router.ServeHTTP(w, req)
+
+ assert.Equal(t, 200, w.Code)
+ assert.Equal(t, "pong", w.Body.String())
+}
+
+// Test for POST /user/add
+func TestPostUser(t *testing.T) {
+ router := setupRouter()
+ router = postUser(router)
+
+ w := httptest.NewRecorder()
+
+ // Create an example user for testing
+ exampleUser := User{
+ Username: "test_name",
+ Gender: "male",
+ }
+ userJson, _ := json.Marshal(exampleUser)
+ req, _ := http.NewRequest("POST", "/user/add", strings.NewReader(string(userJson)))
+ router.ServeHTTP(w, req)
+
+ assert.Equal(t, 200, w.Code)
+ // Compare the response body with the json data of exampleUser
+ assert.Equal(t, string(userJson), w.Body.String())
+}
+```
diff --git a/content/ru/docs/users/_index.md b/content/ru/docs/users/_index.md
new file mode 100644
index 000000000..c3c973b91
--- /dev/null
+++ b/content/ru/docs/users/_index.md
@@ -0,0 +1,21 @@
+---
+title: "Users"
+draft: false
+weight: 8
+---
+
+##### Awesome project lists using [Gin](https://github.com/gin-gonic/gin) web framework:
+
+* [gorush](https://github.com/appleboy/gorush): A push notification server written in Go.
+
+* [fnproject](https://github.com/fnproject/fn): The container native, cloud agnostic serverless platform.
+
+* [photoprism](https://github.com/photoprism/photoprism): Personal photo management powered by Go and Google TensorFlow.
+
+* [krakend](https://github.com/devopsfaith/krakend): Ultra performant API Gateway with middlewares.
+
+* [picfit](https://github.com/thoas/picfit): An image resizing server written in Go.
+
+* [gotify](https://github.com/gotify/server): A simple server for sending and receiving messages in real-time per web socket.
+
+* [cds](https://github.com/ovh/cds): Enterprise-Grade Continuous Delivery & DevOps Automation Open Source Platform.
diff --git a/content/ru/featured-background.jpg b/content/ru/featured-background.jpg
new file mode 100644
index 000000000..8bb8a4cc6
Binary files /dev/null and b/content/ru/featured-background.jpg differ
diff --git a/content/ru/search.md b/content/ru/search.md
new file mode 100644
index 000000000..ec487e522
--- /dev/null
+++ b/content/ru/search.md
@@ -0,0 +1,5 @@
+---
+title: Результаты поиска
+layout: поиск
+---
+