ghost

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jan 8, 2021 License: MIT Imports: 16 Imported by: 0

README

Ghost 👻

Version License

A simple HTTP server framework in Go, without any third-party dependencies.

Use it ONLY when you seek for simpleness, and do not extremely eager for performance and robustness.

Usage

All you need to do, is to make an interesting ghost, then run it.

package main

import (
	"github.com/deadblue/ghost"
	"github.com/deadblue/ghost/view"
)

type YourGhost struct{}

// Get will handle request "GET /"
func (g *YourGhost) Get(_ ghost.Context) (ghost.View, error) {
    return view.Text("You are here!"), nil
}

// GetIndexAsHtml will handle request "GET /index.html"
func (g *YourGhost) GetIndexAsHtml(_ ghost.Context) (ghost.View, error) {
	return view.Text("index.html"), nil
}

// GetDataById will handle request "GET /data/{id}", where the "id" is a path variable.
func (g *YourGhost) GetDataById(ctx ghost.Context) (ghost.View, error) {
	dataId := ctx.PathVar("id")
	return view.Text("Getting data whose id is " + dataId), nil
}

// PostForm will handle request "POST /update" 
func (g *YourGhost) PostUpdate(ctx ghost.Context) (ghost.View, error) {
	// Get post data from ctx.Request()
	return view.Text("Update done!"), nil
}

// BuyMeACoffee will handle request "BUY /me/a/coffee"
func (g *YourGhost) BuyMeACoffee(_ ghost.Context) (ghost.View, error) {
	return view.Text("Thank you!"), nil
}

func main() {
	err := ghost.Born(&YourGhost{}).Run()
    if err != nil {
    	panic(err)
    }
}

Specification

All methods on the ghost object, which is in form of the ghost.Controller, will be mounted as a request handler.

The method name, will be translated as the mount path, following these rules:

  • Suppose the method name is in camel-case, split it into words.
  • The first word will be treated as request method.
  • If there is no remain words, the method function will handle the root request.
  • If there are remain words, each word will be treated as a path segment.
  • In remain words, there are some special words that won't be treated as path segment:
    • By: The next word will be treated as a path variable.
    • As: Link the next word with "." instead of path separator ("/").

For examples:

Method Name Handle Request
Get GET /
GetIndex GET /index
GetUserProfile GET /user/profile
PostUserProfile POST /user/profile
GetDataById GET /data/{id}
GetDataByTypeById GET /data/{type}/{id}
GetDataByIdAsJson GET /data/{id}.json
BuyMeACoffee BUY /me/a/coffee

License

MIT

Documentation

Index

Constants

View Source
const (
	Version = "0.0.1"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type AwareShutdown

type AwareShutdown interface {
	OnShutdown() error
}

AwareShutdown is an optional interface, when developer need do some finalization on his ghost, implements this, and do finalization in OnShutdown().

type AwareStartup

type AwareStartup interface {
	OnStartup() error
}

AwareStartup is an optional interface, when developer need do some initialization on his ghost, implements this, and do initialization in OnStartup().

type Binder

type Binder interface {
	Bind(f interface{}) Controller
}

Binder is an optional interface, if developer implements it on his ghost, he will get 50x speedup on controller invoking.

A standard implementation looks like this:

func (g *YourGhost) Bind(f interface{}) ghost.Controller {
	if ctrl, ok := f.(func(*YourGhost, ghost.Context)(ghost.View, error)); ok {
		return func(ctx ghost.Context) (ghost.View, error) {
			return ctrl(g, ctx)
		}
	} else {
		return nil
	}
}

type Context

type Context interface {

	// Request returns the original HTTP request object.
	Request() *http.Request

	// PathVar return the variable value in request path.
	PathVar(name string) string

	// Query returns the parameter value in query string.
	Query(name string) string
}

Context describes the request context. TODO:

Currently, I have no idea what methods should Context provide.
I will add more methods in future when I think it need.
Anyway, you can call Request() to retrieve the original request, and
get information from it.

type Controller

type Controller func(ctx Context) (v View, err error)

type Shell

type Shell interface {

	// Startup starts up the shell manually, use this when you want to
	// control the shell lifecycle by yourself.
	// Otherwise, use Run instead.
	Startup() error

	// Shutdown shuts down the shell manually, use this when you want to
	// control the shell lifecycle by yourself.
	// Otherwise, use Run instead.
	Shutdown()

	// Done returns a read-only error channel, you will get notification
	// from it when the shell completely shutdown, use this when you
	// control the shell lifecycle by yourself.
	// Otherwise, use Run instead.
	Done() <-chan error

	// Run automatically runs the shell, and shutdown it when receive specific
	// OS signals, Run will exit after the shell completely shutdown.
	// If no signal specified, handles SIGINT and SIGTERM as default.
	Run(sig ...os.Signal) error
}

Shell is a lifeless object, until developer gives an interesting ghost to it.

func Born

func Born(ghost interface{}) Shell

Born creates a Shell with your ghost, and will listen at default network and address: "http://127.0.0.1:8066".

func BornAt

func BornAt(ghost interface{}, network, address string) Shell

BornAt creates a Shell with your ghost, and will listen at the network and address where you give.

type View

type View interface {

	// HTTP status code
	Status() int

	// Response headers
	Header() http.Header

	// Response body
	Body() io.Reader
}

View describes the response.

Directories

Path Synopsis
internal
package view provides most common-use ghost.View implementations for developers.
package view provides most common-use ghost.View implementations for developers.

Jump to

Keyboard shortcuts

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