Goku

Golang Web Mvc Framework

View the Project on GitHub qleelulu/goku

Router

Routes map incoming requests for URLs to a Controller and Action. They also are used to construct an URL to a Controller/Action.

Map Route

You can map route by this two ways:

var Routes []*goku.Route = []*goku.Route{
    &goku.Route{
        Name:     "static",
        IsStatic: true,
        Pattern:  "/public/(.*)",
    },
    &goku.Route{
        Name:       "edit",
        Pattern:    "/{controller}/{id}/{action}",
        Default:    map[string]string{"action": "edit"},
        Constraint: map[string]string{"id": "\\d+"},
    },
    &goku.Route{
        Name:    "default",
        Pattern: "/{controller}/{action}",
        Default: map[string]string{"controller": "todo", "action": "index"},
    },
}
// create server with the rules
rt := &goku.RouteTable{Routes: todo.Routes}
s := goku.CreateServer(rt, nil, nil)
log.Fatal(s.ListenAndServe())

or

rt := new(goku.RouteTable)
rt.Static("staticFile", "/static/(.*)")
rt.Map(
    "blog-page", // route name
    "/blog/p/{page}", // pattern
    map[string]string{"controller": "blog", "action": "page", "page": "0"}, // default
    map[string]string{"page": "\\d+"} // constraint
)
rt.Map(
    "default", // route name
    "/{controller}/{action}", // pattern
    map[string]string{"controller": "home", "action": "index"}, // default
)

Static File Route

When a route set IsStatic to true, if a url matched this route, the request will process as static file. Such as JS, CSS file.

In production environment, i suggest you proxy the static files with Nginx.

URL Patterns

A URL pattern can contain literal values and variable placeholders (referred to as URL parameters). The literals and placeholders are located in segments of the URL which are delimited by the slash (/) character.

When a request is made, the URL is parsed into segments and placeholders, and the variable values are provided to the request handler. This process is similar to the way the data in query strings is parsed and passed to the request handler. In both cases variable information is included in the URL and passed to the handler in the form of key-value pairs. For query strings both the keys and the values are in the URL. For routes, the keys are the placeholder names defined in the URL pattern, and only the values are in the URL.

In a URL pattern, you define placeholders by enclosing them in braces ( { and } ). You can define more than one placeholder in a segment, but they must be separated by a literal value. For example, {language}-{country}/{action} is a valid route pattern. However, {language}{country}/{action} is not a valid pattern, because there is no literal value or delimiter between the placeholders. Therefore, routing cannot determine where to separate the value for the language placeholder from the value for the country placeholder.

The following table shows valid route patterns and examples of URL requests that match the patterns.

Route definitionExample of matching URL
{controller}/{action}/{id}/Products/show/beverages
{table}/Details.html/Products/Details.html
blog/{action}/{entry}/blog/show/123
{reporttype}/{year}/{month}/{day}/sales/2008/1/5
{locale}/{action}/US/show
{language}-{country}/{action}/en-US/show

Setting Default Values for URL Parameters

When you define a route, you can assign a default value for a parameter. The default value is used if a value for that parameter is not included in the URL. You set default values for a route by assigning a map to the Defaults property of the Route struct. The following example shows how to add a route that has default values, by using the MapPageRoute(String, String, String, Boolean, RouteValueDictionary) method.

var Routes []*goku.Route = []*goku.Route{
    &goku.Route{
        Name:    "default",
        Pattern: "Category/{action}/{categoryName}",
        Default: map[string]string{
            "controller": "category", "action": "show", "categoryName":"food"
        },
    }
}

When goku routing handles a URL request, the route definition shown in the example (with default values of food for categoryName and show for action) produces the results that are listed in the following table.

URLParameter values
/Categoryaction = “show” (default value)
categoryName = “food” (default value)
/Category/addaction = “add”
categoryName = “food” (default value)
/Category/add/beveragesaction = “add”
categoryName= “beverages”

Adding Constraints to Routes

In addition to matching a URL request to a route definition by the number of parameters in the URL, you can specify that values in the parameters meet certain constraints. If a URL contains values that are outside the constraints for a route, that route is not used to handle the request. You add constraints to make sure that the URL parameters contain values that will work in your application.

Constraints are defined by using regular expressions. You add constraints for a route by assigning a map to the Constraint property of the Route struct, or add by RouteTable.Map()

var Routes []*goku.Route = []*goku.Route{
    &goku.Route{
        Name:       "post-list",
        Pattern:    "whatever/{locale}/{year}",
        Constraint: map[string]string{
            "locale": "[a-z]{2}-[a-z]{2}", "year": "\\d{4}"
        },
    },
}

// or

rt := new(goku.RouteTable)
rt.Map(
    "post-list", // route name
    "whatever/{locale}/{year}", // pattern
    map[string]string{"controller": "post", "action": "show"}, // default
    map[string]string{ // constraint
        "locale": "[a-z]{2}-[a-z]{2}", "year": "\\d{4}"
    }
)

When routing handles a URL request, the route definition shown in the previous example produces the results that are listed in the following table.

URLResult
/en-usNo match.
Both locale and year are required.
/en-us/08No match.
The constraint on year requires 4 digits.
/en-us/2008locale = “en-us”
year = “2008”

If default value not set, that mean the parameter is required.

Route Data

For the Pattern Category/{action}/{categoryName}, and a URL /Category/add/beverages, you can get the categoryName parameter in the controller action by HttpContext:

// ctx is HttpContext
categoryName := ctx.RouteData.Params["categoryName"]
// categoryName == beverages

TODO

  • Construct URLs from Routes