wsp

command module
v0.0.0-...-021e1c0 Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2022 License: BSD-2-Clause Imports: 17 Imported by: 0

README

中文 README

wsp (go http webserver)

Original Intention

  • Simple and reliable, fully take advantage of golang and have not added anything else complicated. Advantages: much easier to update with golang and reduce learning cost of users.
  • The routing pattern like controller/action provided by yii is commonly used, wsp has already supported.
  • It is easy to use java annotation, in the wsp, we can define the invoking of filter method via annotation.
  • We cannot reduce the QPS of original golang http webserver due to the introduction of wsp.

Installation

go get -u github.com/simplejia/wsp

Occassion

  • Offer service via http webserver
  • Backend api service

Case

  • Massive internet social project

Implementation

  • The routing is generated automatically. Providing the implementation code of controller/action according to the requirements, wsp will analyze the project code, generate routing table automatically and record it in demo/WSP.go. In addition, when controller/action defines code, it has to comply with the definition: func(http.ResponseWriter, *http.Request) and should have method receiver. demo_set.go
package controller

import (
	"net/http"

	"github.com/simplejia/wsp/demo/service"
)

// @prefilter("Login", {"Method":{"type":"get"}})
// @postfilter("Boss")
func (demo *Demo) Set(w http.ResponseWriter, r *http.Request) {
	key := r.FormValue("key")
	value := r.FormValue("value")
	demoService := service.NewDemo()
	demoService.Set(key, value)

	json.NewEncoder(w).Encode(map[string]interface{}{
		"code": 0,
	})
}

WSP.go

// generated by wsp, DO NOT EDIT.

package main

import "net/http"
import "time"
import "github.com/simplejia/wsp/demo/controller"
import "github.com/simplejia/wsp/demo/filter"

func init() {
	http.HandleFunc("/Demo/Get", func(w http.ResponseWriter, r *http.Request) {
		t := time.Now()
		_ = t
		var e interface{}
		c := new(controller.Demo)
		defer func() {
			e = recover()
			if ok := filter.Boss(w, r, map[string]interface{}{"__T__": t, "__C__": c, "__E__": e}); !ok {
				return
			}
		}()
		c.Get(w, r)
	})

	http.HandleFunc("/Demo/Set", func(w http.ResponseWriter, r *http.Request) {
		t := time.Now()
		_ = t
		var e interface{}
		c := new(controller.Demo)
		defer func() {
			e = recover()
			if ok := filter.Boss(w, r, map[string]interface{}{"__T__": t, "__C__": c, "__E__": e}); !ok {
				return
			}
		}()
		if ok := filter.Login(w, r, map[string]interface{}{"__T__": t, "__C__": c, "__E__": e}); !ok {
			return
		}
		if ok := filter.Method(w, r, map[string]interface{}{"type": "get", "__T__": t, "__C__": c, "__E__": e}); !ok {
			return
		}
		c.Set(w, r)
	})

}
  • wsp will analyze the project code, find the annotation that meets its requirements(referring to demo/controller/demo_set.go ) and generate filter invoking code automatically in demo/wsp.go. The annotation of filter is divided into prefilter and postfilter. Its format is as @prefilter({json body}),{json body} standing for the input parameter which complies with the definition format of json array(removing the brackets at the beginning and at the end) and is able to include string value or object value. The definition of filter function meets func (http.ResponseWriter, *http.Request, map[string]interface{}) bool. The filter function is as the following: method.go
package filter

import (
	"net/http"
	"strings"
)

func Method(w http.ResponseWriter, r *http.Request, p map[string]interface{}) bool {
	method, ok := p["type"].(string)
	if ok && strings.ToLower(r.Method) != strings.ToLower(method) {
		http.Error(w, "405 Method Not Allowed", http.StatusMethodNotAllowed)
		return false
	}
	return true
}

When inputting the parameter map[string]interface{} with filter, it will automatically set "T"(time.Time) whose value is the starting time and can be used to record the consuming time. The automatically set "C",{Controller} type whose value is {Controller} instance and it can access relevant data via the interface which is more simple and practical than via context package in accessing data. The automatically set “E",its value is the returned value of recover(), which is used to monitor errors and deal with them(postfilter has to recover()).

  • The instances of project main.go main.go
package main

import (
	"log"

	"github.com/simplejia/clog/api"
	"github.com/simplejia/lc"

	"net/http"
)

func init() {
	lc.Init(1e5)

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.NotFound(w, r)
	})
}

func main() {
	clog.Info("main()")

	log.Panic(http.ListenAndServe(":8080", nil))
}

中文

wsp (go http webserver)

实现初衷

  • 简单可依赖,充分利用go已有的东西,不另外增加复杂、难以理解的东西,这样做的好处包括:更容易跟随go的升级而升级,降低使用者学习成本
  • yii提供的controller/action的路由方式比较常用,在wsp里实现一套
  • java annotation的功能挺方便,在wsp里,通过注释来实现过滤器方法的调用定义
  • 不能因为wsp的引入而降低原生go http webserver的性能

安装

go get -u github.com/simplejia/wsp

使用场景

  • 以http webserver方式对外提供服务
  • 后台接口服务

使用案例

  • 大型互联网社交业务
  • 最新的案例请参考github.com/simplejia/skel (推荐)

实现方式

  • 路由自动生成,按要求提供controller/action的实现代码,wsp执行后会分析项目代码,自动生成路由表并记录在文件demo/WSP.go里,controller/action定义代码必须符合函数定义:func(http.ResponseWriter, *http.Request),并且是带receiver的method demo_set.go
package controller

import (
	"net/http"

	"github.com/simplejia/wsp/demo/service"
)

// @prefilter("Login", {"Method":{"type":"get"}})
// @postfilter("Boss")
func (demo *Demo) Set(w http.ResponseWriter, r *http.Request) {
	key := r.FormValue("key")
	value := r.FormValue("value")
	demoService := service.NewDemo()
	demoService.Set(key, value)

	json.NewEncoder(w).Encode(map[string]interface{}{
		"code": 0,
	})
}

WSP.go

// generated by wsp, DO NOT EDIT.

package main

import "net/http"
import "time"
import "github.com/simplejia/wsp/demo/controller"
import "github.com/simplejia/wsp/demo/filter"

func init() {
	http.HandleFunc("/Demo/Get", func(w http.ResponseWriter, r *http.Request) {
		t := time.Now()
		_ = t
		var e interface{}
		c := new(controller.Demo)
		defer func() {
			e = recover()
			if ok := filter.Boss(w, r, map[string]interface{}{"__T__": t, "__C__": c, "__E__": e}); !ok {
				return
			}
		}()
		c.Get(w, r)
	})

	http.HandleFunc("/Demo/Set", func(w http.ResponseWriter, r *http.Request) {
		t := time.Now()
		_ = t
		var e interface{}
		c := new(controller.Demo)
		defer func() {
			e = recover()
			if ok := filter.Boss(w, r, map[string]interface{}{"__T__": t, "__C__": c, "__E__": e}); !ok {
				return
			}
		}()
		if ok := filter.Login(w, r, map[string]interface{}{"__T__": t, "__C__": c, "__E__": e}); !ok {
			return
		}
		if ok := filter.Method(w, r, map[string]interface{}{"type": "get", "__T__": t, "__C__": c, "__E__": e}); !ok {
			return
		}
		c.Set(w, r)
	})

}
  • wsp分析项目代码,寻找符合要求的注释(见demo/controller/demo_set.go),自动生成过滤器调用代码在文件demo/WSP.go里,filter注解分为前置过滤器(prefilter)和后置过滤器(postfilter),格式如:@prefilter({json body}),{json body}代表传入参数,符合json array定义格式(去掉前后的中括号),可以包含string值或者object值,filter函数定义满足:func (http.ResponseWriter, *http.Request, map[string]interface{}) bool,过滤器函数如下: method.go
package filter

import (
	"net/http"
	"strings"
)

func Method(w http.ResponseWriter, r *http.Request, p map[string]interface{}) bool {
	method, ok := p["type"].(string)
	if ok && strings.ToLower(r.Method) != strings.ToLower(method) {
		http.Error(w, "405 Method Not Allowed", http.StatusMethodNotAllowed)
		return false
	}
	return true
}

filter输入参数map[string]interface{},会自动设置"T",time.Time类型,值为执行起始时间,可用于耗时统计,"C",{Controller}类型,值为{Controller}实例,可通过接口方式存取相关数据(这种方式存取数据较使用context包方式更简单实用),"E",值为recover()返回值,用于检测错误并处理(后置过滤器必须recover())

  • 项目main.go代码示例 (在开头定义go:generate,通过go generate信命令生成WSP.go文件) main.go
//go:generate wsp

package main

import (
	"log"

	"github.com/simplejia/clog/api"
	"github.com/simplejia/lc"

	"net/http"
)

func init() {
	lc.Init(1e5)

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.NotFound(w, r)
	})
}

func main() {
	clog.Info("main()")

	log.Panic(http.ListenAndServe(":8080", nil))
}

Documentation

Overview

A partner for golang webserver Created by simplejia 7/2016

Directories

Path Synopsis
conf
Package conf 用于项目基础配置。
Package conf 用于项目基础配置。

Jump to

Keyboard shortcuts

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