rubik

package module
v0.2.6 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2020 License: Apache-2.0 Imports: 30 Imported by: 7

README

Rubik

An efficient, scalable Web Framework

Homepage - API Documentation

For writing REST client and server-side applications faster. It provides a pluggable layer of abstraction over net/http and enables automation of development environment through extensive tooling.

Even though the goal of Rubik is set it'll take a lot of time to achieve it, that being said you must not use this framework for any production use yet. There can be a lot of edge cases missed and bug fixes beyond the grasps which needs to be fixed before it is production ready.

Framework Components
Quickstart
  • Install Rubik CLI (supports Linux and OSX 64-bit versions only)
curl https://rubik.ashishshekar.com/install | sh
  • Create a new project
okrubik new hello-world
  • Change directory to your project name & run the project
cd hello-world
okrubik run
Questions

Co-ordination with suggestions, opinions and questions can be done through this
Mailing list

Contributing

We encourage you to read this Contributing to Rubik Guidelines for ensuring smooth development flow.

Core Goals
  • Make Rubik fun to work with!
  • Provide a great tooling for Rubik
  • Make client-server development easier in Go
  • Concurrent messgage passing
Things Rubik can't do yet

Here is the list of things that rubik can't do yet and needs fixing/development in these areas.

License

Rubik is released under the Apache 2.0 License

Documentation

Overview

Package rubik is used for accessing Rubik Framework: a minimal and efficient web framework for Go and it's APIs.

Running an empty server:

package main

import r "github.com/rubikorg/rubik"

func main() {
	// this runs Rubik server on port: 8000
	panic(r.Run())
}

Adding a route:

package main

import r "github.com/rubikorg/rubik"

func main() {
	// this runs Rubik server on port: 8000
	index := rubik.Route{
		Path: "/",
		Controller: func (req *r.Request) { req.Respond("This is a text response") },
	}
	rubik.UseRoute(index)
	panic(r.Run())
}

Index

Examples

Constants

View Source
const (
	// GET method
	GET = "GET"
	// POST method
	POST = "POST"
	// PUT method
	PUT = "PUT"
	// DELETE method
	DELETE = "DELETE"
)
View Source
const (
	// Version of rubik
	Version = "0.2.5"
)

Variables

View Source
var Content = struct {
	Header     string
	JSON       string
	Text       string
	HTML       string
	URLEncoded string
	Multipart  string
}{
	"Content-Type",
	"application/json",
	"text/plain",
	"text/html",
	"application/x-www-form-urlencoded",
	"multipart/form-data",
}

Content is a struct that holds default values of Content-Type headers it can be used throughout your rubik application for avoiding basic spell mistakes

View Source
var Dispatch = MessagePasser{
	Message: make(chan Message),
	Error:   make(chan error),
}

Dispatch is topic dispatcher of rubik server

View Source
var Storage = StorageContainer{
	// contains filtered or unexported fields
}

Storage is the Container Access of your storage/ folder

View Source
var StringByteTypeMap = map[string]ByteType{
	"json": Type.JSON,
	"html": Type.HTML,
	"text": Type.Text,
}
View Source
var Type = struct {
	HTML         ByteType
	JSON         ByteType
	Text         ByteType
	Bytes        ByteType
	templateHTML ByteType
	templateText ByteType
}{1, 2, 3, 4, 5, 6}

Type is a rubik type literal used for indication of response/template types

Functions

func AfterRequest

func AfterRequest(h RequestHook)

AfterRequest is used to execute the request hook h after completion of the request. A request is said to be complete only after the response is written through http.ResponseWriter interface of http.Server.

func Attach

func Attach(symbol string, b Block)

Attach a block to rubik tree

func AttachAfter

func AttachAfter(symbol string, b Block)

AttachAfter attaches blocks after boot sequence of routes are complete

func BeforeRequest

func BeforeRequest(h RequestHook)

BeforeRequest is used to execute the request hook h. When a request is sent on a certain route the hook specified as h is executed in a separate goroutine without hindering the current main goroutine of request.

func E

func E(msg string) error

E wraps the message into an error interface and returns it. This method can be used in your controller for throwing error response.

NOTE: this error is not stdlib errors package this is pkg/errors error wrapper

Example
package main

import (
	"github.com/rubikorg/rubik"
)

func main() {
	r := rubik.Route{
		Path: "/test",
		Controller: func(req *rubik.Request) {
			req.Throw(403, rubik.E("invalid token or something"))
		},
	}
	rubik.UseRoute(r)
}
Output:

func GetConfig

func GetConfig() interface{}

GetConfig returns the injected config from the Load method

func GetStorageContainers

func GetStorageContainers() []string

GetStorageContainers returns the names of containers present in your storage/ folder. You can access them by calling `Storage.Access` API and use Get or Put to work with your files.

func Load

func Load(config interface{}) error

Load method loads the config/RUBIK_ENV.toml file into the interface given

func Plug added in v0.2.5

func Plug(ext ExtensionBlock)

Plug adds an extension of Rubik to your workflow

func Run

func Run() error

Run will make sure all dependencies are met, resolves config and it's conflicts with respect to the RUBIC_ENV passed while executing. It boots all your blocks, middlewares message passing channels and port resolution; before starting the server. If this method does not find PORT that is passed as the first argument or the config/*RUBIC_ENV.toml then it startes at :8000.

func SetNotFoundHandler

func SetNotFoundHandler(h http.Handler)

SetNotFoundHandler sets custom 404 handler

func Use

func Use(router Router)

Use ...

func UseRoute

func UseRoute(route Route)

UseRoute is like rubik.Use() but attaches your route to the index Router

Types

type App

type App struct {
	CurrentURL string
	RouteTree
	// contains filtered or unexported fields
}

App is a sandboxed object used by the external blocks of code to access some risk-free part of your rubik server For example: App do not have full access to your project config but it has the ability to decode the config that it needs for only this block of code to work

func (*App) Config

func (sb *App) Config(name string) interface{}

Config get config by name

func (*App) Decode

func (sb *App) Decode(name string, target interface{}) error

Decode decodes the internal rubik server config into the struct that you provide. It returns error if the config is not unmarshalable OR there if there is no config initialized by the given name parameter

type Assertion added in v0.2.5

type Assertion func(interface{}) error

Assertion is the assert functions for rubiks validation cycle it should return a message stating why validation failed and bool indicating if assertion has passed or not

type BlankRequestEntity

type BlankRequestEntity struct {
	Entity
}

BlankRequestEntity ...

type Block

type Block interface {
	OnAttach(*App) error
}

Block is an interface that can be implemented to provide extended functionalities to rubik server Think of it as a plugin which can be attached to the rubik server and can be accessible throughout the lifecycle of rubik server.

A Block can also be thought of as a dependency injected plugin and can be accessed in your controllers by calling rubik.GetBlock('BLOCK_NAME'). Blocks requires you to implement a method called OnAttach. This method is called during rubik server bootstrapper is run and requires you to return an error if any complexity arrises in for your block to function

func GetBlock

func GetBlock(symbol string) Block

GetBlock returns the block that is attached to rubik represented by the symbol supplied as the parameter

type ByteResponse

type ByteResponse struct {
	Status int
	Data   interface{}
	OfType ByteType
	Error  error
	// contains filtered or unexported fields
}

ByteResponse is the response of rubik server

func RenderContent

func RenderContent(btype ByteType, vars interface{}, paths ...string) ByteResponse

RenderContent returns you the response bytes of the target paths that is going to be written on the wire. It is an abstraction of Render method which is used as a layered method inside Render method.

type ByteType

type ByteType int

ByteType let's rubik know what type of bytes to send as response

type Claims added in v0.2.5

type Claims interface{}

Claims populates the JWT.MapClaims inteface

type Client

type Client struct {
	Debug       bool
	JWTSecret   string
	BasicSecret string
	BearerName  string
	UserAgent   string
	// contains filtered or unexported fields
}

Client is the implementation for rubik project to create a common abstraction of HTTP calls by passing defined entity

func NewClient

func NewClient(baseURL string, timeout time.Duration) *Client

NewClient creates a new instance of ink client

func (*Client) Delete

func (c *Client) Delete(entity interface{}) (Response, error)

Delete ...

func (*Client) Download

func (c *Client) Download(entity DownloadRequestEntity) ([]byte, error)

Download method downloads file from an url from your specified Entity->Route to TargetFilePath passed to the entity

func (*Client) Get

func (c *Client) Get(entity interface{}) (Response, error)

Get ...

func (*Client) Post

func (c *Client) Post(entity interface{}) (Response, error)

Post ...

func (*Client) Put

func (c *Client) Put(entity interface{}) (Response, error)

Put ...

type Communicator

type Communicator interface {
	Send(string, interface{}) error
}

Communicator interface is used to handle the service/driver that rubik's inherent communication depends upon

type Controller

type Controller func(*Request)

Controller ...

func Ctls added in v0.2.5

func Ctls(ctls ...Controller) []Controller

Ctls adds the controllers one in the order of parameters passed and feeds them to the bootloader

func Proxy

func Proxy(url string) Controller

Proxy does not redirect your current resource locator but makes an internal GET call to the specified URL to serve it's response as your own

func Render

func Render(btype ByteType, vars interface{}, paths ...string) Controller

Render returns a mixin holding the data to be rendered on the web page or sent over the wire

func UseHandler

func UseHandler(handler http.Handler) Controller

UseHandler converts any http,Handler into rubik.Controller

func UseHandlerFunc

func UseHandlerFunc(fn http.HandlerFunc) Controller

UseHandlerFunc converts any http,HandlerFunc into rubik.Controller

func UseIntermHandler

func UseIntermHandler(intermHandler func(http.Handler) http.Handler) Controller

UseIntermHandler converts any func(http,Handler) http,Handler into rubik.Controller

type DownloadRequestEntity

type DownloadRequestEntity struct {
	Entity
	TargetFilePath string
}

DownloadRequestEntity ...

type Entity

type Entity struct {
	PointTo string
	Params  []string

	FormData   bool
	URLEncoded bool
	JSON       bool
	Infer      interface{}
	Cookies    Values
	// contains filtered or unexported fields
}

Entity holds the data for a single API call It lets you write consolidated clean Go code

type ExtensionBlock added in v0.2.5

type ExtensionBlock interface {
	OnPlug(*App) error
	Name() string
}

ExtensionBlock is executed plugins when RUBIK_ENV = ext. Blocks which requires access to server but does need the server to run. To run your extention block use `okrubik run --ext`

type File

type File struct {
	Path   string
	OSFile *os.File
	Raw    []byte
}

File used by ink to embbed file

type FileStore

type FileStore struct {
	Name string
	// contains filtered or unexported fields
}

FileStore lets you perform CRUD on files of StorageContainer FileStore returns the name of container you are accessing by Name field

func (FileStore) Delete

func (fs FileStore) Delete(file string) error

Delete a file from the FileStore, returns error

func (FileStore) Get

func (fs FileStore) Get(file string) []byte

Get a file from this FileStore, returs byte slice

func (FileStore) GetFile

func (fs FileStore) GetFile(file string) *os.File

GetFile returns pointer to os.File for passing it into the rubikClient using File{}.OSFile = return value of this function Other usage may be to obtain file metadata stored

func (FileStore) Has

func (fs FileStore) Has(file string) bool

Has checks if the file by given name is present inside this FileStore

func (FileStore) Put

func (fs FileStore) Put(file string, content []byte) error

Put a file inside this FileStore given the content as parameter

type HookContext

type HookContext struct {
	Request  *http.Request
	Ctx      map[string]interface{}
	Response []byte
	Status   int
}

HookContext ...

type Message

type Message struct {
	Communicator string
	Topic        string
	Body         interface{}
}

Message that is to be sent in communicator channel

type MessagePasser

type MessagePasser struct {
	Message chan Message
	Error   chan error
}

MessagePasser holds the channels for communication with rubik server

type Payload

type Payload struct {
	// contains filtered or unexported fields
}

Payload holds the data between the intermediate state of Client and PostProcessor

func (*Payload) Cancel

func (r *Payload) Cancel()

Cancel ...

type RResponseWriter

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

RResponseWriter is Rubik's response writer that implements http.ResponseWriter and it's methods to provide additional functionalities related to Rubik.

func (*RResponseWriter) Write

func (w *RResponseWriter) Write(b []byte) (int, error)

Write writes the response bytes b to the wire

func (*RResponseWriter) WriteHeader

func (w *RResponseWriter) WriteHeader(status int)

WriteHeader writes the http.Request's Header values to the wire and sets the status given as the parameter

type RenderMixin

type RenderMixin struct {
	// contains filtered or unexported fields
}

RenderMixin is a mixin holding values for rendering a template

func (RenderMixin) Result

func (rm RenderMixin) Result() []byte

Result returns the parsed/executed content of a template as bytes

type Request

type Request struct {
	Entity  interface{}
	Session SessionManager
	Writer  RResponseWriter
	Params  httprouter.Params
	Raw     *http.Request
	Ctx     context.Context
	Claims  Claims
	// contains filtered or unexported fields
}

Request ...

func (Request) Config

func (req Request) Config(accessor string) interface{}

Config returns the configuration of your server for a specific accessor

func (Request) GetRouteTree

func (req Request) GetRouteTree() RouteTree

GetRouteTree returns a list of loaded routes in rubik

func (*Request) Redirect

func (req *Request) Redirect(url string, customStatus ...int)

Redirect redirects your request to the given URL with status 302 by default. If you want to provide a custom status for your redirection you can do that by passing in a custom status like so:

func someCtl(req *Request) {
	req.Redirect("https://ashishshekar.com", http.StatusTemporaryRedirect)
}

func (*Request) Respond

func (req *Request) Respond(data interface{}, ofType ...ByteType)

Respond is a terminal function for rubik controller that sends byte response it wraps around your arguments for better reading

func (*Request) Throw

func (req *Request) Throw(status int, err error, btype ...ByteType)

Throw writes an error with given status code as response The ByteType parameter is optional as you can convert your error into a JSON or plain text

If you dont have an error object with you in the moment you can use rubik.E() to quickly wrap your string into an error and pass it inside this function

Example
package main

import (
	"github.com/rubikorg/rubik"
)

func main() {
	func(req *rubik.Request) {
		req.Throw(403, rubik.E("invalid token or something"))
	}(&rubik.Request{})
}
Output:

type RequestHook

type RequestHook func(*HookContext)

RequestHook ...

type Response

type Response struct {
	Status     int
	Body       interface{}
	Raw        *http.Response
	ParsedBody interface{}
	StringBody string
	IsJSON     bool
}

Response is a struct that is returned by every client after request is made successful

type RestErrorMixin

type RestErrorMixin struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

RestErrorMixin type is used by rubik when rubik.Throw is called for writing error types as common JSON structure across Rubik server

func (RestErrorMixin) Error

func (re RestErrorMixin) Error() string

Error implements the error interface of Go

type Route

type Route struct {
	Path                 string
	Method               string
	Description          string
	ResponseDeclarations map[int]string
	JSON                 bool
	Entity               interface{}
	Guards               []Controller
	Middlewares          []Controller
	Validation           Validation
	Controller           Controller
}

Route defines how a specific route route inside the Rubik server must behave. Route collects all the information required for processing of a HTTP request and performs a handler construction depending upon these values.

There is a specific order in which handlers of Routes are constructed:

[ Entity check --- Guard() --- Validation() --- []Middlewares() --- Controller() ]

type RouteInfo

type RouteInfo struct {
	Path        string
	Description string
	BelongsTo   string
	Entity      interface{}
	IsJSON      bool
	Method      string
	Responses   map[int]string
}

RouteInfo is a flat structure for processing information about the routes

type RouteTree

type RouteTree struct {
	RouterList map[string]string
	Routes     []RouteInfo
}

RouteTree represents your routes as a local map for getting information about your routes

type Router

type Router struct {
	Middleware  []Controller
	Description string
	// contains filtered or unexported fields
}

Router is used to hold all your rubik routes together

func Create

func Create(index string) Router

Create retuens a rubik.Router instance for using and grouping routes. It is generally used if you want to add routes under the same umbrella prefix of this router. In Rubik it is used to group routes by domains/ responsibilities.

func (*Router) Add

func (ro *Router) Add(r Route)

Add injects a rubik.Route definition to the parent router from which it is called

type SessionManager added in v0.2.5

type SessionManager interface {
	Get(string) string
	Set(string, string) error
	Delete(string) bool
}

SessionManager is an interface contract that rubik.Session uses Anything abiding by this contract can

type StorageContainer

type StorageContainer struct {
	// contains filtered or unexported fields
}

StorageContainer is abstracted struct to access your storage files. It can access of remove a whole container.

Container corresponds to a single directory in your storage folder and will have access to files only inside this container/directory

func (StorageContainer) Access

func (s StorageContainer) Access(name string) (FileStore, error)

Access a FileStore from your StorageContainer. It can be viewed as accessing a specific folder inside your storage/ folder and performing operations inside of that folder

func (StorageContainer) Remove

func (s StorageContainer) Remove(name string) error

Remove a FileStore from your StorageContainer. Removing a FileStore will remove all the files inside the FileStore

type TestProbe

type TestProbe struct {
	// contains filtered or unexported fields
}

TestProbe is an abstraction for easily testing your rubik routes

func NewProbe

func NewProbe(ro Router) TestProbe

NewProbe returns a probe for testing your rubik server

Example:

var probe rubik.TestProbe
func init() {
	// pass the rubik.Router you want to test
	probe = rubik.NewProbe(index.Router)
}

func TestSomeRoute(t *testing.T) {
	// returns the *http.Request, *httptest.ResponseRecorder used inside the test
	req, rr := probe.Test(en)
	if rr.Result().StatusCode != 200 { /* Something is wrong */}
}

func (TestProbe) TestHandler

func (p TestProbe) TestHandler(method, path string, reqBody io.Reader, en interface{},
	h http.Handler) (*http.Request, *httptest.ResponseRecorder)

TestHandler is a probe util function to test your handler if you are not using a rubik.Controller for your route and using UseHandler() to cast it

func (TestProbe) TestSimple added in v0.2.5

func (p TestProbe) TestSimple(r Route, en interface{}, ctl Controller) *httptest.ResponseRecorder

TestSimple a route with method, path to request, Entity (if used) and the controller to test

type Validation

type Validation map[string][]Assertion

Validation is validation operations to be performed on the request entity

type Values

type Values map[string]interface{}

Values that transcends url.Values allowing any type as value

func (Values) Encode

func (val Values) Encode() string

Encode converts the values into urlencoded strings

func (Values) Set

func (val Values) Set(key string, value interface{})

Set assigns a value for key `key` inside the rubik.Values

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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