go vendor

This commit is contained in:
lealife
2017-11-30 19:55:33 +08:00
parent 2856da6888
commit 0fb92efbf3
670 changed files with 199010 additions and 0 deletions

View File

@ -0,0 +1,11 @@
# FastHTTP
This module is the for [FastHTTP](https://github.com/valyala/fasthttp) server engine.
It does not support WebSockets.
### app.conf
- **server.engine** You must set this to `fasthttp` in order to use this server engine
### Other Notes
All features from that the go HTTP engine is supported by this server engine.
Memory usage is decreased by avoiding memory allocations. This should
increase overall runtime performance and throughput.

View File

@ -0,0 +1,423 @@
package fasthttp
import (
"bytes"
"fmt"
"github.com/revel/revel"
"github.com/valyala/fasthttp"
"io"
"mime/multipart"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
type FastHTTPServer struct {
Server *fasthttp.Server
ServerInit *revel.EngineInit
MaxMultipartSize int64
}
var serverLog = revel.AppLog
func init() {
revel.RegisterServerEngine("fasthttp", func() revel.ServerEngine {
return &FastHTTPServer{}
})
revel.RegisterModuleInit(func(m *revel.Module) {
serverLog = m.Log
})
}
func (f *FastHTTPServer) Init(init *revel.EngineInit) {
f.MaxMultipartSize = int64(revel.Config.IntDefault("server.request.max.multipart.filesize", 32)) << 20 /* 32 MB */
fastHttpContextStack = revel.NewStackLock(revel.Config.IntDefault("server.context.stack", 100),
revel.Config.IntDefault("server.context.maxstack", 200),
func() interface{} { return NewFastHttpContext(f) })
fastHttpMultipartFormStack = revel.NewStackLock(revel.Config.IntDefault("server.form.stack", 100),
revel.Config.IntDefault("server.form.maxstack", 200),
func() interface{} { return &FastHttpMultipartForm{} })
requestHandler := func(ctx *fasthttp.RequestCtx) {
f.RequestHandler(ctx)
}
f.ServerInit = init
f.Server = &fasthttp.Server{
ReadTimeout: time.Duration(revel.Config.IntDefault("http.timeout.read", 0)) * time.Second,
WriteTimeout: time.Duration(revel.Config.IntDefault("http.timeout.write", 0)) * time.Second,
Handler: requestHandler,
}
}
// Handler is assigned in the Init
func (f *FastHTTPServer) Start() {
go func() {
time.Sleep(100 * time.Millisecond)
fmt.Printf("\nListening on fasthttp %s...\n", f.ServerInit.Address)
}()
if revel.HTTPSsl {
if f.ServerInit.Network != "tcp" {
// This limitation is just to reduce complexity, since it is standard
// to terminate SSL upstream when using unix domain sockets.
serverLog.Fatal("SSL is only supported for TCP sockets. Specify a port to listen on.")
}
serverLog.Fatal("Failed to listen https:", "error",
f.Server.ListenAndServeTLS(f.ServerInit.Address, revel.HTTPSslCert, revel.HTTPSslKey))
} else {
listener, err := net.Listen(f.ServerInit.Network, f.ServerInit.Address)
if err != nil {
serverLog.Fatal("Failed to listen http:", "error", err)
}
serverLog.Info("Listening fasthttp ", f.ServerInit.Network, f.ServerInit.Address)
// revel.ERROR.Fatalln("Failed to serve:", f.Server.ListenAndServe(f.ServerInit.Address))
serverLog.Fatal("Server exited", "error", f.Server.Serve(listener))
println("***ENDING ***")
}
}
func (f *FastHTTPServer) RequestHandler(ctx *fasthttp.RequestCtx) {
// TODO this
//if maxRequestSize := int64(revel.Config.IntDefault("http.maxrequestsize", 0)); maxRequestSize > 0 {
// buffer := &bytes.Buffer{}
// err := ctx.Request.ReadLimitBody(buffer,maxRequestSize)
// if err!=nil {
// // Send the error back to the client
// ctx.SetStatusCode(http.StatusRequestEntityTooLarge)
// return
// }
//}
context := fastHttpContextStack.Pop().(*FastHttpContext)
defer func() {
fastHttpContextStack.Push(context)
}()
context.SetContext(ctx)
f.ServerInit.Callback(context)
}
func (f *FastHTTPServer) Event(event int, args interface{}) {
switch event {
case revel.ENGINE_BEFORE_INITIALIZED:
case revel.ENGINE_STARTED:
}
}
func (f *FastHTTPServer) Name() string {
return "fasthttp"
}
func (f *FastHTTPServer) Engine() interface{} {
return f
}
func (g *FastHTTPServer) Stats() map[string]interface{} {
return map[string]interface{}{
"FastHTTP Engine Context": fastHttpContextStack.String(),
"FastHTTP Engine Forms": fastHttpMultipartFormStack.String(),
}
}
type (
FastHttpContext struct {
Request *FastHttpRequest
Response *FastHttpResponse
}
FastHttpRequest struct {
toQuery bool
url *url.URL
query url.Values
Original *fasthttp.RequestCtx
FormParsed bool
form url.Values
MultiFormParsed bool
// WebSocket *websocket.Conn
ParsedForm *FastHttpMultipartForm
header *FastHttpHeader
Engine *FastHTTPServer
}
FastHttpResponse struct {
Original *fasthttp.RequestCtx
header *FastHttpHeader
Writer io.Writer
Engine *FastHTTPServer
}
FastHttpMultipartForm struct {
Form *multipart.Form
}
FastHttpHeader struct {
Source interface{}
isResponse bool
}
FastHttpCookie []byte
)
var (
fastHttpContextStack *revel.SimpleLockStack
fastHttpMultipartFormStack *revel.SimpleLockStack
)
func NewFastHttpContext(instance *FastHTTPServer) *FastHttpContext {
if instance == nil {
instance = &FastHTTPServer{MaxMultipartSize: 32 << 20}
}
c := &FastHttpContext{
Request: &FastHttpRequest{header: &FastHttpHeader{isResponse: false},
Engine: instance},
Response: &FastHttpResponse{header: &FastHttpHeader{isResponse: true},
Engine: instance},
}
c.Response.header.Source = c.Response
c.Request.header.Source = c.Request
return c
}
func (c *FastHttpContext) GetRequest() revel.ServerRequest {
return c.Request
}
func (c *FastHttpContext) GetResponse() revel.ServerResponse {
return c.Response
}
func (c *FastHttpContext) SetContext(context *fasthttp.RequestCtx) {
c.Response.SetContext(context)
c.Request.SetContext(context)
}
func (c *FastHttpContext) Destroy() {
c.Response.Destroy()
c.Request.Destroy()
}
func (r *FastHttpRequest) Get(key int) (value interface{}, err error) {
switch key {
case revel.HTTP_SERVER_HEADER:
value = r.GetHeader()
case revel.HTTP_MULTIPART_FORM:
value, err = r.GetMultipartForm()
case revel.HTTP_QUERY:
value = r.GetQuery()
case revel.HTTP_FORM:
value, err = r.GetForm()
case revel.HTTP_REQUEST_URI:
value = string(r.Original.RequestURI())
case revel.HTTP_REMOTE_ADDR:
value = r.Original.RemoteAddr().String()
case revel.HTTP_METHOD:
value = string(r.Original.Method())
case revel.HTTP_PATH:
value = string(r.Original.Path())
case revel.HTTP_HOST:
value = string(r.Original.Request.Host())
case revel.HTTP_URL:
if r.url == nil {
r.url, _ = url.Parse(string(r.Original.Request.URI().FullURI()))
}
value = r.url
case revel.HTTP_BODY:
value = bytes.NewBuffer(r.Original.Request.Body())
default:
err = revel.ENGINE_UNKNOWN_GET
}
return
}
func (r *FastHttpRequest) Set(key int, value interface{}) bool {
return false
}
func (r *FastHttpRequest) GetQuery() url.Values {
if !r.toQuery {
// Attempt to convert to query
r.query = url.Values{}
r.Original.QueryArgs().VisitAll(func(key, value []byte) {
r.query.Set(string(key), string(value))
})
r.toQuery = true
}
return r.query
}
func (r *FastHttpRequest) GetForm() (url.Values, error) {
if !r.FormParsed {
r.form = url.Values{}
r.Original.PostArgs().VisitAll(func(key, value []byte) {
println("Set value", string(key), string(value))
r.query.Set(string(key), string(value))
})
r.FormParsed = true
}
return r.form, nil
}
func (r *FastHttpRequest) GetMultipartForm() (revel.ServerMultipartForm, error) {
if !r.MultiFormParsed {
// TODO Limit size r.Engine.MaxMultipartSize
form, err := r.Original.MultipartForm()
if err != nil {
return nil, err
}
r.ParsedForm = fastHttpMultipartFormStack.Pop().(*FastHttpMultipartForm)
r.ParsedForm.Form = form
}
return r.ParsedForm, nil
}
func (r *FastHttpRequest) GetHeader() revel.ServerHeader {
return r.header
}
func (r *FastHttpRequest) GetRaw() interface{} {
return r.Original
}
func (r *FastHttpRequest) SetContext(req *fasthttp.RequestCtx) {
r.Original = req
}
func (r *FastHttpRequest) Destroy() {
r.Original = nil
r.FormParsed = false
r.MultiFormParsed = false
r.ParsedForm = nil
r.toQuery = false
}
func (r *FastHttpResponse) Get(key int) (value interface{}, err error) {
switch key {
case revel.HTTP_SERVER_HEADER:
value = r.Header()
case revel.HTTP_STREAM_WRITER:
value = r
case revel.HTTP_WRITER:
value = r.Writer
default:
err = revel.ENGINE_UNKNOWN_GET
}
return
}
func (r *FastHttpResponse) Set(key int, value interface{}) (set bool) {
switch key {
case revel.ENGINE_RESPONSE_STATUS:
r.Header().SetStatus(value.(int))
set = true
case revel.HTTP_WRITER:
r.SetWriter(value.(io.Writer))
set = true
}
return
}
func (r *FastHttpResponse) GetWriter() io.Writer {
return r.Writer
}
func (r *FastHttpResponse) Header() revel.ServerHeader {
return r.header
}
func (r *FastHttpResponse) GetRaw() interface{} {
return r.Original
}
func (r *FastHttpResponse) WriteStream(name string, contentlen int64, modtime time.Time, reader io.Reader) error {
// do a simple io.Copy, we do it directly into the writer which may be configured to be a compressed
// writer
ius := r.Original.Request.Header.Peek("If-Unmodified-Since")
if t, err := http.ParseTime(string(ius)); ius != nil && err == nil && !modtime.IsZero() {
// The Date-Modified header truncates sub-second precision, so
// use mtime < t+1s instead of mtime <= t to check for unmodified.
if modtime.Before(t.Add(1 * time.Second)) {
h := r.Original.Response.Header
h.Del("Content-Type")
h.Del("Content-Length")
if h.Peek("Etag") != nil {
h.Del("Last-Modified")
}
h.SetStatusCode(http.StatusNotModified)
return nil
}
}
if contentlen != -1 {
r.Original.Response.Header.Set("Content-Length", strconv.FormatInt(contentlen, 10))
}
if _, err := io.Copy(r.Writer, reader); err != nil {
r.Original.Response.Header.SetStatusCode(http.StatusInternalServerError)
return err
} else {
r.Original.Response.Header.SetStatusCode(http.StatusOK)
}
return nil
}
func (r *FastHttpResponse) Destroy() {
if c, ok := r.Writer.(io.Closer); ok {
c.Close()
}
r.Original = nil
r.Writer = nil
}
func (r *FastHttpResponse) SetContext(w *fasthttp.RequestCtx) {
r.Original = w
r.Writer = w.Response.BodyWriter()
}
func (r *FastHttpResponse) SetWriter(writer io.Writer) {
r.Writer = writer
}
func (r *FastHttpHeader) SetCookie(cookie string) {
if r.isResponse {
r.Source.(*FastHttpResponse).Original.Response.Header.Add("Set-Cookie", cookie)
}
}
func (r *FastHttpHeader) GetCookie(key string) (value revel.ServerCookie, err error) {
if !r.isResponse {
var cookie []byte
if cookie = r.Source.(*FastHttpRequest).Original.Request.Header.Cookie(key); cookie != nil {
value = FastHttpCookie(cookie)
} else {
err = http.ErrNoCookie
}
}
return
}
func (r *FastHttpHeader) Set(key string, value string) {
if r.isResponse {
r.Source.(*FastHttpResponse).Original.Response.Header.Set(key, value)
}
}
func (r *FastHttpHeader) Add(key string, value string) {
if r.isResponse {
r.Source.(*FastHttpResponse).Original.Response.Header.Add(key, value)
}
}
func (r *FastHttpHeader) Del(key string) {
if r.isResponse {
r.Source.(*FastHttpResponse).Original.Response.Header.Del(key)
}
}
func (r *FastHttpHeader) Get(key string) (value []string) {
if !r.isResponse {
value = strings.Split(string(r.Source.(*FastHttpRequest).Original.Request.Header.Peek(key)), ",")
} else {
value = strings.Split(string(r.Source.(*FastHttpResponse).Original.Response.Header.Peek(key)), ",")
}
return
}
func (r *FastHttpHeader) SetStatus(statusCode int) {
if r.isResponse {
r.Source.(*FastHttpResponse).Original.Response.SetStatusCode(statusCode)
}
}
func (r FastHttpCookie) GetValue() string {
return string(r)
}
func (f *FastHttpMultipartForm) GetFiles() map[string][]*multipart.FileHeader {
return f.Form.File
}
func (f *FastHttpMultipartForm) GetValues() url.Values {
return url.Values(f.Form.Value)
}
func (f *FastHttpMultipartForm) RemoveAll() error {
return f.Form.RemoveAll()
}

View File

@ -0,0 +1,3 @@
package fasthttp
// Required for vendoring see golang.org/issue/13832