<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Gerasimos Maropoulos on Medium]]></title>
        <description><![CDATA[Stories by Gerasimos Maropoulos on Medium]]></description>
        <link>https://medium.com/@kataras?source=rss-15bee39f2b28------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*rgCiwAJdlTl6XQzqlZsRdQ.jpeg</url>
            <title>Stories by Gerasimos Maropoulos on Medium</title>
            <link>https://medium.com/@kataras?source=rss-15bee39f2b28------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 04 Nov 2026 20:32:06 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@kataras/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[HTTP Method Override for Go]]></title>
            <link>https://medium.com/@kataras/http-method-override-for-go-708ca9bd1a33?source=rss-15bee39f2b28------2</link>
            <guid isPermaLink="false">https://medium.com/p/708ca9bd1a33</guid>
            <category><![CDATA[go]]></category>
            <category><![CDATA[methodoverride]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Gerasimos Maropoulos]]></dc:creator>
            <pubDate>Fri, 08 Nov 2024 11:15:03 GMT</pubDate>
            <atom:updated>2024-11-08T11:18:02.295Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2et05kGnMWhvYd9jaKMwBQ.jpeg" /></figure><h3>Introduction</h3><p>HTTP method override is a technique used to support clients that do not support certain HTTP methods such as PUT or DELETE. This is particularly useful for web browsers and older clients that only support GET and POST methods. The Iris web framework provides a robust and flexible method override middleware that allows developers to easily implement HTTP method overriding in their applications. This guide will walk you through the features and usage of the Iris method override middleware, helping you to understand and leverage its capabilities to enhance your web applications.</p><h3>Features of Iris Method Override Middleware</h3><p>The Iris method override middleware offers a variety of features to handle HTTP method overriding efficiently. These features include:</p><ol><li><strong>Customizable Methods</strong>: Define which HTTP methods can be overridden.</li><li><strong>Custom Headers</strong>: Specify custom headers to determine the method override.</li><li><strong>Form Field Support</strong>: Use form fields to specify the method override.</li><li><strong>Query Parameter Support</strong>: Use query parameters to specify the method override.</li><li><strong>Save Original Method</strong>: Optionally save the original HTTP method for later use.</li></ol><h3>Installation</h3><p>To use the Iris method override middleware, you need to import it in your Iris application:</p><pre>import &quot;github.com/kataras/iris/v12/middleware/methodoverride&quot;</pre><h3>Usage</h3><h3>Basic Setup</h3><p>To use the method override middleware, you need to import the necessary packages and configure the middleware in your Iris application. Here is a basic example:</p><pre>package main<br><br>import (<br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/methodoverride&quot;<br>)<br><br>func main() {<br> app := iris.New()<br><br> // Create the method override middleware<br> mo := methodoverride.New(<br>  methodoverride.SaveOriginalMethod(&quot;_originalMethod&quot;),<br> )<br><br> // Register the middleware with UseRouter<br> app.UseRouter(mo)<br><br> app.Post(&quot;/path&quot;, func(ctx iris.Context) {<br>  ctx.WriteString(&quot;POST response&quot;)<br> })<br><br> app.Delete(&quot;/path&quot;, func(ctx iris.Context) {<br>  ctx.WriteString(&quot;DELETE response&quot;)<br> })<br><br> app.Listen(&quot;:8080&quot;)<br>}</pre><h3>Customizable Methods</h3><p>You can define which HTTP methods can be overridden using the Methods option. By default, only the POST method can be overridden. Here is an example:</p><pre>mo := methodoverride.New(<br>    methodoverride.Methods(&quot;POST&quot;, &quot;PUT&quot;),<br>)</pre><h3>Custom Headers</h3><p>You can specify custom headers to determine the method override using the Headersoption. By default, the middleware checks the following headers: X-HTTP-Method, X-HTTP-Method-Override, and X-Method-Override. Here is an example:</p><pre>mo := methodoverride.New(<br>    methodoverride.Headers(&quot;X-Custom-Method&quot;),<br>)</pre><h3>Form Field Support</h3><p>You can use form fields to specify the method override using the FormFieldoption. By default, the middleware checks the _method form field. Here is an example:</p><pre>mo := methodoverride.New(<br>    methodoverride.FormField(&quot;_method&quot;),<br>)</pre><h3>Query Parameter Support</h3><p>You can use query parameters to specify the method override using the Queryoption. By default, the middleware checks the _method query parameter. Here is an example:</p><pre>mo := methodoverride.New(<br>    methodoverride.Query(&quot;_method&quot;),<br>)</pre><h3>Save Original Method</h3><p>You can optionally save the original HTTP method for later use using the SaveOriginalMethod option. Here is an example:</p><pre>mo := methodoverride.New(<br>    methodoverride.SaveOriginalMethod(&quot;_originalMethod&quot;),<br>)</pre><h3>Example</h3><p>Here is a complete example demonstrating how to use the method override middleware with an Iris application:</p><pre>package main<br><br>import (<br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/methodoverride&quot;<br>)<br><br>func main() {<br> app := iris.New()<br><br> // Create the method override middleware<br> mo := methodoverride.New(<br>  methodoverride.SaveOriginalMethod(&quot;_originalMethod&quot;),<br> )<br><br> // Register the middleware with UseRouter<br> app.UseRouter(mo)<br><br> app.Post(&quot;/path&quot;, func(ctx iris.Context) {<br>  ctx.WriteString(&quot;POST response&quot;)<br> })<br><br> app.Delete(&quot;/path&quot;, func(ctx iris.Context) {<br>  ctx.WriteString(&quot;DELETE response&quot;)<br> })<br><br> app.Listen(&quot;:8080&quot;)<br>}</pre><h3>Conclusion</h3><p>The Iris method override middleware provides a simple and efficient way to support clients that do not support certain HTTP methods. By leveraging the features of this middleware, you can enhance the compatibility and flexibility of your web applications.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=708ca9bd1a33" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Request Body Limit Middleware for Iris]]></title>
            <link>https://medium.com/@kataras/request-body-limit-middleware-for-iris-2b132364e0e3?source=rss-15bee39f2b28------2</link>
            <guid isPermaLink="false">https://medium.com/p/2b132364e0e3</guid>
            <category><![CDATA[go]]></category>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Gerasimos Maropoulos]]></dc:creator>
            <pubDate>Fri, 01 Nov 2024 16:20:29 GMT</pubDate>
            <atom:updated>2024-11-01T16:20:29.471Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/560/1*fXSuw7x7oL9oY9ER0ITKAA.png" /></figure><h3>Overview</h3><p>The <a href="https://www.iris-go.com">Iris</a> Body Limit middleware is a powerful tool for controlling the size of incoming request bodies in your Iris web applications. By setting a limit on the size of request bodies, you can prevent clients from sending excessively large payloads that could potentially overwhelm your server or lead to denial-of-service (DoS) attacks. This middleware is particularly useful for applications that handle file uploads, JSON payloads, or any other type of data that could vary significantly in size.</p><h3>Why Use Body Limit Middleware?</h3><h3>Security</h3><p>One of the primary reasons to use body limit middleware is to enhance the security of your application. By limiting the size of incoming request bodies, you can mitigate the risk of DoS attacks, where an attacker sends large payloads to exhaust server resources.</p><h3>Performance</h3><p>Limiting the size of request bodies can also improve the performance of your application. Large payloads can consume significant amounts of memory and processing power, slowing down your server and affecting the user experience. By setting a reasonable limit, you can ensure that your server remains responsive and efficient.</p><h3>Resource Management</h3><p>In applications that handle file uploads or large JSON payloads, it’s essential to manage resources effectively. By setting a body limit, you can prevent clients from uploading excessively large files or sending huge JSON objects that could strain your server’s resources.</p><h3>Installation</h3><p>To use the bodylimit middleware, you need to import it in your Iris application:</p><pre>import &quot;github.com/kataras/iris/v12/middleware/bodylimit&quot;</pre><h3>Usage</h3><h3>Basic Setup</h3><p>To use the body limit middleware, you need to create an Iris application and register the middleware. Below is an example of how to set up the middleware with a limit of 2 MB:</p><pre>package main<br><br>import (<br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/bodylimit&quot;<br>)<br><br>func main() {<br> app := iris.New()<br> app.Use(bodylimit.New(2 * iris.MB)) // set the limit to 2 MB.<br><br> handler := func(ctx iris.Context) {<br>  body, err := ctx.Body()<br>  if err != nil {<br>   ctx.StopWithPlainError(iris.StatusInternalServerError, err)<br>   return<br>  }<br><br>  ctx.Write(body) // write the request body back to the client.<br> }<br><br> app.Post(&quot;/&quot;, handler)<br> app.Listen(&quot;:8080&quot;)<br>}</pre><h3>Explanation</h3><ul><li>Limit: The bodylimit.New function takes a single parameter, which is the maximum size of the request body in bytes. In the example above, the limit is set to 10 bytes.</li><li>Handler: The handler reads the request body and writes it back to the response. If the request body exceeds the limit, the middleware will stop the request and return a 413 Request Entity Too Large status.</li><li>The body limit middleware uses a sync.Pool to manage Reader instances, which are used to read the request body and enforce the size limit. This approach ensures efficient memory usage and reduces the overhead of creating new Reader instances for each request.</li></ul><h3>Testing Handlers with BodyLimit Middleware</h3><p>To test handlers that use the BodyLimit middleware, you can use the httptest package provided by Iris. Here is an example of how to test a handler:</p><pre>package main_test<br><br>import (<br> &quot;testing&quot;<br><br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/httptest&quot;<br> &quot;github.com/kataras/iris/v12/middleware/bodylimit&quot;<br>)<br><br>func TestBodyLimit(t *testing.T) {<br> limit := int64(10) // set the limit to 10 bytes for the shake of the test.<br><br> handler := func(ctx iris.Context) {<br>  body, err := ctx.Body()<br>  if err != nil {<br>   ctx.StopWithPlainError(iris.StatusInternalServerError, err)<br>   return<br>  }<br>  ctx.Write(body)<br> }<br><br> app := iris.New()<br> app.Use(bodylimit.New(limit))<br> app.Post(&quot;/&quot;, handler)<br><br> e := httptest.New(t, app)<br><br> // Test with a body that is smaller than the limit.<br> e.POST(&quot;/&quot;).WithText(&quot;123456789&quot;).Expect().Status(iris.StatusOK).Body().IsEqual(&quot;123456789&quot;)<br><br> // Test with a body that is equal to the limit.<br> e.POST(&quot;/&quot;).WithText(&quot;1234567890&quot;).Expect().Status(iris.StatusOK).Body().IsEqual(&quot;1234567890&quot;)<br><br> // Test with a body that is bigger than the limit.<br> e.POST(&quot;/&quot;).WithText(&quot;12345678910&quot;).Expect().Status(iris.StatusRequestEntityTooLarge)<br>}</pre><h3>Conclusion</h3><p>The Iris Body Limit middleware provides a simple yet effective way to control the size of incoming request bodies in your Iris web applications. By setting a limit on the size of request bodies, you can enhance the security, performance, and resource management of your application. With easy integration and advanced features, this middleware is a valuable tool for any Iris developer.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2b132364e0e3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Basic Authentication Middleware for Iris]]></title>
            <link>https://medium.com/@kataras/basic-authentication-middleware-for-iris-52eb80042e98?source=rss-15bee39f2b28------2</link>
            <guid isPermaLink="false">https://medium.com/p/52eb80042e98</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[go]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[authentication]]></category>
            <dc:creator><![CDATA[Gerasimos Maropoulos]]></dc:creator>
            <pubDate>Thu, 31 Oct 2024 10:17:46 GMT</pubDate>
            <atom:updated>2024-10-31T10:23:30.717Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uAtxFhJLQ4yweSR5qzIiSg.jpeg" /></figure><h3>Overview</h3><p>The Basic Authentication middleware provides a robust and flexible way to secure your <a href="https://www.iris-go.com">Iris</a> web applications. It supports various user storage methods, including in-memory lists, files, and databases, and offers advanced features such as password encryption, custom error handling, and session expiration.</p><h3>Installation</h3><p>To use the basicauth middleware, you need to import it in your Iris application:</p><pre>import &quot;github.com/kataras/iris/v12/middleware/basicauth&quot;</pre><h3>Features</h3><h3>Authentication Function</h3><p>The core of the middleware is the Allow field, which is a function with the following signature:</p><pre>func(ctx iris.Context, username, password string) (any, bool)</pre><p>This function is responsible for validating the username and password. It returns a user object (or any other type) and a boolean indicating whether the authentication was successful.</p><h3>User Structure (Helper)</h3><p>While the middleware does not require a specific user structure, you can use a helper structure to manage user data more conveniently. Here is an example of a user structure:</p><pre>type User struct {<br>	Username string   `json:&quot;username&quot;`<br>	Password string   `json:&quot;password&quot;`<br>	Roles    []string `json:&quot;roles&quot;`<br>}</pre><h3>In-Memory User Storage</h3><p>You can store users in memory using a slice of user structures. This is useful for small applications or testing purposes.</p><pre>var users = []User{<br>	{&quot;admin&quot;, &quot;admin&quot;, []string{&quot;admin&quot;}},<br>	{&quot;kataras&quot;, &quot;kataras_pass&quot;, []string{&quot;manager&quot;, &quot;author&quot;}},<br>	{&quot;george&quot;, &quot;george_pass&quot;, []string{&quot;member&quot;}},<br>	{&quot;john&quot;, &quot;john_pass&quot;, []string{}},<br>}</pre><h3>Basic Setup</h3><p>To set up the middleware, create an instance of basicauth.Options and pass it to basicauth.New.</p><pre>opts := basicauth.Options{<br>	Realm: basicauth.DefaultRealm,<br>	MaxAge: 10 * time.Minute,<br>	GC: basicauth.GC{<br>		Every: 2 * time.Hour,<br>	},<br>	Allow: basicauth.AllowUsers(users),<br>}</pre><pre>auth := basicauth.New(opts)</pre><h3>Using a File for User Storage</h3><p>You can load users from a file (JSON or YAML). This is useful for applications where user data changes frequently.</p><pre>auth := basicauth.Load(&quot;users.yml&quot;)</pre><h3>BCRYPT Option</h3><p>The BCRYPT option allows you to use bcrypt for password hashing. Bcrypt is a password hashing function designed to be computationally intensive to resist brute-force attacks. It is widely used for securely storing passwords.</p><pre>auth := basicauth.Load(&quot;users.yml&quot;, basicauth.BCRYPT)</pre><p>You can also use the BCRYPT option with other user fetching methods, such as in-memory or database storage.</p><h3>Using a Database for User Storage</h3><p>For more dynamic user management, you can validate users against a database. Here is an example of how to set up the middleware using a MySQL database:</p><pre>package main<br><br>import (<br> &quot;context&quot;<br> &quot;database/sql&quot;<br> &quot;fmt&quot;<br> &quot;os&quot;<br><br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/basicauth&quot;<br><br> _ &quot;github.com/go-sql-driver/mysql&quot;<br>)<br><br>type User struct {<br> ID       int64  `db:&quot;id&quot; json:&quot;id&quot;`<br> Username string `db:&quot;username&quot; json:&quot;username&quot;`<br> Password string `db:&quot;password&quot; json:&quot;password&quot;`<br> Email    string `db:&quot;email&quot; json:&quot;email&quot;`<br>}<br><br>func (u User) GetUsername() string {<br> return u.Username<br>}<br><br>func (u User) GetPassword() string {<br> return u.Password<br>}<br><br>func main() {<br> dsn := fmt.Sprintf(&quot;%s:%s@tcp(%s:3306)/%s?parseTime=true&amp;charset=utf8mb4&amp;collation=utf8mb4_unicode_ci&quot;,<br>  getenv(&quot;MYSQL_USER&quot;, &quot;user_myapp&quot;),<br>  getenv(&quot;MYSQL_PASSWORD&quot;, &quot;dbpassword&quot;),<br><br> get<br><br>env(&quot;MYSQL_HOST&quot;, &quot;localhost&quot;),<br>  getenv(&quot;MYSQL_DATABASE&quot;, &quot;myapp&quot;),<br> )<br> db, err := connect(dsn)<br> if err != nil {<br>  panic(err)<br> }<br><br> // Validate a user from database.<br> allowFunc := func(ctx iris.Context, username, password string) (any, bool) {<br>  user, err := db.getUserByUsernameAndPassword(context.Background(), username, password)<br>  return user, err == nil<br> }<br><br> opts := basicauth.Options{<br>  Realm:        basicauth.DefaultRealm,<br>  ErrorHandler: basicauth.DefaultErrorHandler,<br>  Allow:        allowFunc,<br> }<br><br> auth := basicauth.New(opts)<br><br> app := iris.New()<br> app.Use(auth)<br> app.Get(&quot;/&quot;, index)<br> app.Listen(&quot;:8080&quot;)<br>}<br><br>func index(ctx iris.Context) {<br> user, _ := ctx.User().GetRaw()<br> // user is a type of main.User<br> ctx.JSON(user)<br>}</pre><h3>Custom Error Handling</h3><p>You can customize the error handling behavior by setting the ErrorHandler field in the basicauth.Options.</p><pre>opts := basicauth.Options{<br>	ErrorHandler: func(ctx iris.Context, err error) {<br>		ctx.StatusCode(iris.StatusUnauthorized)<br>		ctx.JSON(iris.Map{&quot;error&quot;: &quot;Unauthorized&quot;})<br>	},<br>}</pre><h3>Session Expiration</h3><p>The middleware supports session expiration. You can set the MaxAge field to specify the duration after which the user must re-authenticate.</p><pre>opts := basicauth.Options{<br>	MaxAge: 10 * time.Minute,<br>}</pre><h3>Garbage Collection</h3><p>To clear expired users from memory, you can set the GC field.</p><pre>opts := basicauth.Options{<br>	GC: basicauth.GC{<br>		Every: 2 * time.Hour,<br>	},<br>}</pre><h3>Testing Handlers with BasicAuth Middleware</h3><p>To test handlers that use the BasicAuth middleware, you can use the</p><p>httptest</p><p>package provided by Iris. Here is an example of how to test a handler:</p><pre>package main_test<br><br>import (<br> &quot;testing&quot;<br><br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/httptest&quot;<br> &quot;github.com/kataras/iris/v12/middleware/basicauth&quot;<br>)<br><br>func TestIndexHandler(t *testing.T) {<br> opts := basicauth.Options{<br>  Realm: basicauth.DefaultRealm,<br>  Allow: basicauth.AllowUsers(users),<br> }<br><br> auth := basicauth.New(opts)<br><br> app := iris.New()<br> app.Use(auth)<br> app.Get(&quot;/&quot;, index)<br><br> e := httptest.New(t, app)<br><br> // Test with valid credentials<br> e.GET(&quot;/&quot;).WithBasicAuth(&quot;admin&quot;, &quot;admin&quot;).Expect().Status(httptest.StatusOK).JSON().Object().Value(&quot;username&quot;).Equal(&quot;admin&quot;)<br><br> // Test with invalid credentials<br> e.GET(&quot;/&quot;).WithBasicAuth(&quot;admin&quot;, &quot;wrongpassword&quot;).Expect().Status(httptest.StatusUnauthorized)<br>}</pre><h3>Example</h3><p>Here is a complete example that demonstrates how to set up the middleware with in-memory user storage:</p><pre>package main<br><br>import (<br> &quot;time&quot;<br><br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/basicauth&quot;<br>)<br><br>type User struct {<br> Username string   `json:&quot;username&quot;`<br> Password string   `json:&quot;password&quot;`<br> Roles    []string `json:&quot;roles&quot;`<br>}<br><br>var users = []User{<br> {&quot;admin&quot;, &quot;admin&quot;, []string{&quot;admin&quot;}},<br> {&quot;kataras&quot;, &quot;kataras_pass&quot;, []string{&quot;manager&quot;, &quot;author&quot;}},<br> {&quot;george&quot;, &quot;george_pass&quot;, []string{&quot;member&quot;}},<br> {&quot;john&quot;, &quot;john_pass&quot;, []string{}},<br>}<br><br>func main() {<br> opts := basicauth.Options{<br>  Realm: basicauth.DefaultRealm,<br>  MaxAge: 10 * time.Minute,<br>  GC: basicauth.GC{<br>   Every: 2 * time.Hour,<br>  },<br>  Allow: basicauth.AllowUsers(users),<br> }<br><br> auth := basicauth.New(opts)<br><br> app := iris.New()<br> app.Use(auth)<br> app.Get(&quot;/&quot;, index)<br> app.Listen(&quot;:8080&quot;)<br>}<br><br>func index(ctx iris.Context) {<br> user, _ := ctx.User().GetRaw()<br> ctx.JSON(user)<br>}</pre><h3>Conclusion</h3><p>The <a href="https://github.com/kataras/iris/tree/main/_examples/auth/basicauth">Basic Authentication middleware</a> provides a comprehensive solution for securing your Iris web applications. With support for various user storage methods, advanced features like password encryption and custom error handling, and easy integration, it is a powerful tool for developers.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=52eb80042e98" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Request Rate Limiting Middleware for Iris]]></title>
            <link>https://medium.com/@kataras/request-rate-limiting-middleware-for-iris-dc5746df7bfe?source=rss-15bee39f2b28------2</link>
            <guid isPermaLink="false">https://medium.com/p/dc5746df7bfe</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[go-programming-language]]></category>
            <dc:creator><![CDATA[Gerasimos Maropoulos]]></dc:creator>
            <pubDate>Wed, 30 Oct 2024 20:54:59 GMT</pubDate>
            <atom:updated>2024-10-30T20:54:59.703Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QefM1bzZRODpMEzhP-l3Tg.jpeg" /></figure><h3>Overview</h3><p>The rate middleware provides rate limiting capabilities for the <a href="https://www.iris-go.com">Iris</a> web framework. It allows developers to control the rate of requests to their applications, ensuring fair usage and preventing abuse. The middleware is based on the token bucket algorithm, which is a popular method for rate limiting.</p><h3>Installation</h3><p>To use the rate middleware, you need to import it in your Iris application:</p><pre>import &quot;github.com/kataras/iris/v12/middleware/rate&quot;</pre><h3>Usage</h3><h3>Basic Setup</h3><p>To use the rate limiter, you need to create an Iris application and register the middleware. Below is an example of how to set up the rate limiter:</p><pre>package main<br><br>import (<br> &quot;time&quot;<br><br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/rate&quot;<br>)<br><br>func main() {<br> app := iris.New()<br> app.Logger().SetLevel(&quot;debug&quot;)<br><br> limit := rate.Limit(1, 5, rate.PurgeEvery(time.Minute, 5*time.Minute))<br> app.Use(limit)<br><br> app.Get(&quot;/&quot;, index)<br> app.Get(&quot;/other&quot;, other)<br><br> app.Listen(&quot;:8080&quot;)<br>}<br><br>func index(ctx iris.Context) {<br> ctx.HTML(&quot;&lt;h1&gt;Index Page&lt;/h1&gt;&quot;)<br>}<br><br>func other(ctx iris.Context) {<br> ctx.HTML(&quot;&lt;h1&gt;Other Page&lt;/h1&gt;&quot;)<br>}</pre><p>This example allows 1 request per second with a maximum burst size of 5. It also purges old entries every minute if they haven’t been seen for 5 minutes.</p><h3>Using rate.Every Helper</h3><p>This example demonstrates how to use the rate.Every helper to set up a rate limiter:</p><pre>package main<br><br>import (<br> &quot;time&quot;<br><br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/rate&quot;<br>)<br><br>func main() {<br> app := iris.New()<br> app.Logger().SetLevel(&quot;debug&quot;)<br><br> // Use rate.Every helper to set up the rate limiter.<br> limit := rate.Limit(rate.Every(time.Minute), 5)<br> app.Use(limit)<br><br> app.Get(&quot;/&quot;, index)<br> app.Get(&quot;/other&quot;, other)<br><br> app.Listen(&quot;:8080&quot;)<br>}<br><br>func index(ctx iris.Context) {<br> ctx.HTML(&quot;&lt;h1&gt;Index Page&lt;/h1&gt;&quot;)<br>}<br><br>func other(ctx iris.Context) {<br> ctx.HTML(&quot;&lt;h1&gt;Other Page&lt;/h1&gt;&quot;)<br>}</pre><h3>Using API Key for Rate Limiting</h3><p>This example demonstrates how to set up a rate limiter that uses an API key instead of the client’s remote IP address:</p><pre>package main<br><br>import (<br> &quot;time&quot;<br><br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/rate&quot;<br>)<br><br>func main() {<br> app := iris.New()<br> app.Logger().SetLevel(&quot;debug&quot;)<br><br> // Use API key for rate limiting.<br> app.Use(useAPIKey)<br><br> limit := rate.Limit(rate.Every(time.Minute), 300, rate.PurgeEvery(5*time.Minute, 15*time.Minute))<br> app.Use(limit)<br><br> app.Get(&quot;/list&quot;, list)<br><br> app.Listen(&quot;:8080&quot;)<br>}<br><br>func useAPIKey(ctx iris.Context) {<br> apiKey := ctx.Header(&quot;X-API-Key&quot;)<br> if apiKey == &quot;&quot; {<br>  ctx.StopWithStatus(iris.StatusForbidden)<br>  return<br> }<br><br> rate.SetIdentifier(ctx, apiKey)<br> ctx.Next()<br>}<br><br>func list(ctx iris.Context) {<br> ctx.JSON(iris.Map{&quot;key&quot;: &quot;value&quot;})<br>}</pre><h3>Custom Exceed Handler</h3><p>This example demonstrates how to set a custom handler to be executed when the rate limit is exceeded:</p><pre>package main<br><br>import (<br> &quot;time&quot;<br><br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/rate&quot;<br>)<br><br>func main() {<br> app := iris.New()<br> app.Logger().SetLevel(&quot;debug&quot;)<br><br> // Set a custom exceed handler.<br> limit := rate.Limit(1, 5, rate.ExceedHandler(func(ctx iris.Context) {<br>  ctx.StopWithStatus(429)<br> }))<br> app.Use(limit)<br><br> app.Get(&quot;/&quot;, index)<br> app.Get(&quot;/other&quot;, other)<br><br> app.Listen(&quot;:8080&quot;)<br>}<br><br>func index(ctx iris.Context) {<br> ctx.HTML(&quot;&lt;h1&gt;Index Page&lt;/h1&gt;&quot;)<br>}<br><br>func other(ctx iris.Context) {<br> ctx.HTML(&quot;&lt;h1&gt;Other Page&lt;/h1&gt;&quot;)<br>}</pre><h3>Custom Client Data</h3><p>This example demonstrates how to store custom data for each client:</p><pre>package main<br><br>import (<br> &quot;time&quot;<br><br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/rate&quot;<br>)<br><br>func main() {<br> app := iris.New()<br> app.Logger().SetLevel(&quot;debug&quot;)<br><br> // Store custom data for each client.<br> limit := rate.Limit(1, 5, rate.ClientData(func(ctx iris.Context) any {<br>  return ctx.RemoteAddr()<br> }))<br> app.Use(limit)<br><br> app.Get(&quot;/&quot;, index)<br> app.Get(&quot;/other&quot;, other)<br><br> app.Listen(&quot;:8080&quot;)<br>}<br><br>func index(ctx iris.Context) {<br> ctx.HTML(&quot;&lt;h1&gt;Index Page&lt;/h1&gt;&quot;)<br>}<br><br>func other(ctx iris.Context) {<br> ctx.HTML(&quot;&lt;h1&gt;Other Page&lt;/h1&gt;&quot;)<br>}</pre><h3>Explanation</h3><ul><li>Rate Limiting: The rate.Limit function is used to create a new rate limiter. It takes three parameters:</li></ul><p>limit: The maximum number of requests allowed per second.</p><p>burst: The maximum burst size.</p><p>options: Additional options such as PurgeEvery for cleaning up old entries.</p><ul><li>Token Bucket Algorithm: This algorithm controls the rate of requests by maintaining a bucket of tokens. Each request consumes a token, and tokens are added to the bucket at a fixed rate. If the bucket is empty, the request is denied.</li></ul><h3>Token Bucket Algorithm</h3><p>The token bucket algorithm is a simple and efficient way to control the rate of requests. It works as follows:</p><ol><li>Initialization: A bucket is initialized with a certain number of tokens.</li><li>Token Addition: Tokens are added to the bucket at a fixed rate.</li><li>Request Handling: Each request consumes a token. If the bucket is empty, the request is denied.</li><li>Burst Handling: The bucket can hold a maximum number of tokens, allowing for bursts of traffic.</li></ol><p>For more details, refer to the <a href="https://en.wikipedia.org/wiki/Token_bucket">Wikipedia article on Token Bucket</a>.</p><h3>Conclusion</h3><p>This middleware provides a robust and flexible way to implement rate limiting in your Iris applications. By using the token bucket algorithm, it ensures fair usage and prevents abuse, making your application more reliable and secure.</p><p>For more examples and detailed usage, refer to the <a href="https://github.com/kataras/iris/tree/main/_examples/request-ratelimit/rate-middleware">official Iris documentation</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dc5746df7bfe" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AccessLog Middleware for Iris]]></title>
            <link>https://medium.com/@kataras/accesslog-middleware-for-iris-2e411ba0e4a0?source=rss-15bee39f2b28------2</link>
            <guid isPermaLink="false">https://medium.com/p/2e411ba0e4a0</guid>
            <category><![CDATA[go]]></category>
            <category><![CDATA[backend-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[logging]]></category>
            <dc:creator><![CDATA[Gerasimos Maropoulos]]></dc:creator>
            <pubDate>Wed, 30 Oct 2024 18:47:55 GMT</pubDate>
            <atom:updated>2024-10-30T20:56:07.856Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*l8dV2rKhFYSq6LdJKz6xsQ.png" /></figure><p>The accesslog middleware for the Iris web framework provides detailed logging for incoming HTTP requests. This middleware is highly configurable and can log various aspects of the request and response, including custom fields.</p><h3>Features</h3><ul><li>Logs request and response details.</li><li>Supports multiple output formats (JSON, CSV, custom templates).</li><li>Can log to multiple destinations (files, stdout, etc.).</li><li>Asynchronous logging support.</li><li>Customizable log fields.</li><li>Middleware can be conditionally applied.</li></ul><h3>Installation</h3><p>To use the accesslog middleware, you need to import it in your Iris application:</p><pre>import (<br>    &quot;github.com/kataras/iris/v12&quot;<br>    &quot;github.com/kataras/iris/v12/middleware/accesslog&quot;<br>)</pre><h3>Basic Usage</h3><p>Here is a basic example of how to use the accesslog middleware in an Iris application:</p><pre>package main<br><br>import (<br>    &quot;github.com/kataras/iris/v12&quot;<br>    &quot;github.com/kataras/iris/v12/middleware/accesslog&quot;<br>)<br><br>func makeAccessLog() *accesslog.AccessLog {<br>    ac := accesslog.File(&quot;./access.log&quot;)<br>    ac.Delim = &#39;|&#39;<br>    ac.TimeFormat = &quot;2006-01-02 15:04:05&quot;<br>    ac.Async = false<br>    ac.IP = true<br>    ac.BytesReceivedBody = true<br>    ac.BytesSentBody = true<br>    ac.BytesReceived = false<br>    ac.BytesSent = false<br>    ac.RequestBody = true<br>    ac.ResponseBody = false<br>    ac.KeepMultiLineError = true<br>    ac.PanicLog = accesslog.LogHandler<br>    ac.SetFormatter(&amp;accesslog.JSON{<br>        Indent:    &quot;  &quot;,<br>        HumanTime: true,<br>    })<br>    return ac<br>}<br><br>func main() {<br>    ac := makeAccessLog()<br>    defer ac.Close()<br>    app := iris.New()<br>    app.UseRouter(ac.Handler)<br>    app.Get(&quot;/&quot;, func(ctx iris.Context) {<br>        ctx.WriteString(&quot;OK&quot;)<br>    })<br>    app.Listen(&quot;:8080&quot;)<br>}</pre><h3>Configuration Options</h3><h3>Output Destination</h3><p>You can set the output destination for the logs using the File or New functions:</p><pre>ac := accesslog.File(&quot;./access.log&quot;)<br>// or<br>ac := accesslog.New(os.Stdout)</pre><h3>Log Format</h3><p>The default log format is:</p><pre>Time|Latency|Code|Method|Path|IP|Path Params Query Fields|Bytes Received|Bytes Sent|Request|Response|</pre><p>You can customize the log format using different formatters:</p><h4>JSON Formatter</h4><pre>ac.SetFormatter(&amp;accesslog.JSON{<br>    Indent:    &quot;  &quot;,<br>    HumanTime: true,<br>})</pre><h4>CSV Formatter</h4><pre>ac.SetFormatter(&amp;accesslog.CSV{})</pre><h4>Custom Template Formatter</h4><pre>ac.SetFormatter(&amp;accesslog.Template{Text: &quot;{{.Code}}&quot;})</pre><h3>Custom Fields</h3><p>You can add custom fields to the log entries:</p><pre>ac.AddFields(func(ctx iris.Context, f *accesslog.Fields) {<br>    for k, v := range ctx.Request().Header {<br>        value := strings.Join(v, &quot;, &quot;)<br>        f.Set(&quot;request.header.&quot;+k, value)<br>    }<br>})</pre><h3>Asynchronous Logging</h3><p>Enable asynchronous logging to improve performance:</p><pre>ac.Async = true</pre><h3>Conditional Logging</h3><p>You can skip logging for specific routes or conditions:</p><pre>app.UseRouter(accesslog.SkipHandler)</pre><h3>Advanced Usage</h3><h3>Logging to Multiple Destinations</h3><p>You can log to multiple destinations using io.MultiWriter:</p><pre>ac.SetOutput(io.MultiWriter(os.Stdout, accesslog.File(&quot;./access.log&quot;)))</pre><h3>Custom Clock</h3><p>You can set a custom clock for the log timestamps, useful for testing:</p><pre>ac.Clock = accesslog.TClock(time.Now())</pre><h3>Middleware Integration</h3><p>Integrate the accesslog middleware with other middlewares:</p><pre>app.UseRouter(ac.Handler)<br>app.UseRouter(otherMiddleware)</pre><h3>Examples</h3><h3>Log Requests to a JSON File</h3><pre>ac := accesslog.File(&quot;access_log.json&quot;)<br>ac.SetFormatter(&amp;accesslog.JSON{<br>    Indent:    &quot;  &quot;,<br>    HumanTime: true,<br>})<br>app.UseRouter(ac.Handler)</pre><h3>Using Log Rotation</h3><p>Refer to the <a href="https://github.com/kataras/iris/tree/main/_examples/logging/request-logger/accesslog">log rotation example</a> for more details.</p><h3>Custom Fields and Template</h3><p>Refer to the <a href="https://github.com/kataras/iris/tree/main/_examples/logging/request-logger/accesslog-template">custom fields and template example</a> for more details.</p><h3>Listen and Render Logs to a Client</h3><p>Refer to the <a href="https://github.com/kataras/iris/tree/main/_examples/logging/request-logger/accesslog-broker">log broker example</a> for more details.</p><h3>Conclusion</h3><p>The accesslog middleware for Iris is a powerful tool for logging HTTP requests and responses. With its flexible configuration options and support for custom fields and formats, it can be tailored to meet the needs of any application.</p><p>For more examples and detailed usage, refer to the <a href="https://github.com/kataras/iris/tree/main/_examples/logging/request-logger">official Iris documentation</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2e411ba0e4a0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Rewrite: A Simple and Powerful URL Rewriter for Go]]></title>
            <link>https://medium.com/@kataras/rewrite-a-simple-and-powerful-url-rewriter-for-go-e0b4db5bfce6?source=rss-15bee39f2b28------2</link>
            <guid isPermaLink="false">https://medium.com/p/e0b4db5bfce6</guid>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[networking]]></category>
            <category><![CDATA[go]]></category>
            <dc:creator><![CDATA[Gerasimos Maropoulos]]></dc:creator>
            <pubDate>Sun, 09 Jul 2023 14:05:18 GMT</pubDate>
            <atom:updated>2023-07-09T14:05:18.559Z</atom:updated>
            <content:encoded><![CDATA[<p>Rewrite is a Go package that lets you rewrite URL paths, subdomains or hosts based on regular expressions. It is inspired by Apache’s mod_rewrite module and can be used as a middleware for <a href="https://pkg.go.dev/net/http">net/http</a>-based servers.</p><p>Rewrite can help you achieve better SEO results by redirecting old or unwanted URLs to new ones, enforcing a primary subdomain, or simplifying complex URL structures.</p><h4>How to Install Rewrite</h4><p>To install Rewrite, you need to have Go installed on your system. Then, you can use the go get command to download and install the package:</p><pre>$ go get github.com/kataras/rewrite</pre><h4>How to Use Rewrite</h4><p>You can load rewrite options in two ways:</p><p>1. Through code using the <em>New</em> function and <em>Handler</em> method. This way, you can handle parse errors and create rules programmatically.</p><p>2. Or through a YAML file using the <em>Load</em> function which returns a <em>func(http.Handler) http.Handler</em>. This is the most common and simplest way. It panics on parse errors.</p><p>The syntax of the rewrite rules is:</p><pre>REDIRECT_CODE_DIGITS PATTERN_REGEX TARGET_REPL</pre><p>Where:</p><p>- <em>REDIRECT_CODE_DIGITS</em> is the HTTP status code to use for the redirection, such as 301 (Moved Permanently) or 302 (Found).</p><p>- <em>PATTERN_REGEX</em> is the regular expression that matches the request URL path, subdomain or host.</p><p>- <em>TARGET_REPL</em> is the replacement string that contains the new URL path, subdomain or host.</p><p>For example:</p><pre>301 /seo/(.*) /$1</pre><p>This rule redirects all requests from relative path <em>/seo/*` to `/*</em> using the 301 HTTP status code.</p><p>You can also use a special option called <em>PrimarySubdomain</em> to redirect all requests from the root domain to a specific subdomain, such as <em>www</em>.</p><p>For example:</p><pre>PrimarySubdomain: www</pre><p>This option redirects all requests from <em>example.com</em> to <em>www.example.com</em>.</p><h4>Examples</h4><p>Let’s write a simple application that follows these redirect rules:</p><p>- Redirects `<em>/seo/*</em>` to `<em>/*</em>`</p><p>- Redirects `<em>/docs/v12</em>*` to `<em>/docs</em>`</p><p>- Redirects `<em>/old (.*)</em>` to `<em>/</em>`</p><p>- Redirects root domain requests to `<em>www.</em>`</p><p>The code would look like this:</p><pre>package main<br><br>import (<br>  &quot;net/http&quot;<br><br>  &quot;github.com/kataras/rewrite&quot;<br>)<br><br>func main() {<br>  mux := http.NewServeMux()<br>  // […routes]<br>  // Load the redirect rules from a YAML file.<br>  redirects := rewrite.Load(&quot;redirects.yml&quot;)<br>  // Wrap the router with the rewrite middleware.<br>  http.ListenAndServe(&quot;:8080&quot;, redirects(mux))<br>}</pre><p>The YAML file would look like this:</p><pre>RedirectMatch:<br>  # Redirects /seo/* to /*<br>  - 301 /seo/(.*) /$1<br>  # Redirects /docs/v12* to /docs<br>  - 301 /docs/v12(.*) /docs<br>  # Redirects /old (.*) to /<br>  - 301 /old(.*) /<br># Redirects root domain requests to www.<br>PrimarySubdomain: www</pre><p>That’s it! Now you can test your application and see how it redirects the requests according to your rules.</p><p>You can find more examples in the `_examples` folder of the GitHub repository: <a href="https://github.com/kataras/rewrite/tree/main/_examples">https://github.com/kataras/rewrite/tree/main/_examples</a></p><h4>Conclusion</h4><p>Rewrite is a handy package that lets you rewrite URLs in Go with ease. It is compatible with any net/http router or framework and supports regular expressions for flexible matching and replacing. It can help you improve your SEO performance by redirecting old or unwanted URLs to new ones, enforcing a primary subdomain, or simplifying complex URL structures.</p><p>If you want to learn more about Rewrite, you can check out its GitHub repository: <a href="https://github.com/kataras/rewrite">https://github.com/kataras/rewrite</a></p><p>I hope you enjoyed this article and found it useful. If you have any feedback or questions, feel free to leave a comment below. Thank you for reading! 😊</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e0b4db5bfce6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to use Iris and Basic authentication]]></title>
            <link>https://medium.com/@kataras/how-to-use-iris-and-basic-authentication-b648b8b95e02?source=rss-15bee39f2b28------2</link>
            <guid isPermaLink="false">https://medium.com/p/b648b8b95e02</guid>
            <category><![CDATA[siri]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[go]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Gerasimos Maropoulos]]></dc:creator>
            <pubDate>Sat, 08 Jul 2023 12:35:51 GMT</pubDate>
            <atom:updated>2023-07-08T12:36:54.465Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Xbf8982Wu5ECogXIO9yXFQ.png" /></figure><p><a href="https://www.iris-go.com">Iris </a>is a fast, simple yet fully featured and very efficient web framework for Go. It provides a beautifully expressive and easy to use foundation for your next website or API. One of the features that Iris offers the middleware/basicauth sub-package, which allows you to implement basic authentication for your web applications.</p><p>Basic authentication is a simple and widely used scheme that requires the client to provide a username and password to access a protected resource. The credentials are encoded with Base64 and sent in the HTTP header. However, they are not encrypted or hashed, so basic authentication should be used in conjunction with HTTPS to provide confidentiality.</p><p>In this article, we will show you how to use the basicauth middleware to add basic authentication to your Iris handlers.</p><h4>Installing Iris and BasicAuth Middleware</h4><p>To use the BasicAuth middleware, you need to install Iris first. You can do that by running the following command in your terminal:</p><pre>go get github.com/kataras/iris/v12@latest</pre><p>This will download and install the latest version of Iris and its dependencies. You can also specify a specific version if you want.</p><p>Next, you need to import the middleware/basicauth sub-package in your Go code. You can do that by adding the following line at the top of your file:</p><pre>import &quot;github.com/kataras/iris/v12/middleware/basicauth&quot;</pre><p>This will make the basicauth package available for your use.</p><h4>Creating a basic authentication middleware</h4><p>To create a basic authentication middleware, you need to use the <em>basicauth.New</em> function from the basicauth package. This function accepts a <em>basicauth.Options</em> struct that contains various options for configuring the middleware. The most important option is the <em>Allow </em>field, which is a function that takes a username and password as arguments and returns true if they are valid or false otherwise. You can use one of the helper methods from the basicauth package to create this function from different sources of valid credentials. They are:</p><p>- <em>basicauth.AllowUsers</em>: This method takes a map of usernames and passwords and returns an Allow function that uses the given map as the source of valid credentials. This is useful if you want to create the Allow function from a predefined map of users.</p><p>- <em>basicauth.AllowUsersFile</em>: This method takes a JSON or YAML filename and returns an Allow function that uses the file as the source of valid credentials. The file should contain an array of objects with username and password fields. This is useful if you want to store your users in an external file instead of in your code.</p><p>- <em>basicauth.BCRYPT:</em> This method takes a <em>UserAuthOptions </em>struct and modifies it to use bcrypt hashing for comparing passwords. This is useful if you want to store hashed passwords instead of plain ones in your users map or file. You can pass this method as an argument to the <em>basicauth.AllowUsers</em> or <em>basicauth.AllowUsersFile</em> helper methods to create an <em>Allow </em>function that uses bcrypt hashing.</p><p>You can also set other options such as <em>Realm</em>, <em>Expires</em>, <em>ErrorHandler </em>and more.</p><p>The <em>basicauth.New</em> function returns an <em>iris.Handler</em>, which is a function that takes an <em>iris.Context</em> as an argument and performs some actions on it. You can register this handler as a middleware for your routes or parties using methods such as <em>Use</em>, <em>UseGlobal</em>, or <em>UseRouter</em>.</p><p>Here is an example of how to create and use a basic authentication middleware using a map of users:</p><pre>package main<br><br>import (<br> &quot;github.com/kataras/iris/v12&quot;<br> &quot;github.com/kataras/iris/v12/middleware/basicauth&quot;<br>)<br><br>func main() {<br> app := iris.New()<br><br> // Create a map of usernames and passwords.<br> users := map[string]string{<br>  &quot;myusername&quot;: &quot;mypassword&quot;,<br>  &quot;admin&quot;:      &quot;admin&quot;,<br> }<br><br> // Create an Allow function using basicauth.AllowUsers helper method.<br> allow := basicauth.AllowUsers(users)<br><br> // Create a basic authentication middleware using basicauth.New.<br> auth := basicauth.New(basicauth.Options{<br>  Realm: basicauth.DefaultRealm,<br>  Allow: allow,<br> })<br><br> // Register the auth handler as a global middleware using UseGlobal.<br> app.UseGlobal(auth)<br><br> // Register some routes that require basic authentication.<br> app.Get(&quot;/&quot;, func(ctx iris.Context) {<br>  username, password, _ := ctx.User()<br>  ctx.Writef(&quot;%s %s: You are authenticated&quot;, username, password)<br> })<br><br> app.Get(&quot;/admin&quot;, func(ctx iris.Context) {<br>  username, _, _ := ctx.User()<br>  if username == &quot;admin&quot; {<br>   ctx.WriteString(&quot;Hello admin&quot;)<br>  } else {<br>   ctx.StopWithText(iris.StatusForbidden, &quot;Only admin can access this page&quot;)<br>  }<br> })<br><br> app.Get(&quot;/logout&quot;, func(ctx iris.Context) {<br>  ctx.Logout()<br>  ctx.Redirect(&quot;/&quot;)<br> })<br><br> app.Listen(&quot;:8080&quot;)<br>}</pre><h4>Testing the basic authentication middleware</h4><p>To test the basic authentication middleware, you can run the above code and visit <a href="http://localhost:8080">http:<em>//localhost:8080</em></a><em> in your browser. You should see a prompt asking you for your username and password. If you enter one of the valid credentials from the users map, you should see a message saying that you are authenticated. If you enter an invalid credential, you should see an error message saying that authorization is required.</em></p><p>You can also visit <a href="http://localhost:8080/admin">http:<em>//localhost:8080/admin</em></a><em> to see a page that is only accessible by the admin user. If you enter the admin credential, you should see a message saying hello admin. If you enter any other credential, you should see a message saying that only admin can access this page.</em></p><p>You can also visit <a href="http://localhost:8080/logout">http:<em>//localhost:8080/logout</em></a><em> to log out from the basic authentication and clear the cookie. You should be redirected to the home page and see the prompt again if you refresh the page.</em></p><h4>Conclusion</h4><p>In this article, we have learned how to use the middleware/basicauth sub-package to create a basic authentication middleware for your Iris handlers. We have seen how to configure the middleware with various options, how to register it as a global or route-specific middleware, and how to test it in the browser. We have also seen how to use different helper methods to create the <em>Allow </em>function from different sources of valid credentials, and how to use bcrypt hashing to store hashed passwords. We have also seen how to use the <em>Context.User()</em> method to get the username and password of the authenticated user, and how to use the <em>Context.Logout()</em> method to log out from the basic authentication.</p><p>We hope that this article has helped you understand how to use Iris and basic authentication for your web applications. For more information and examples, you can visit the official documentation of Iris at <a href="https://www.iris-go.com/docs/#/?id=using-basic-authentication">https:<em>//www.iris-go.com/docs/#/?id=using-basic-authentication</em></a><em> and the GitHub repository of Iris at </em><a href="https://github.com/kataras/iris/tree/master/_examples/auth/basicauth."><em>https://github.com/kataras/iris/tree/master/_examples/auth/basicauth.</em></a><em> Thank you for reading!</em></p><p>The article was also published at:</p><p><a href="https://dev.to/kataras/how-to-use-iris-and-basic-authentication-5hjm">https://dev.to/kataras/how-to-use-iris-and-basic-authentication-5hjm</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b648b8b95e02" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Use Iris and PostgreSQL for Web Development]]></title>
            <link>https://medium.com/@kataras/how-to-use-iris-and-postgresql-for-web-development-e8c46d72f1e6?source=rss-15bee39f2b28------2</link>
            <guid isPermaLink="false">https://medium.com/p/e8c46d72f1e6</guid>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[go]]></category>
            <category><![CDATA[siri]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Gerasimos Maropoulos]]></dc:creator>
            <pubDate>Sun, 02 Jul 2023 12:09:13 GMT</pubDate>
            <atom:updated>2023-07-08T12:23:46.109Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*p89WGN73K6atrZcgJPLyAw.jpeg" /></figure><h3>A guide to using PG middleware, a package for Iris that provides easy and type-safe access to PostgreSQL database.</h3><p><a href="https://www.iris-go.com/">Iris</a> is a fast and lightweight web framework for Go that offers a rich set of features and a high-performance engine. PostgreSQL is a powerful and reliable relational database system that supports advanced data types and functions. Together, they can form a solid foundation for building modern web applications.</p><p>But how can you connect Iris and PostgreSQL in a simple and type-safe way? How can you perform common database operations without writing too much boilerplate code? How can you handle transactions, schema creation, query tracing and error handling in a consistent manner?</p><p>The answer is PG middleware, a package for Iris that provides easy and type-safe access to PostgreSQL database. In this article, we will show you how to use PG middleware to create a simple REST API for managing customers.</p><h3>What is PG middleware?</h3><p>PG middleware is a package for Iris web framework that provides easy and type-safe access to PostgreSQL database. It has the following features:</p><ul><li>It supports PostgreSQL 9.5 and above.</li><li>It uses <a href="https://github.com/kataras/pg">pg</a> package and <a href="https://github.com/jackc/pgx">pgx</a> driver under the hood.</li><li>It supports transactions, schema creation and validation, query tracing and error handling.</li><li>It allows registering custom types and table models using a schema object.</li><li>It provides a generic repository interface for common CRUD operations.</li></ul><h3>How to install PG middleware?</h3><p>To install PG middleware, you need to use the following command:</p><pre>go get github.com/iris-contrib/middleware/pg@master</pre><h3>How to use PG middleware?</h3><p>To use PG middleware, you need to follow these steps:</p><ol><li>Import the package in your code:</li></ol><pre>import (<br>    &quot;github.com/kataras/iris/v12&quot;</pre><pre>    &quot;github.com/iris-contrib/middleware/pg&quot;<br>)</pre><ol><li>Define your database table models as structs with pg tags:</li></ol><pre>// The Customer database table model.<br>type Customer struct {<br>    ID   string `json:&quot;id&quot; pg:&quot;type=uuid,primary&quot;`<br>    Name string `json:&quot;name&quot; pg:&quot;type=varchar(255)&quot;`<br>}</pre><p>The json tag defines how the struct fields are encoded or decoded as JSON. The pg tag defines how the struct fields are mapped to the database table columns. You can specify the column type, constraints, indexes and other options using the pg tag. Read more at <a href="https://github.com/kataras/pg">pg</a> repository.</p><ol><li>Create a schema object and register your models:</li></ol><pre>schema := pg.NewSchema()<br>schema.MustRegister(&quot;customers&quot;, Customer{})</pre><p>The schema object is used to store the metadata of your database tables and models. You need to register your models with the schema object using the MustRegister method. The first argument is the table name, and the second argument is the model type.</p><ol><li>Create a PG middleware instance with the schema and database options:</li></ol><pre>opts := pg.Options{<br>    Host:          &quot;localhost&quot;,<br>    Port:          5432,<br>    User:          &quot;postgres&quot;,<br>    Password:      &quot;admin!123&quot;,<br>    DBName:        &quot;test_db&quot;,<br>    Schema:        &quot;public&quot;,<br>    SSLMode:       &quot;disable&quot;,<br>    Transactional: true,<br>    Trace:         true,<br>    CreateSchema:  true,<br>    CheckSchema:   true,<br>    ErrorHandler: func(ctx iris.Context, err error) {<br>        ctx.StopWithError(iris.StatusInternalServerError, err)<br>    },<br>}</pre><pre>p := pg.New(schema, opts)</pre><p>The options struct defines the configuration parameters for connecting to the database and using the middleware features. You need to specify the host, port, user, password, dbname, schema and sslmode fields for establishing the connection. You can also enable or disable the transactional feature, which wraps each request handler in a database transaction. You can also enable or disable the trace feature, which logs each query executed by the middleware. You can also enable or disable the createSchema feature, which creates the schema if it doesn’t exist in the database. You can also enable or disable the checkSchema feature, which checks the schema for missing tables and columns and reports any discrepancies. You can also provide an errorHandler function, which handles any errors occurred during the middleware execution.</p><p>The New function creates a new PG middleware instance with the given schema and options.</p><ol><li>Attach the middleware handler to your Iris app or routes:</li></ol><pre>app := iris.New()</pre><pre>postgresMiddleware := newPostgresMiddleware()</pre><pre>{<br>    customerAPI := app.Party(&quot;/api/customer&quot;, postgresMiddleware)<br>    customerAPI.Post(&quot;/&quot;, createCustomer)<br>    customerAPI.Get(&quot;/{id:uuid}&quot;, getCustomer)<br>    customerAPI.Put(&quot;/{id:uuid}&quot;, updateCustomer)<br>    customerAPI.Delete(&quot;/{id:uuid}&quot;, deleteCustomer)<br>}</pre><p>The middleware handler is a function that takes an Iris context and calls the next handler in the chain. You can attach the middleware handler to your Iris app or routes using the Use or Party methods. In this example, we create a subrouter for the customer API and apply the middleware handler to it.</p><ol><li>Use the pg.DB or pg.Repository package-level functions to access the database instance or the repository interface in your handlers:</li></ol><pre>func createCustomer(ctx iris.Context) {<br>    var payload = struct {<br>        Name string `json:&quot;name&quot;`<br>    }{}<br>    err := ctx.ReadJSON(&amp;payload)<br>    if err != nil {<br>        ctx.StopWithError(iris.StatusBadRequest, err)<br>        return<br>    }<br><br>    // Get the current database instance through pg.DB middleware<br>    // package-level function.<br>    // db := pg.DB(ctx)<br>    // [Work with db instance...]<br>    // OR, initialize a new repository of Customer type and<br>    // work with it (type-safety).<br>    customers := pg.Repository[Customer](ctx)<br>    // Insert a new Customer.<br>    customer := Customer{<br>        Name: payload.Name,<br>    }<br>    err = customers.InsertSingle(ctx, customer, &amp;customer.ID)<br>    if err != nil {<br>        ctx.StopWithError(iris.StatusInternalServerError, err)<br>        return<br>    }<br>    // Display the result ID.<br>    ctx.StatusCode(iris.StatusCreated)<br>    ctx.JSON(iris.Map{&quot;id&quot;: customer.ID})<br>}<br><br>func getCustomer(ctx iris.Context) {<br>    // Get the id from the path parameter.<br>    id := ctx.Params().Get(&quot;id&quot;)<br>    // Get the repository of Customer type through pg.Repository<br>    // middleware package-level function.<br>    customers := pg.Repository[Customer](ctx)<br>    // Get the customer by the id.<br>    customer, err := customers.SelectByID(ctx, id)<br>    if err != nil {<br>        if pg.IsErrNoRows(err) {<br>            ctx.StopWithStatus(iris.StatusNotFound)<br>        } else {<br>            ctx.StopWithError(iris.StatusInternalServerError, err)<br>        }<br>        return<br>    }<br>    // Display the retrieved Customer.<br>    ctx.JSON(customer)<br>}<br><br>func updateCustomer(ctx iris.Context) {<br>    // Get the id from the path parameter.<br>    id := ctx.Params().Get(&quot;id&quot;)<br>    var payload = struct {<br>        Name string `json:&quot;name&quot;`<br>    }{}<br>    err := ctx.ReadJSON(&amp;payload)<br>    if err != nil {<br>        ctx.StopWithError(iris.StatusBadRequest, err)<br>        return<br>    }<br>    // Get the repository of Customer type through pg.Repository<br>    // middleware package-level function.<br>    customers := pg.Repository[Customer](ctx)<br>    // Update the customer by the id and name.<br>    customer := Customer{<br>        ID: id,<br>        Name: payload.Name,<br>    }<br>    _, err = customers.UpdateOnlyColumns(ctx, []string{&quot;name&quot;}, customer)<br>    // OR customers.Update(ctx, customer)<br>    if err != nil {<br>        if pg.IsErrNoRows(err) {<br>            ctx.StopWithStatus(iris.StatusNotFound)<br>        } else {<br>            ctx.StopWithError(iris.StatusInternalServerError, err)<br>        }<br>        return<br>    }<br>    // Display a success message.<br>    ctx.StatusCode(iris.StatusOK)<br>    ctx.JSON(iris.Map{&quot;message&quot;: &quot;Customer updated successfully&quot;})<br>}<br><br>func deleteCustomer(ctx iris.Context) {<br>    // Get the id from the path parameter.<br>    id := ctx.Params().Get(&quot;id&quot;)<br>    // Get the repository of Customer type through pg.Repository<br>    // middleware package-level function.<br>    customers := pg.Repository[Customer](ctx)<br>    // Delete the customer by the id.<br>    _, err := customers.Delete(ctx, Customer{ID: id})<br>    if err != nil {<br>        if pg.IsErrNoRows(err) {<br>            ctx.StopWithStatus(iris.StatusNotFound)<br>        } else {<br>            ctx.StopWithError(iris.StatusInternalServerError, err)<br>        }<br>        return<br>    }<br>    // Display a success message.<br>    ctx.StatusCode(iris.StatusOK)<br>    ctx.JSON(iris.Map{&quot;message&quot;: &quot;Customer deleted successfully&quot;})<br>}</pre><p>The pg.DB function returns the current database instance associated with the Iris context. You can use this instance to perform any database operations using the pg package API. The pg.Repository function returns a generic repository interface for the given model type associated with the Iris context. You can use this interface to perform common CRUD operations using type-safe methods. In this example, we use the repository interface to insert and select customers.</p><h3>How to run the example?</h3><p>To run the example, you need to:</p><ol><li>Clone the <a href="https://github.com/iris-contrib/middleware/tree/master/pg">PG middleware repository</a> and navigate to the _examples/basic folder.</li><li>Install the dependencies using go mod tidy.</li><li>Start a PostgreSQL server and create a database named test_db.</li><li>Run the main.go file using go run main.go.</li><li>Use a tool like <a href="https://www.postman.com/">Postman</a> or <a href="https://curl.se/">curl</a> to test the API endpoints:</li></ol><pre># Create a new customer<br>curl -X POST -H &quot;Content-Type: application/json&quot; -d &#39;{&quot;name&quot;:&quot;Alice&quot;}&#39; http://localhost:8080/api/customer</pre><pre># Get a customer by id<br>curl -X GET <a href="http://localhost:8080/api/customer/1f8c9a7c-6b7c-4f0e-8a1d-9f2a9c3b7b8e">http://localhost:8080/api/customer/1f8c9a7c-6b7c-4f0e-8a1d-9f2a9c3b7b8e</a></pre><pre># Update a customer by id<br>curl -X PUT -H &quot;Content-Type: application/json&quot; -d &#39;{&quot;name&quot;:&quot;Bob&quot;}&#39; <a href="http://localhost:8080/api/customer/1f8c9a7c-6b7c-4f0e-8a1d-9f2a9c3b7b8e">http://localhost:8080/api/customer/1f8c9a7c-6b7c-4f0e-8a1d-9f2a9c3b7b8e</a></pre><pre># Delete a customer by id<br>curl -X DELETE <a href="http://localhost:8080/api/customer/1f8c9a7c-6b7c-4f0e-8a1d-9f2a9c3b7b8e">http://localhost:8080/api/customer/1f8c9a7c-6b7c-4f0e-8a1d-9f2a9c3b7b8e</a></pre><h3>Conclusion</h3><p>In this article, we have shown you how to use PG middleware to connect Iris and PostgreSQL in a simple and type-safe way. We have also demonstrated how to use PG middleware features such as transactions, schema creation and validation, query tracing and error handling. We have also shown how to use PG middleware to create a simple REST API for managing customers.</p><p>The article was also published at:</p><ol><li><a href="https://dev.to/kataras/how-to-use-iris-and-postgresql-for-web-development-3kka">https://dev.to/kataras/how-to-use-iris-and-postgresql-for-web-development-3kka</a></li><li><a href="https://www.linkedin.com/pulse/how-use-iris-postgresql-web-development-gerasimos-maropoulos/">https://medium.com/@kataras/how-to-use-iris-and-postgresql-for-web-development-e8c46d72f1e6</a></li><li><a href="https://twitter.com/TheGoDev/status/1676701488544874498">https://twitter.com/TheGoDev/status/1676701488544874498</a></li><li><a href="https://twitter.com/TheDatabaseDev/status/1676748294595174401">https://twitter.com/TheDatabaseDev/status/1676748294595174401</a></li></ol><p>We hope you find PG middleware useful and easy to use. If you have any feedback or questions, please feel free to open an issue or a pull request on <a href="https://github.com/iris-contrib/middleware/tree/master/pg">GitHub</a>. Thank you for reading!🙏</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e8c46d72f1e6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What’s the fastest template engine in Go?]]></title>
            <link>https://medium.com/hackernoon/whats-the-fastest-template-engine-in-go-fdf0cb95899b?source=rss-15bee39f2b28------2</link>
            <guid isPermaLink="false">https://medium.com/p/fdf0cb95899b</guid>
            <category><![CDATA[html]]></category>
            <category><![CDATA[iris-web-framework]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[go]]></category>
            <dc:creator><![CDATA[Gerasimos Maropoulos]]></dc:creator>
            <pubDate>Thu, 01 Oct 2020 14:26:59 GMT</pubDate>
            <atom:updated>2020-10-16T18:33:11.817Z</atom:updated>
            <content:encoded><![CDATA[<p>Have you ever wondered what template engine to use in Go?</p><p>Hello folks,</p><p>It has been a <a href="https://medium.com/hackernoon/go-vs-net-core-in-terms-of-http-performance-7535a61b67b8">long time</a> since we talked about performance in <a href="https://golang.org/">Go</a>.</p><p>There is no secret that Go has support for a large amount of template syntax nowadays. However, we’ve seen zero articles on how each of them performs. Here we are.</p><h3>Intro</h3><p>In this article we will run simple, easy to understand, mini benchmarks to find out which template parser renders faster. Keep in mind that speed is not always the case, you have to choose wisely the template parser to use because their features varies and depending your application’s needs you may be forced to use an under-performant parser instead.</p><p>We will compare the following 8 template engines/parsers:</p><ol><li><a href="https://github.com/yosssi/ace">Ace</a></li><li><a href="https://github.com/eknkc/amber">Amber</a></li><li><a href="https://github.com/kataras/blocks">Blocks</a></li><li><a href="https://github.com/flosch/pongo2">Django</a></li><li><a href="https://github.com/aymerick/raymond">Handlebars</a></li><li><a href="https://pkg.go.dev/html/template">HTML (standard html/template)</a></li><li><a href="https://github.com/CloudyKit/jet">Jet</a></li><li><a href="https://github.com/Joker/jade">Pug</a></li></ol><p>Each benchmark test consists of a template + layout + partial + template data (map). They all have the same response amount of total bytes. Amber, Ace and Pug parsers minifies the template before render, therefore, all other template file’s contents are minified too (no new lines and spaces between html blocks).</p><p>As always, my benchmark code is available for everyone but I will not tire you anymore by showing the code for each of them in the article, instead you can navigate <a href="https://github.com/kataras/iris/tree/master/_benchmarks/view">here</a>.</p><h3>Benchmarks</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8a2b10f63fde6faa7fce8dda52c455c8/href">https://medium.com/media/8a2b10f63fde6faa7fce8dda52c455c8/href</a></iframe><h4>Terminology</h4><p><strong>Name </strong>is the name of the template engine.</p><p><strong>Reqs/sec </strong>is the avg number of total requests could be processed per second (the higher the better).</p><p><strong>Latency </strong>is the amount of time it takes from when a request is made by the client to the time it takes for the response to get back to that client (the smaller the better).</p><p><strong>Throughput </strong>is the rate of production or the rate at which data are transferred (the higher the better, it depends from response length (body + headers).</p><p><strong>Time To Complete</strong> is the total time (in seconds) the test completed (the smaller the better).</p><h4>Results</h4><p>📖 Fires 1000000 requests with 125 concurrent clients. It receives HTML response. The server handler sets some template data and renders a template file which consists of a layout and a partial footer.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9a99e76b2a0518189163ea228652d1bb/href">https://medium.com/media/9a99e76b2a0518189163ea228652d1bb/href</a></iframe><p>And for those who like graphs, here you are:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*iBhebOAuZ4Ktg7DDe1dTIw.png" /></figure><p>As we’ve seen above, Amber is the fastest and Jet is the slowest one. Keep in mind that in Jet parser, we cache the templates by ourselves before server ran — its default behavior is to cache them at runtime instead, so it could be even slower natively.</p><p>If you want to run the benchmarks by yourself, please follow the guide below:</p><ol><li>Install the <a href="https://golang.org/dl">Go Programming Language</a></li><li>Download and unzip the<a href="https://github.com/kataras/iris/tree/master/_benchmarks/view"> test files</a> using <em>git clone</em></li><li>Open a terminal inside the test files directory and execute the commands below:</li></ol><pre>$ go get -u github.com/kataras/server-benchmarks<br>$ go get -u github.com/codesenberg/bombardier<br>$ server-benchmarks --wait-run=3s -o ./results</pre><blockquote>Follow my <a href="https://twitter.com/MakisMaropoulos">Twitter </a>and <a href="https://github.com/kataras">GitHub</a> <em>accounts</em>.</blockquote><p>Have fun 🥳 and keep yourself strong in these difficult and restless times we live in💪</p><p>Yours,<br>Gerasimos Maropoulos. Author of the <a href="https://www.iris-go.com/">Iris Web Framework</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fdf0cb95899b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/whats-the-fastest-template-engine-in-go-fdf0cb95899b">What’s the fastest template engine in Go?</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Todo MVC Application using Iris and Vue.js]]></title>
            <link>https://medium.com/hackernoon/a-todo-mvc-application-using-iris-and-vue-js-5019ff870064?source=rss-15bee39f2b28------2</link>
            <guid isPermaLink="false">https://medium.com/p/5019ff870064</guid>
            <category><![CDATA[iris-web-framework]]></category>
            <category><![CDATA[vuejs]]></category>
            <category><![CDATA[go]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Gerasimos Maropoulos]]></dc:creator>
            <pubDate>Sun, 31 Dec 2017 22:13:41 GMT</pubDate>
            <atom:updated>2019-11-02T22:15:36.861Z</atom:updated>
            <content:encoded><![CDATA[<p>Write a fast and modern mini todo application using Iris MVC and Vue.js</p><p>Vue.js is a front-end framework for building web applications using javascript. It has a blazing fast Virtual DOM renderer.</p><p>Iris is a back-end framework for building web applications using The Go Programming Language (disclaimer: author here). It’s one of the fastest and featured web frameworks out there. We wanna use this to serve our “todo service”.</p><h3>The Tools</h3><p>Programming Languages are just tools for us, but we need a safe, fast and “cross-platform” programming language to power our service.</p><p><a href="https://golang.org">Go</a> is a <a href="https://www.tiobe.com/tiobe-index/">rapidly growing</a> open source programming language designed for building simple, fast, and reliable software. Take a look <a href="https://github.com/golang/go/wiki/GoUsers">here</a> which great companies use Go to power their services.</p><h4>Install the Go Programming Language</h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F9x-pG3lvLi0%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D9x-pG3lvLi0&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F9x-pG3lvLi0%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/6f264d179f2c5b49fd3b2c7b346b7a3c/href">https://medium.com/media/6f264d179f2c5b49fd3b2c7b346b7a3c/href</a></iframe><blockquote>The article does not contain an introduction to the language itself, if you’re a newcomer I recommend you to bookmark this article, <a href="https://github.com/golang/go/wiki/Learn">learn </a>the language’s fundamentals and come back later on.</blockquote><h3><strong>The Dependencies</strong></h3><p>Many articles have been written, in the past, that lead developers not to use a web framework because they are useless and “bad”. I have to tell you that there is no such thing, it always depends on the (web) framework that you’re going to use. At production environment, we don’t have the time or the experience to code everything that we wanna use in the applications, and if we could are we sure that we can do better and safely than others? In short term: <strong>Good frameworks are helpful tools for any developer, company or startup and “bad” frameworks are waste of time, crystal clear.</strong></p><p>You’ll need two dependencies:</p><ol><li>Vue.js, for our client-side requirements. Download it from <a href="https://vuejs.org/">here</a>, latest v2.</li><li>The Iris Web Framework, for our server-side requirements. Can be found <a href="https://github.com/kataras/iris">here</a>, latest v12.</li></ol><p>If you have Go already installed then just execute go get github.com/kataras/iris/v12@latestto install the Iris Web Framework.</p><h3>Start</h3><p>If we are all in the same page, it’s time to learn how we can create a live todo application that will be easy to deploy and extend even more!</p><p>We’re going to use a vue.js todo application which uses browser’s local storage and doesn’t have any user-specified features like live sync between browser’s tabs, you can find the original version inside the vue’s <a href="https://vuejs.org/v2/examples/todomvc.html">docs</a>.</p><ul><li>web/public/js/app.js</li><li>web/public/index.html</li><li>todo/item.go</li><li>todo/service.go</li><li>web/controllers/todo_controller.go</li><li>web/main.go</li></ul><p><em>Read the comments in the source code, they may be very helpful</em></p><h3>The client-side (vue.js)</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ebeec059ec571184d0f89c54dba48fe3/href">https://medium.com/media/ebeec059ec571184d0f89c54dba48fe3/href</a></iframe><h4>Let’s add our view, the html.</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bd04992c3e1bf47f61ce2f4402ef4a93/href">https://medium.com/media/bd04992c3e1bf47f61ce2f4402ef4a93/href</a></iframe><h3>The server-side (iris)</h3><p>Our view model.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/952201398a8fedad49914f87904d3e89/href">https://medium.com/media/952201398a8fedad49914f87904d3e89/href</a></iframe><p>Our service.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8f7551739dca6abf7269e6ed7b2f17f8/href">https://medium.com/media/8f7551739dca6abf7269e6ed7b2f17f8/href</a></iframe><p>We are going to use some of the MVC functionalities of the iris web framework here but you can do the same with the standard API as well.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cb25acdc8e72139a43f581ea688ed552/href">https://medium.com/media/cb25acdc8e72139a43f581ea688ed552/href</a></iframe><p>And finally our main application’s endpoind.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f6ac6da7ab54d7904a48154eb660eab6/href">https://medium.com/media/f6ac6da7ab54d7904a48154eb660eab6/href</a></iframe><p>Run the Iris web server you’ve just created by executing go run main.go from your current path (%GOPATH%/src/%your_folder%/web/).</p><pre>$ go run main.go<br>Now listening on: <a href="http://localhost:8080">http://localhost:8080</a><br>Application Started. Press CTRL+C to shut down.<br>_</pre><p>Open one or more browser tabs at: <a href="http://localhost:8080">http://localhost:8080</a> and have fun!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VxYIRlnbAtMLn3GRAL6tHA.png" /></figure><h3>Download the Source Code</h3><p>The whole project, all the files you saw in this article are located at: <a href="https://github.com/kataras/iris/tree/master/_examples/tutorial/vuejs-todo-mvc">https://github.com/kataras/iris/tree/master/_examples/tutorial/vuejs-todo-mvc</a></p><h3>References</h3><p><a href="https://vuejs.org/v2/examples/todomvc.html">https://vuejs.org/v2/examples/todomvc.html</a> (using browser’s local storage)</p><p><a href="https://github.com/kataras/iris/tree/master/_examples/mvc">https://github.com/kataras/iris/tree/master/_examples/mvc</a> (mvc examples and features overview repository)</p><h3>Thank you, once again</h3><p>Happy new year and thank you for your pattience, once again:) Don’t hesitate to post any questions and provide feedback(I’m very active dev therefore you will be heard here!)</p><p>Don’t forget to check out my medium profile and twitter as well, I’m posting some (useful) stuff there too:)</p><ul><li><a href="https://medium.com/@kataras">https://medium.com/@kataras</a></li><li><a href="https://twitter.com/MakisMaropoulos">https://twitter.com/MakisMaropoulos</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5019ff870064" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/a-todo-mvc-application-using-iris-and-vue-js-5019ff870064">A Todo MVC Application using Iris and Vue.js</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>