Skip to main content

Gin Redirects

When building web applications, you often need to redirect users from one URL to another. This could be after form submissions, authentication, or when resources have moved. Gin provides simple and powerful ways to handle these redirects in your Go web applications.

Understanding Redirects

A redirect is an HTTP response with a special status code (usually 301, 302, 303, or 307) and a Location header that tells the browser to navigate to a different URL. In Gin, you can implement redirects easily using built-in methods.

Basic Redirect Methods in Gin

Gin offers several methods for handling redirects:

1. Redirect() Method

The most common way to perform a redirect is using the Redirect() method:

go
func handleRedirect(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "https://example.com")
}

This example redirects the user to "https://example.com" with a 301 (Moved Permanently) status code.

The Redirect() method takes two parameters:

  • HTTP status code (indicating the type of redirect)
  • Target URL (where to redirect the user)

2. RedirectToAction() Method

Gin also allows you to redirect to another handler (route) within your application:

go
func redirectToProfile(c *gin.Context) {
// Get the user ID from request or session
userID := "123"
c.Redirect(http.StatusFound, "/users/"+userID)
}

Common Redirect Status Codes

Choosing the right status code for your redirect is important:

Status CodeNameUse Case
301Moved PermanentlyResource has permanently moved to a new URL
302FoundTemporary redirect (default in many frameworks)
303See OtherUsed after POST to redirect to a GET resource
307Temporary RedirectLike 302, but guarantees method won't change
308Permanent RedirectLike 301, but guarantees method won't change

Example with Different Status Codes:

go
func redirectHandler(c *gin.Context) {
redirectType := c.Query("type")

switch redirectType {
case "permanent":
c.Redirect(http.StatusMovedPermanently, "/new-page") // 301
case "post-redirect":
c.Redirect(http.StatusSeeOther, "/success") // 303
default:
c.Redirect(http.StatusFound, "/default-page") // 302
}
}

Relative vs Absolute URLs

Gin supports both relative and absolute URLs for redirects:

go
// Relative URL (within the same domain)
c.Redirect(http.StatusFound, "/dashboard")

// Absolute URL (to a different domain)
c.Redirect(http.StatusFound, "https://example.com/page")

When using relative URLs, Gin automatically resolves them based on the current request's domain.

Practical Examples

1. Redirect After Form Submission

A common pattern is redirecting after a form submission to prevent duplicate submissions:

go
func createArticle(c *gin.Context) {
// Get form data
title := c.PostForm("title")
content := c.PostForm("content")

// Save to database
articleID := saveArticleToDatabase(title, content)

// Redirect to the newly created article
c.Redirect(http.StatusSeeOther, "/articles/"+articleID)
}

2. Authentication Redirect

Redirecting unauthenticated users to a login page:

go
func requireAuth() gin.HandlerFunc {
return func(c *gin.Context) {
// Check if user is authenticated
if !isAuthenticated(c) {
// Save the original URL they were trying to access
returnURL := c.Request.URL.Path
c.Redirect(http.StatusFound, "/login?return="+returnURL)
c.Abort() // Stop execution of subsequent handlers
return
}
c.Next() // Continue to the next handler
}
}

// Usage
router.GET("/profile", requireAuth(), profileHandler)

3. URL Shortener

A simple URL shortener implementation using redirects:

go
func setupRouter() *gin.Engine {
router := gin.Default()

// URL database (in a real app, this would be in a database)
urlMap := map[string]string{
"go": "https://golang.org",
"gin": "https://github.com/gin-gonic/gin",
"docs": "https://gin-gonic.com/docs/",
}

// Handle short URLs
router.GET("/s/:code", func(c *gin.Context) {
code := c.Param("code")

if target, exists := urlMap[code]; exists {
c.Redirect(http.StatusMovedPermanently, target)
return
}

c.String(http.StatusNotFound, "Short URL not found")
})

return router
}

PRG Pattern: Post/Redirect/Get

The PRG (Post/Redirect/Get) pattern is a web development design pattern that prevents duplicate form submissions. Gin makes implementing this pattern straightforward:

go
func handleForm(c *gin.Context) {
if c.Request.Method == "POST" {
// Process the form data
name := c.PostForm("name")
email := c.PostForm("email")

// Save to database
userID := saveUser(name, email)

// Redirect to a confirmation page (GET request)
c.Redirect(http.StatusSeeOther, "/registration-success?id="+userID)
return
}

// If not a POST request, display the form
c.HTML(http.StatusOK, "form.html", nil)
}

The HTTP 303 (See Other) status code is specifically designed for this pattern.

Complete Example Application

Here's a more complete example showing different redirect scenarios in a Gin application:

go
package main

import (
"net/http"
"github.com/gin-gonic/gin"
)

func main() {
router := gin.Default()

// Basic redirect
router.GET("/old-page", func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "/new-page")
})

// Target of the redirect
router.GET("/new-page", func(c *gin.Context) {
c.String(http.StatusOK, "This is the new page")
})

// External redirect
router.GET("/external", func(c *gin.Context) {
c.Redirect(http.StatusFound, "https://golang.org")
})

// Form handling with PRG pattern
router.GET("/contact", showContactForm)
router.POST("/contact", handleContactForm)
router.GET("/thank-you", func(c *gin.Context) {
name := c.Query("name")
c.HTML(http.StatusOK, "thank-you.html", gin.H{
"name": name,
})
})

router.Run(":8080")
}

func showContactForm(c *gin.Context) {
c.HTML(http.StatusOK, "contact.html", nil)
}

func handleContactForm(c *gin.Context) {
name := c.PostForm("name")
email := c.PostForm("email")
message := c.PostForm("message")

// Save to database...
saveContactMessage(name, email, message)

// Redirect to thank you page
c.Redirect(http.StatusSeeOther, "/thank-you?name="+name)
}

func saveContactMessage(name, email, message string) {
// In a real application, save to database
// This is just a placeholder
}

Summary

Redirects are a fundamental part of web applications, and Gin provides straightforward methods to implement them:

  • Use the c.Redirect() method with appropriate status codes
  • Choose the right status code for your use case (301, 302, 303, 307, 308)
  • Implement patterns like PRG to create better user experiences
  • You can redirect to both relative and absolute URLs

Mastering redirects in Gin will help you build more robust web applications with better user flows and improved SEO.

Exercises

  1. Create a simple URL shortener that redirects short codes to full URLs
  2. Implement a login system that redirects users back to their originally requested page after authentication
  3. Build a form that uses the PRG pattern to avoid duplicate submissions
  4. Create a route that randomly redirects to one of several possible destinations

Additional Resources

Understanding redirects is essential for creating modern web applications with smooth user experiences and proper handling of form submissions and authentication flows.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)