Frodo

package
v0.0.0-...-74a8149 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 10, 2015 License: MIT Imports: 14 Imported by: 0

README

Frodo [Go Web Micro Framework]

Frodo is a Go mini web framework inspired by the sweet/beautiful parts that make up Laravel(php), Slim (php) and ExpressJS(node.js).

Looking for GoDocs Documentation

Hello World example:
package main

import (
    "net/http"
    "github.com/kn9ts/frodo"
)

func main()  {
    // Create a new instance of Frodo
    App := Frodo.New()

    // Add the root route
    App.Get("/", func(w http.ResponseWriter, r *Frodo.Request) {
        // https://www.youtube.com/watch?v=vjW8wmF5VWc
        w.Write([]byte("Hello World!!!"))
    })

    App.Serve() // Open in browser http://localhost:3102/
}
A big Hello world example:
package main

import (
	"net/http"
	"github.com/kn9ts/frodo"
	"github.com/username/project/filters"
	"github.com/username/project/controller"
	"gopkg.in/unrolled/render.v1"
)

func main()  {
	// Create a new instance of Frodo
	App := Frodo.New()

	// Yes, you can use the famous old render package to ender your views
	Response := render.New(render.Options{})

	// Add the root route
	App.Get("/", func(w http.ResponseWriter, r *Frodo.Request) {
		// https://www.youtube.com/watch?v=vjW8wmF5VWc
		w.Write([]byte("Hey, Watch Me Nae Nae!!!"))
	})

	// ------ Controller Awesomeness! ------
	// Passing a controller instead of a callback function, runs Index method by default
	App.Get("/home", &controller.Home{})

	// ----- Methods and Dynamic routes -----
	// You can declare which method in a controller should be called for the specified route
	// Oh yeah! you can name your routes eg. user-profile
	App.Post("/profile/{name}", &controller.Home{}, Frodo.Use{
		Method: "Profile",
		Name: "user-profile",
	})

	// ----- Multiple Methods -----
	// How about declaring more than one method to accept a specific Request, HELL YES!!!
	App.Match(Frodo.Methods{"GET", "POST"}, "/home", func(w http.ResponseWriter, r *Frodo.Request) {
		Response.HTML(w, http.StatusOK, "hello", nil)
	})

	App.AddFilters(filters.MiddleWare)
	App.Serve() // Open in browser http://localhost:3102/
}

Controllers

From the above example you can observe that Frodo can also accept controllers instead of the usual callback function passed. The controller used above route mapping would look as follows, placed in the controllers folder, the file name does not matter but the package name matters. It then should embed Frodo.Controller struct so as to inherit controller functionality.

Example of controller.Home{} used above would be:

package controller

import (
	"github.com/kn9ts/frodo"
	"net/http"
)

// Home is plays an example of a controller
type Home struct {
	Frodo.Controller
}

// Index is the default route handler for "/" route
func (h *Home) Index(w http.ResponseWriter, r *Frodo.Request) {
	w.Write([]byte("Hello world, a message from Home controller."))
}

func (h *Home) Profile(w http.ResponseWriter, r *Frodo.Request) {
	w.Write([]byte("Hey, Watch Me, " + r.Param("name") + ", Dougie from home controller."))
}

Middleware/Application Filters

Owh Yeah! Ofcourse you saw Filters or MiddleWare added just before we initialized the server. So you can create a folder named filter and declare your MiddleWare there, for example the above filter.MiddleWare would look like this when declared in a file inside the filters folder.

package filters

import (
	"github.com/kn9ts/frodo"
	"net/http"
)

// This is how a dev makes a Filter instance
var MiddleWare = Frodo.NewFilters()

func init() {

	// Adding application `Before` filters
	MiddleWare.Before(func(w http.ResponseWriter, r *Frodo.Request) {
		// Do something here
	})

	// Adding application `After` filters
	MiddleWare.After(func(w http.ResponseWriter, r *Frodo.Request) {
		// Do something here
	})

	// Adding route secific filters/middleware
	// pass the name of route pattern of the route you want to run the following middleware
	MiddleWare.Filter("user-profile", func(w http.ResponseWriter, r *Frodo.Request) {
		// do something here before the router named 'user-profile'
		// for example check if the name is 'Eugene'
		if r.Param("name") == "Eugene" {
			// Yes! the name passed in the params is Eugene, it has passed
		} else {
			// Name does not match. Do something if it has not passed
		}
	})

}

Release History

Version: 0.9.1 Preview

License

Copyright (c) 2014 Eugene Mutai Licensed under the MIT license

Documentation

Overview

Copyright © 2015 Eugene Mutai. All rights reserved.

Use of this source code is governed by the MIT License (MIT) license that can be found in the LICENSE file.

Frodo is a Go mini web framework inspired by the sweet/beautiful parts that make up Laravel(php), Slim (php) and ExpressJS(node.js).

Hello World example:

package main

import (
    "net/http"
    "github.com/kn9ts/frodo"
)

func main()  {
    // Create a new instance of Frodo
    App := Frodo.New()

    // Add the root route
    App.Get("/", func(w http.ResponseWriter, r *Frodo.Request) {
        w.Write([]byte("Expect the best but always prepare for the worst!!!"))
    })

    App.Serve() // Open in browser http://localhost:3102/
}

Index

Constants

This section is empty.

Variables

View Source
var MethodsAllowed = Methods{"GET", "POST", "PATCH", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"}

HTTP Methods/Verbs allowed

View Source
var UploadPath = "./assets/upload/"

UploadPath for now, declares the path to upload the files

Functions

This section is empty.

Types

type Controller

type Controller struct {
	Method, Layout string
}

Controller defines the basic structure of a REST application controller, the devs controller should embed this to create their own controllers. It then automatically implements ControllerInterface, and can be passed as a controller in routing

func (*Controller) Create

func (c *Controller) Create(w http.ResponseWriter, r *Request)

Create handles a request to Show the form for creating a new resource. * GET /posts/create

func (*Controller) Destroy

func (c *Controller) Destroy(w http.ResponseWriter, r *Request)

Destroy handles a request to Remove the specified resource from storage. * DELETE /posts/{id}

func (*Controller) Edit

func (c *Controller) Edit(w http.ResponseWriter, r *Request)

Edit handles a request to Show the form for editing the specified resource. * GET /posts/{id}/edit

func (*Controller) Head

func (c *Controller) Head(w http.ResponseWriter, r *Request)

Head handle HEAD request.

func (*Controller) Index

func (c *Controller) Index(w http.ResponseWriter, r *Request)

Index is the default handler for any incoming request or route's request that is not matched to it's handler It can also be used for specific route, mostly for the root routes("/")

func (*Controller) NotFound

func (c *Controller) NotFound(w http.ResponseWriter, r *Request)

NotFound can be customised to be used as an alternative thus run your own custom handles eg. Redirect the user to a 404 page, or rooot page

func (*Controller) Options

func (c *Controller) Options(w http.ResponseWriter, r *Request)

Options handle OPTIONS request.

func (*Controller) Patch

func (c *Controller) Patch(w http.ResponseWriter, r *Request)

Patch is an alternative to Update

func (*Controller) Show

func (c *Controller) Show(w http.ResponseWriter, r *Request)

Show handles a request to Display the specified resource. * GET /posts/{id}

func (*Controller) Store

func (c *Controller) Store(w http.ResponseWriter, r *Request)

Store handles a request to Store a newly created resource in storage. * POST /posts

func (*Controller) Update

func (c *Controller) Update(w http.ResponseWriter, r *Request)

Update handles a request to update the specified resource in storage. * PUT /posts/{id}

type ControllerInterface

type ControllerInterface interface {
	Index(http.ResponseWriter, *Request)
	Create(http.ResponseWriter, *Request)
	Store(http.ResponseWriter, *Request)
	Show(http.ResponseWriter, *Request)
	Edit(http.ResponseWriter, *Request)
	Update(http.ResponseWriter, *Request)
	Patch(http.ResponseWriter, *Request)
	Destroy(http.ResponseWriter, *Request)
	Head(http.ResponseWriter, *Request)
	Options(http.ResponseWriter, *Request)
	NotFound(http.ResponseWriter, *Request)
	// contains filtered or unexported methods
}

ControllerInterface will be used to parse back the developer's controller back to it's own type. Since we know that a REST controller entails the following methods then any struct that implements the Controller methods suffices the ControllerInterface

type CustomHandle

type CustomHandle struct {
	Name    string
	Handle  HandleFunc
	IsRoute bool
}

CustomHandle is for filter Middleware, belong to a method or route Reminder:

type HandleFunc func(http.ResponseWriter, *http.Request, Params)

type Handle

type Handle interface{}

Handle should be able to carry a HandleFunc or a Controller thus only both can satisfy an interface

type HandleFunc

type HandleFunc func(http.ResponseWriter, *Request)

HandleFunc is a function that can be registered to a route to handle HTTP requests. http.Request is now fused with Params, Inputs and Uploads custom handlers these are Facades to handle common request processing cases eg. saving a file

type Logger

type Logger struct {
	FilePath, FileName string
	LogFile            *log.Logger
	// contains filtered or unexported fields
}

Logger embeds the standard library's `*log.Logger` to handle all logs

var Log *Logger

Log becomes the global var that handles Frodo's logging

func (*Logger) Alert

func (console *Logger) Alert(format string, args ...interface{})

Alert can be used to log Alerts, maybe on certain events (Magenta background, white text).

func (*Logger) Critical

func (console *Logger) Critical(format string, args ...interface{})

Critical can be used to log system wide Critical information that needs to be fixed immediately (Red background and white text)

func (*Logger) Debug

func (console *Logger) Debug(format string, args ...interface{})

Debug logs debug information

func (*Logger) Dump

func (console *Logger) Dump()

Dump simply does just that. Dumps all the logging that has been collected by the buffer to the output

func (*Logger) Error

func (console *Logger) Error(format string, args ...interface{})

Error can be used to log Errors(red in color).

func (*Logger) Fatal

func (console *Logger) Fatal(format string, args ...interface{})

Fatal is similar to `Frodo.Log.Error` but panics after logging

func (*Logger) Info

func (console *Logger) Info(format string, args ...interface{})

Info can be used to log informative information of the application

func (*Logger) Initialise

func (console *Logger) Initialise()

Initialise checks if a logging instance exists, if not starts one

func (*Logger) SetLevel

func (console *Logger) SetLevel(option string)

SetLevel enables the user to select a LOG LEVEL for the app to monitor the app

func (*Logger) Success

func (console *Logger) Success(format string, args ...interface{})

Success can be used to log information on successful transactions(logs in green)

func (*Logger) Warn

func (console *Logger) Warn(format string, args ...interface{})

Warn can be used to log meaningful and light errors/bugs that might want to be checked later

func (*Logger) WriteToFile

func (console *Logger) WriteToFile(fl ...interface{}) (*log.Logger, error)

WriteToFile prompts all logs to be written to a file if not already enabled

type Methods

type Methods []string

Methods type is used in Match method to get all methods user wants to apply that will help in invoking the related handler

type Middleware

type Middleware struct {
	BeforeMiddleware, AfterMiddleware []HandleFunc
	FilterMiddleware                  []CustomHandle
}

Middleware refers to a chain of handlers that wrap around the web app adding extra functionality eg. authenticate user, redirect guest visits, compress response content, rate limit requests, log application events. This struct splits them into Before, After or Filter(route specific) middlware for requests received

func NewFilters

func NewFilters() *Middleware

NewFilters creates a new (pointer)Middleware instance

func (*Middleware) After

func (m *Middleware) After(h HandleFunc)

After adds application wide Middleware that run after the controller specified before giving back a response

func (*Middleware) Before

func (m *Middleware) Before(h HandleFunc)

Before adds application wide Middleware that run as soon as request comes in

func (*Middleware) Filter

func (m *Middleware) Filter(name string, h HandleFunc)

Filter adds Middleware that will be special to an application route that runs after before middlware, and before the developer's route specific handler

type MiddlewareResponseWriter

type MiddlewareResponseWriter struct {
	http.ResponseWriter
	// contains filtered or unexported fields
}

MiddlewareResponseWriter is used to hijack/embed http.ResponseWriter thus making it satisfy the ResponseWriter interface, we then add a written boolean property to trace when a write made, with a couple of other helpful properties

func (*MiddlewareResponseWriter) Write

func (w *MiddlewareResponseWriter) Write(bytes []byte) (int, error)

Write writes data back the client/creates the body

func (*MiddlewareResponseWriter) WriteHeader

func (w *MiddlewareResponseWriter) WriteHeader(code int)

WriteHeader is in charge of building the Header file and writing it back to the client

type Request

type Request struct {
	*http.Request
	// contains filtered or unexported fields
}

Request type carrys all the http.Request values, and params in curly {} brackets that are translated from url param values to ready-to-be-used values in route specific Handler function

func (*Request) GetParam

func (r *Request) GetParam(name string) string

GetParam returns the value of the first Param which key matches the given name. If no matching Param is found, an empty string is returned.

func (*Request) HasFile

func (r *Request) HasFile(name string) bool

HasFile mimics FormFile method from `http.Request`

func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error)

func (*Request) HasInput

func (r *Request) HasInput(name string) bool

HasInput checks for the existence of the given input name in the inputs sent from a FORM

func (*Request) Input

func (r *Request) Input(name string) interface{}

Input gets ALL key/values sent via POST from all methods. Keep in mind `r.Form == type url.Values map[string][]string`

func (*Request) InputFile

func (r *Request) InputFile(name string) (*UploadFile, error)

InputFile gets the file requested that was uploaded

func (*Request) InputFiles

func (r *Request) InputFiles(name string) []*UploadFile

InputFiles parses all uploaded files and creates an array of UploadFile type representing each uploaded file

func (*Request) IsAjax

func (r *Request) IsAjax() bool

IsAjax checks if the Request was made via AJAX, the XMLHttpRequest will usually be sent with a X-Requested-With HTTP header.

func (*Request) IsXhr

func (r *Request) IsXhr() bool

IsXhr gives user a choice in whichever way he/she feels okay checking for AJAX Request It actually calls r.IsAjax()

func (*Request) MoveAll

func (r *Request) MoveAll(args ...interface{}) (bool, int)

MoveAll is a neat trick to upload all the files that have been parsed. Awesome for bulk uploading, and storage.

func (*Request) Param

func (r *Request) Param(name string) string

Param is shorter equivalent of `GetParam` method

func (*Request) SetParam

func (r *Request) SetParam(name, value string) bool

SetParam adds a key/value pair to the Request params

type Router

type Router struct {
	Middleware
	NotFoundHandle, MethodNotAllowedHandle, PanicHandle HandleFunc
	// contains filtered or unexported fields
}

Router is a http.Handler which can be used to dispatch requests to different handler functions via configurable routes

func New

func New() *Router

New is the short method to create a new Frodo application instance

func (*Router) AddFilters

func (r *Router) AddFilters(m *Middleware)

AddFilters adds `Middlewares` to routes, requests and responses

func (*Router) All

func (r *Router) All(args ...interface{})

All method adds the Handle to all Methods/HTTPVerbs for a given route

func (*Router) Assets

func (r *Router) Assets(pattern, assetDir string)

Assets can be used instead of ServeFiles though internally it uses ServeFiles() since they do the same thing

func (*Router) BadMethod

func (r *Router) BadMethod(handler HandleFunc)

BadMethod can be used to define custom routes to handle Methods that are not allowed

func (*Router) Delete

func (r *Router) Delete(args ...interface{})

Delete is a shortcut for router.addHandle("DELETE", args...)

func (*Router) Get

func (r *Router) Get(args ...interface{})

Get is a shortcut for router.addHandle("GET", args...)

func (*Router) Handler

func (r *Router) Handler(method, path string, handler http.Handler)

Handler is an adapter which allows the usage of an http.Handler as a request handle.

func (*Router) HandlerFunc

func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc)

HandlerFunc is an adapter which allows the usage of an http.HandlerFunc as a request handle. Stolen idea from 'httprouter'

func (*Router) Head

func (r *Router) Head(args ...interface{})

Head is a shortcut for router.addHandle("HEAD", args...)

func (*Router) Match

func (r *Router) Match(httpVerbs Methods, args ...interface{})

Match adds the Handle to the provided Methods/HTTPVerbs for a given route EG. GET/POST from /home to have the same Handle

func (*Router) NotFound

func (r *Router) NotFound(handler HandleFunc)

NotFound can be used to define custom routes to handle NotFound routes

func (*Router) On404

func (r *Router) On404(handler HandleFunc)

On404 is shortform for NotFound

func (*Router) On500

func (r *Router) On500(handler HandleFunc)

On500 is shortform for ServerError

func (*Router) Options

func (r *Router) Options(args ...interface{})

Options is a shortcut for router.addHandle("OPTIONS", args...)

func (*Router) Patch

func (r *Router) Patch(args ...interface{})

Patch is a shortcut for router.addHandle("PATCH", args...)

func (*Router) Post

func (r *Router) Post(args ...interface{})

Post is a shortcut for router.addHandle("POST", args...)

func (*Router) Put

func (r *Router) Put(args ...interface{})

Put is a shortcut for router.addHandle("PUT", args...)

func (*Router) Serve

func (r *Router) Serve()

Serve deploys the application Default port is 3102, inspired by https://en.wikipedia.org/wiki/Fourth_Age The "Fourth Age" followed the defeat of Sauron and the destruction of his One Ring, but did not officially begin until after the Bearers of the Three Rings left Middle-earth for Valinor, the 'Uttermost West'

func (*Router) ServeFiles

func (r *Router) ServeFiles(pattern, assetDir string)

ServeFiles serves files from the given file system root. TODO: Be able to add a list of file types, and names that should not be served

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP is the function that receives all requests, and process them for our router by using it we are implementing the http.Handler and thus can use our own ways to handle incoming requests and process them

func (*Router) ServeOnPort

func (r *Router) ServeOnPort(portNumber interface{})

ServeOnPort is to used if you plan change the port to serve the application on

func (*Router) ServerError

func (r *Router) ServerError(handler HandleFunc)

ServerError can be used to define custom routes to handle OnServerError routes

func (*Router) Static

func (r *Router) Static(pattern, assetDir string)

Static can be used instead of Assets, ServeFiles though internally it uses ServeFiles() since they do the same thing

type UploadFile

type UploadFile struct {
	multipart.File
	*multipart.FileHeader
}

UploadFile struct/type is the data that makes up an uploaded file once it is recieved and parsed eg. using request.FormFile()

func (*UploadFile) Extension

func (file *UploadFile) Extension() string

Extension returns the extension of the file uploaded

func (*UploadFile) IsValid

func (file *UploadFile) IsValid() bool

IsValid checks if the file is alright by opening it up if errors come up while opening it is an invalid upload

func (*UploadFile) MimeType

func (file *UploadFile) MimeType() string

MimeType returns the mime/type of the file uploaded

func (*UploadFile) Move

func (file *UploadFile) Move(args ...interface{}) bool

Move basically moves/transfers the uploaded file to the upload folder provided

  • Using ...interface{} because I want the user to only pass more than one argument
  • when changing upload dir and filename, if none is changed then defaults are used *
  • eg. file.Move(true)
  • ----- or -----
  • file.Move("../new_upload_path/", "newfilename.png")

func (*UploadFile) Name

func (file *UploadFile) Name() string

Name returns the name of the file when it was uploaded

func (*UploadFile) Size

func (file *UploadFile) Size() int64

Size returns the size of the file in question

type Use

type Use struct {
	Method, Name string
	Filter       string
	Meta         map[string]interface{}
}

Use will be used in conjuction with routing for further sugar in the Routing system It defines the Method to be used if the Handle is a Controller Filter[string, name of filter] can also be related to the route and run in this specified route only in every incoming requests

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL