sola

package module
v2.1.2 Latest Latest
Warning

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

Go to latest
Published: Dec 13, 2019 License: Apache-2.0 Imports: 11 Imported by: 3

README

Sola V2

A simple golang web framwork based middleware.

内部错误(无法修复)

  • v2.1.0 & v2.1.1 内部版本号变量误标记为 2.0.0

Quick Start

基本的 sola 程序 (Hello World) 如下:

package main

import (
	"net/http"

	"github.com/ddosakura/sola/v2"
)

// handler
func hw(c sola.Context) error {
	// 输出 Hello World
	return c.String(http.StatusOK, "Hello World")
}

func main() {
	// 将 handler 包装为中间件
	m := sola.Handler(hw).M()
	// 使用中间件
	sola.Use(m)
	// 监听 127.0.0.1:3000
	sola.ListenKeep("127.0.0.1:3000")
}

Hot Update

# 安装
go get -u -v github.com/ddosakura/sola/v2/cli/sola-hot
# 在开发目录执行
sola-hot

执行 sola-hot 进行热更新,运行过程中将生成临时可执行文件 sola-dev

linux 系统使用 sola-linux 监听端口可实现平滑切换(不中断请求)。

import (
	linux "github.com/ddosakura/sola/v2/extension/sola-linux"
)

linux.Listen("127.0.0.1:3000", app)
linux.Keep()

Extension

  • hot 动态模块加载(使用了 plugin,仅 linux 可用)
  • sola-linux 平滑切换(使用了大量系统调用,仅 linux 可用)
More Example

废弃说明

即将废弃的中间件/方法会在注释中标注 @deprecated

About Reader

Reader 可简化 Request 的读取:

var a ReqLogin
if err := c.GetJSON(&a); err != nil {
	return err
}
Builtin Reader
  • GetJSON JSON

About Writer

Writer 可简化 Response 的书写:

// String Writer
c.String(http.StatusOK, "Hello World")

// JSON Writer
c.JSON(http.StatusOK, &MyResponse{
	Code: 0,
	Msg:  "Success",
	Data: "Hello World!",
})
Builtin Writer
  • Blob 二进制
  • HTML HTML(text/html)
  • String 普通文本(text/plain)
  • JSON JSON(application/json)
  • File 文件 - 兼容 afero

About Middleware

中间间的定义如下:

type (
	// Context for Middleware
	Context interface {
		// Set/Get
		Store() map[string]interface{}
		Origin() Context
		Shadow() Context
		Set(key string, value interface{})
		Get(key string) interface{}

		// API
		Sola() *Sola
		SetCookie(cookie *http.Cookie)
		Request() *http.Request
		Response() http.ResponseWriter

		// Writer
		Blob(code int, contentType string, bs []byte) (err error)
		HTML(code int, data string) error
		String(code int, data string) error
		JSON(code int, data interface{}) error
		File(f File) (err error)

		// Reader
		GetJSON(data interface{}) error

		// Handler
		Handle(code int) Handler
	}
	context struct {
		origin Context
		lock   sync.RWMutex
		store  map[string]interface{}
	}

	// Handler func
	Handler func(Context) error

	// Middleware func
	Middleware func(Handler) Handler
)

关于 Context 键值的约定:

  • sola 框架

    • sola *sola.Sola
    • sola.request *http.Request
    • sola.response http.ResponseWriter
  • auth 认证中间件

    • auth.username Base Auth 用户名
    • auth.password Base Auth 密码
    • auth.claims JWT Auth Payload
    • auth.token 签发的 JWT
  • logger 日志中间件

    • logger message chan
  • x/router 旧路由中间件

    • x.router.param.* 路径参数
  • router 新路由中间件

    • router.meta 路由元数据
    • router.param.* 路径参数
  • hot 动态模块加载扩展

    • ext.hot *Hot

注意:请尽量使用中间件包中提供的标准方法、常量读取上下文数据,防止内部逻辑修改导致的向后不兼容。

Builtin Middleware
  • auth 认证中间件
    • 自定义返回内容
    • Dev Mode(500)
  • cors 跨域中间件 - 参考 koa2-cors
  • graphql GraphQL 中间件
  • logger 日志中间件
  • native go 原生 handler 转换中间件(取代原静态文件中间件)
    • static 原静态文件中间件
    • 可用于静态文件
    • 可用于 statik
    • 可用于 afero
    • ...
  • proxy 反向代理中间件(取代原 backup、favicon 中间件)
  • rest RESTful API 中间件
  • swagger API 文档中间件
  • ws WebSocket 中间件
  • x/router 旧路由中间件 (@deprecated 预计在 v2.2.x 移除)
  • router 新路由中间件
router 匹配规则
  • 完整版 GET localhost:3000/user/:id (注意 Host 直接匹配 *http.Request 中的 Host)
  • 不指定 Method localhost:3000/user/:id
  • 不指定 Host GET /user/:id
  • 不指定 Method & Host /user/:id
  • 默认路径匹配(仅在 Bind 中使用,一般作为最后一个路径) /*
  • 特殊用法:仅指定 Method(用于 Bind,Path 由 Router 的 Pattern 匹配) GET - 支持 net/http 包中的所有 Method*

样例解释:

// 匹配 /api/v1/*
r := router.New(&router.Option{
	Pattern: "/api/v1",
})
// 严格匹配 /api/v1/hello
r.Bind("/hello", hello("Hello World!"))
{
	// 匹配 /api/v1/user/*
	sub := r.Sub(&router.Option{
		Pattern: "/user",
	})
	// 严格匹配 /api/v1/user/hello
	sub.Bind("/hello", hello("Hello!"))
	// 严格匹配 /api/v1/user/hello 失败后执行该中间件
	sub.Use(func(next sola.Handler) sola.Handler {
		return func(c sola.Context) error {
			fmt.Println("do auth")
			return next(c)
		}
	})
	// 严格匹配 /api/v1/user/info
	sub.Bind("/info", hello("user info"))
	// 匹配 /api/v1/user/infox/*
	sub.Bind("/infox/*", hello("user infox"))
	// 严格匹配 /api/v1/user/:id (路径参数 id)
	sub.Bind("/:id", get("id"))
	// sub 没有默认匹配
	// 如果 sub 加了 UseNotFound 选项,将调用 sola 的 404 Handler
	// 否则不会调用,将继续匹配后面的 `/*`
}
// 匹配 /api/v1/* (默认匹配)
r.Bind("/*", error404)
// 使用路由
app.Use(r.Routes())

About Config

About ORM

  • Debug in Dev Mode
  • see gorm

About API Doc

以下例子仅作为 API Doc 使用说明,未实现具体功能:

package main

import (
	"github.com/ddosakura/sola/v2"
	"github.com/ddosakura/sola/v2/middleware/auth"
	"github.com/ddosakura/sola/v2/middleware/x/router"
	"github.com/ddosakura/sola/v2/middleware/swagger"

	_ "example/sola-example/api-doc/docs"
	"example/sola-example/api-doc/handler"
)

// @title Swagger Example API
// @version 1.0
// @host localhost:3000
// @BasePath /api/v1
// @description This is a sample server celler server.

// @termsOfService http://swagger.io/terms/

// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization

// @x-extension-openapi {"example": "value on a json format"}

func main() {
	_sign := auth.Sign(auth.AuthJWT, []byte("sola_key"))
	_auth := auth.Auth(auth.AuthJWT, []byte("sola_key"))

	app := sola.New()
	r := router.New()

	r.BindFunc("GET /swagger", swagger.WrapHandler)

	sub := router.New()
	sub.Prefix = "/api/v1"
	{
		sub.BindFunc("GET /hello", handler.Hello)
		sub.BindFunc("POST /login", auth.NewFunc(_sign, tmp, handler.Hello))
		sub.BindFunc("/logout", auth.CleanFunc(handler.Hello))

		third := router.New()
		third.Prefix = sub.Prefix
		{
			third.BindFunc("GET /list", handler.List)
			third.BindFunc("GET /item/:id", handler.Item)
		}
		sub.Bind("", auth.New(_auth, nil, third.Routes()))
	}
	r.Bind("/api/v1", sub.Routes())

	app.Use(r.Routes())
	sola.Listen("127.0.0.1:3000", app)
	sola.Keep()
}

func tmp(sola.Handler) sola.Handler {
	return handler.Hello
}
// Hello godoc
// @Summary     Say Hello
// @Description Print Hello World!
// @Produce     plain
// @Success     200 {string} string "Hello World!"
// @Router      /hello [get]
func Hello(c sola.Context) error {
	return c.String(http.StatusOK, "Hello World!")
}

Documentation

Index

Constants

View Source
const (
	MIMEApplicationJSON                  = "application/json"
	MIMEApplicationJSONCharsetUTF8       = MIMEApplicationJSON + "; " + charsetUTF8
	MIMEApplicationJavaScript            = "application/javascript"
	MIMEApplicationJavaScriptCharsetUTF8 = MIMEApplicationJavaScript + "; " + charsetUTF8
	MIMEApplicationXML                   = "application/xml"
	MIMEApplicationXMLCharsetUTF8        = MIMEApplicationXML + "; " + charsetUTF8
	MIMETextXML                          = "text/xml"
	MIMETextXMLCharsetUTF8               = MIMETextXML + "; " + charsetUTF8
	MIMEApplicationForm                  = "application/x-www-form-urlencoded"
	MIMEApplicationProtobuf              = "application/protobuf"
	MIMEApplicationMsgpack               = "application/msgpack"
	MIMETextHTML                         = "text/html"
	MIMETextHTMLCharsetUTF8              = MIMETextHTML + "; " + charsetUTF8
	MIMETextPlain                        = "text/plain"
	MIMETextPlainCharsetUTF8             = MIMETextPlain + "; " + charsetUTF8
	MIMEMultipartForm                    = "multipart/form-data"
	MIMEOctetStream                      = "application/octet-stream"
)

MIME types

View Source
const (
	// Version of Sola
	Version = "v2.1.2"
	// Issuer of InternalError
	Issuer = "sola"
)
View Source
const (
	CtxSola     = "sola"
	CtxRequest  = "sola.request"
	CtxResponse = "sola.response"
)

ContextKey

View Source
const (
	HandleCodePass = iota
)

Custom Handle Code

Variables

View Source
var (
	DefaultApp = New()
)

default

View Source
var (
	ErrM2H = errors.New("Middleware using next() can't be Handler")
)

error(s)

View Source
var HandlePass = Handler(func(c Context) error {
	return nil
})

HandlePass Handler

View Source
var TplInternalError = template.Must(template.
	New("SolaInternalError").
	Parse(`<html>
<head>
<meta charset="utf-8">
<title>Sola Internal Error</title>
<style>
body {
	margin-top: 50px;
}

th {
    color: #4f6b72;
    border-right: 1px solid #C1DAD7;
    border-bottom: 1px solid #C1DAD7;
    border-top: 1px solid #C1DAD7;
    letter-spacing: 2px;
    text-transform: uppercase;
    text-align: left;
    padding: 6px 6px 6px 12px;
}

th.top {
    border-left: 1px solid #C1DAD7;
    border-right: 1px solid #C1DAD7;
}

th.spec {
    border-left: 1px solid #C1DAD7;
    border-top: 0;
    color: #797268;
}

td {
    border-right: 1px solid #C1DAD7;
    border-bottom: 1px solid #C1DAD7;
    background: #fff;
    font-size: 11px;
    padding: 6px 6px 6px 12px;
    color: #4f6b72;
}

tr:nth-child(odd) td {
    background: #F5FAFA;
    color: #797268;
}
</style>
</head>
<body>
<h1 style="text-align: center;">Sola Internal Error</h1>
<table cellspacing="0" style="width: 70%;margin: auto;">
<tr>
    <th class="top">Meta</th>
    <th>Value</th>
</tr>
{{range $i,$e := .}}
<tr>
    <th class="spec">{{$i}}</td>
    <td>{{$e}}</td>
</tr>
{{end}}
</table>
</body>
</html>`))

TplInternalError for sola

Functions

func Error added in v2.1.2

func Error(issuer string, e error) error

Error Internal

func Keep

func Keep()

Keep Serve(s)

func Listen

func Listen(addr string, gs ...*Sola)

Listen & Serve(s)

func ListenKeep added in v2.1.2

func ListenKeep(addr string, gs ...*Sola)

ListenKeep Serve(s)

func ListenKeepTLS added in v2.1.2

func ListenKeepTLS(addr, certFile, keyFile string, gs ...*Sola)

ListenKeepTLS Serve(s)

func ListenTLS

func ListenTLS(addr, certFile, keyFile string, gs ...*Sola)

ListenTLS & Serve(s)

func Use added in v2.1.2

func Use(ms ...Middleware)

Use Middleware

Types

type C added in v2.1.2

type C Context

C alias of Context

type Context

type Context interface {
	// Set/Get
	Store() map[string]interface{}
	Origin() Context
	Shadow() Context
	Set(key string, value interface{})
	Get(key string) interface{}

	// API
	Sola() *Sola
	SetCookie(cookie *http.Cookie)
	Request() *http.Request
	Response() http.ResponseWriter

	// Writer
	Blob(code int, contentType string, bs []byte) (err error)
	HTML(code int, data string) error
	String(code int, data string) error
	JSON(code int, data interface{}) error
	File(f File) (err error)

	// Reader
	GetJSON(data interface{}) error

	// Handler
	Handle(code int) Handler
}

Context for Middleware

type File

type File interface {
	io.ReadSeeker
	Close() error
	Stat() (os.FileInfo, error)
}

File for Reader

type H added in v2.1.2

type H Handler

H alias of Handler

type Handler

type Handler func(Context) error

Handler func

func FromHandler added in v2.1.2

func FromHandler(h http.Handler) Handler

FromHandler http.Handler

func FromHandlerFunc added in v2.1.2

func FromHandlerFunc(h func(http.ResponseWriter, *http.Request)) Handler

FromHandlerFunc func(http.ResponseWriter, *http.Request)

func MergeFunc

func MergeFunc(h Handler, middlewares ...Middleware) Handler

MergeFunc for Middlewares & Handler

func OriginContext

func OriginContext(next Handler) Handler

OriginContext Middleware change ctx to it's origin

func (Handler) M added in v2.1.2

func (h Handler) M() Middleware

M wrap Handler to Middleware

func (Handler) Must added in v2.1.2

func (h Handler) Must(not Handler) Handler

Must not nil

func (Handler) ServeHTTP added in v2.1.2

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ToHandlerFunc func(http.ResponseWriter, *http.Request)

func (Handler) ToHandler added in v2.1.2

func (h Handler) ToHandler() http.Handler

ToHandler http.Handler

func (Handler) ToHandlerFunc added in v2.1.2

func (h Handler) ToHandlerFunc() func(http.ResponseWriter, *http.Request)

ToHandlerFunc func(http.ResponseWriter, *http.Request)

type InternalError added in v2.1.2

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

InternalError of sola

func IError added in v2.1.2

func IError(issuer string, e error) *InternalError

IError Internal Error

func (*InternalError) Handler added in v2.1.2

func (e *InternalError) Handler() Handler

Handler of InternalError

func (*InternalError) Issuer added in v2.1.2

func (e *InternalError) Issuer() string

Issuer of InternalError

func (*InternalError) Write added in v2.1.2

func (e *InternalError) Write(w io.Writer) error

Write to io.Writer

type M added in v2.1.2

type M func(c C, next H) error

M func

func (M) M added in v2.1.2

func (m M) M() Middleware

M to Middleware

func (M) Must added in v2.1.2

func (m M) Must(not Handler) Middleware

Must not nil

type Middleware

type Middleware func(Handler) Handler

Middleware func

func Merge

func Merge(middlewares ...Middleware) Middleware

Merge Middlewares

func (Middleware) H added in v2.1.2

func (m Middleware) H() Handler

H wrap Middleware to Handler

func (Middleware) Handler

func (m Middleware) Handler() Handler

Handler of Middleware

func (Middleware) Must added in v2.1.2

func (m Middleware) Must(not Handler) Middleware

Must not nil

type Sola

type Sola struct {
	ErrorHandler func(error, Context) // 500
	// contains filtered or unexported fields
}

Sola App

func New

func New() *Sola

New Sola App

func (*Sola) CacheORM

func (s *Sola) CacheORM(key string, db *gorm.DB)

CacheORM - *gorm.DB

func (*Sola) DefaultORM

func (s *Sola) DefaultORM() *gorm.DB

DefaultORM getter

func (*Sola) Dev

func (s *Sola) Dev()

Dev Mode

func (*Sola) LoadConfig

func (s *Sola) LoadConfig()

LoadConfig by viper

func (*Sola) ORM

func (s *Sola) ORM(key string) *gorm.DB

ORM getter

func (*Sola) ServeHTTP

func (s *Sola) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP to impl http handler

func (*Sola) SetHandler

func (s *Sola) SetHandler(code int, h Handler)

SetHandler in Sola

func (*Sola) Use

func (s *Sola) Use(ms ...Middleware)

Use Middleware

Directories

Path Synopsis
cli
extension
hot
middleware
ws

Jump to

Keyboard shortcuts

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