Пример #1
0
func mainHandler(ctx *fasthttp.RequestCtx) {
	// Performance hack for prefork mode - periodically close keepalive
	// connections for evenly distributing connections among available
	// processes.
	if *prefork {
		maxDuration := maxConnDuration + time.Millisecond*time.Duration(atomic.LoadUint64(&connDurationJitter))
		if time.Since(ctx.ConnTime()) > maxDuration {
			atomic.StoreUint64(&connDurationJitter, uint64(rand.Intn(100)))
			ctx.SetConnectionClose()
		}
	}

	path := ctx.Path()
	switch string(path) {
	case "/plaintext":
		plaintextHandler(ctx)
	case "/json":
		jsonHandler(ctx)
	case "/db":
		dbHandler(ctx)
	case "/queries":
		queriesHandler(ctx)
	case "/fortune":
		fortuneHandler(ctx)
	case "/update":
		updateHandler(ctx)
	default:
		ctx.Error("unexpected path", fasthttp.StatusBadRequest)
	}
}
Пример #2
0
func idHandlerFunc(ctx *fasthttp.RequestCtx, idWorker *goflake.IdWorker, retry int) {
	ua := string(ctx.UserAgent())

	var (
		id  uint64
		err error
	)

	for i := 0; i < retry; i++ {
		id, err = idWorker.GetId(ua)
		if err == nil {
			break
		}
	}

	r := map[string]string{
		"id": strconv.FormatUint(id, 10),
	}

	if strings.HasSuffix(string(ctx.Path()), ".msgpack") {
		ctx.SetContentType("application/x-msgpack; charset=UTF-8")
		if err := codec.NewEncoder(ctx, mh).Encode(r); err != nil {
			ctx.Error(err.Error(), fasthttp.StatusInternalServerError)
		}
	} else {
		ctx.SetContentType("application/json; charset=UTF-8")
		if err := json.NewEncoder(ctx).Encode(r); err != nil {
			ctx.Error(fmt.Sprintf(`{"error":"%v"}`, err.Error()), fasthttp.StatusInternalServerError)
		}
	}
}
Пример #3
0
func (s *Selector) Match(ctx *fasthttp.RequestCtx) (string, bool) {
	var matchSlice []byte
	found := false
	switch s.RequestAttr {
	case "IP":
		matchSlice = []byte(ctx.RemoteIP().String())
	case "Method":
		matchSlice = ctx.Method()
	case "Path":
		matchSlice = ctx.Path()
	case "Host":
		matchSlice = ctx.Host()
	case "POST":
		matchSlice = ctx.PostArgs().Peek(s.SubAttr)
	case "GET":
		matchSlice = ctx.QueryArgs().Peek(s.SubAttr)
	case "Param":
		matchSlice = ctx.PostArgs().Peek(s.SubAttr)
		if matchSlice == nil {
			matchSlice = ctx.QueryArgs().Peek(s.SubAttr)
		}
	case "Header":
		matchSlice = ctx.Request.Header.Peek(s.SubAttr)
	default:
		log.Println("unknown request attribute:", s.RequestAttr)
	}
	if matchSlice != nil && (s.Regexp == nil || s.Regexp.Match(matchSlice)) {
		found = true
	}
	if s.Negate {
		found = !found
	}
	return string(matchSlice), found
}
Пример #4
0
func requestHandler(ctx *fasthttp.RequestCtx) {
	fmt.Fprintf(ctx, "Hello, world!\n\n")

	fmt.Fprintf(ctx, "Request method is %q\n", ctx.Method())
	fmt.Fprintf(ctx, "RequestURI is %q\n", ctx.RequestURI())
	fmt.Fprintf(ctx, "Requested path is %q\n", ctx.Path())
	fmt.Fprintf(ctx, "Host is %q\n", ctx.Host())
	fmt.Fprintf(ctx, "Query string is %q\n", ctx.QueryArgs())
	fmt.Fprintf(ctx, "User-Agent is %q\n", ctx.UserAgent())
	fmt.Fprintf(ctx, "Connection has been established at %s\n", ctx.ConnTime())
	fmt.Fprintf(ctx, "Request has been started at %s\n", ctx.Time())
	fmt.Fprintf(ctx, "Serial request number for the current connection is %d\n", ctx.ConnRequestNum())
	fmt.Fprintf(ctx, "Your ip is %q\n\n", ctx.RemoteIP())

	fmt.Fprintf(ctx, "Raw request is:\n---CUT---\n%s\n---CUT---", &ctx.Request)

	ctx.SetContentType("text/plain; charset=utf8")

	// Set arbitrary headers
	ctx.Response.Header.Set("X-My-Header", "my-header-value")

	// Set cookies
	var c fasthttp.Cookie
	c.SetKey("cookie-name")
	c.SetValue("cookie-value")
	ctx.Response.Header.SetCookie(&c)
}
func fastHTTPHandler(ctx *fasthttp.RequestCtx) {
	if string(ctx.Method()) == "GET" {
		switch string(ctx.Path()) {
		case "/rest/hello":
			ctx.Write([]byte("Hello world"))
		default:
			ctx.Error("Unsupported path", fasthttp.StatusNotFound)
		}
		return
	}
}
Пример #6
0
// Main request handler
func requestHandler(ctx *fasthttp.RequestCtx) {
	path := ctx.Path()
	switch {
	case bytes.HasPrefix(path, imgPrefix):
		imgHandler(ctx)
	case bytes.HasPrefix(path, cssPrefix):
		cssHandler(ctx)
	default:
		filesHandler(ctx)
	}
}
Пример #7
0
//fasthttp
func fastHttpRawHandler(ctx *fasthttp.RequestCtx) {
	if string(ctx.Method()) == "GET" {
		switch string(ctx.Path()) {
		case "/hello":
			if sleepTime > 0 {
				time.Sleep(sleepTimeDuration)
			}
			ctx.Write(message)
		default:
			ctx.Error("Unsupported path", fasthttp.StatusNotFound)
		}
		return
	}
	ctx.Error("Unsupported method", fasthttp.StatusMethodNotAllowed)
}
Пример #8
0
func (g *Goka) Serve(rCtx *fasthttp.RequestCtx) {

	c := g.pool.Get().(*Context)
	h, g := g.router.Find(string(rCtx.Method()), string(rCtx.Path()), c)
	c.reset(rCtx, g)

	for i := len(g.middleware) - 1; i >= 0; i-- {
		h = g.middleware[i](h)
	}

	if err := h(c); err != nil {
		g.httpErrorHandler(err, c)
	}

	g.pool.Put(c)
}
Пример #9
0
func mainHandler(ctx *fasthttp.RequestCtx) {
	path := ctx.Path()
	switch string(path) {
	case "/plaintext":
		plaintextHandler(ctx)
	case "/json":
		jsonHandler(ctx)
	case "/db":
		dbHandler(ctx)
	case "/queries":
		queriesHandler(ctx)
	case "/fortune":
		fortuneHandler(ctx)
	case "/update":
		updateHandler(ctx)
	default:
		ctx.Error("unexpected path", fasthttp.StatusBadRequest)
	}
}
Пример #10
0
func (a *API) Handler(ctx *fasthttp.RequestCtx) {
	ctx.SetContentType("application/json")
	ctx.Response.Header.Set("Access-Control-Allow-Origin", "*")
	switch string(ctx.Path()) {
	case "/rules":
		j, err := json.Marshal(a.Proxy.Rules)
		if err != nil {
			ctx.Error(fmt.Sprintf("{\"error\": \"%v\"}", err), 500)
			return
		}
		ctx.Write(j)
	case "/rules/reload":
		if err := a.Proxy.ReloadRules(a.RuleFile); err != nil {
			ctx.Error(fmt.Sprintf("{\"error\": \"%v\"}", err), 500)
			return
		}
		log.Println("Rule file reloaded")
		ctx.Write([]byte("{\"status\": \"ok\"}"))
	default:
		ctx.Error("{\"error\": \"Not found\"}", fasthttp.StatusNotFound)
	}
}
Пример #11
0
// Handler makes the router implement the fasthttp.ListenAndServe interface.
func (r *Router) Handler(ctx *fasthttp.RequestCtx) {
	if r.PanicHandler != nil {
		defer r.recv(ctx)
	}

	method := string(ctx.Method())
	if root := r.trees[method]; root != nil {
		path := string(ctx.Path())

		if f, ps, tsr := root.getValue(path); f != nil {
			f(ctx, ps)
			return
		} else if method != "CONNECT" && path != "/" {
			code := 301 // Permanent redirect, request with GET method
			if method != "GET" {
				// Temporary redirect, request with same method
				// As of Go 1.3, Go does not support status code 308.
				code = 307
			}

			if tsr && r.RedirectTrailingSlash {
				var uri string
				if len(path) > 1 && path[len(path)-1] == '/' {
					uri = path[:len(path)-1]
				} else {
					uri = path + "/"
				}
				ctx.Redirect(uri, code)
				return
			}

			// Try to fix the request path
			if r.RedirectFixedPath {
				fixedPath, found := root.findCaseInsensitivePath(
					CleanPath(path),
					r.RedirectTrailingSlash,
				)
				if found {
					uri := string(fixedPath)
					ctx.Redirect(uri, code)
					return
				}
			}
		}
	}

	// Handle 405
	if r.HandleMethodNotAllowed {
		for method := range r.trees {
			// Skip the requested method - we already tried this one
			if method == string(ctx.Method()) {
				continue
			}

			f, _, _ := r.trees[method].getValue(string(ctx.Path()))
			if f != nil {
				if r.MethodNotAllowed != nil {
					r.MethodNotAllowed(ctx)
				} else {
					ctx.Error(fasthttp.StatusMessage(fasthttp.StatusMethodNotAllowed),
						fasthttp.StatusMethodNotAllowed)
				}
				return
			}
		}
	}

	// Handle 404
	if r.NotFound != nil {
		r.NotFound(ctx)
	} else {
		ctx.Error(fasthttp.StatusMessage(fasthttp.StatusNotFound),
			fasthttp.StatusNotFound)
	}
}
Пример #12
0
// Handler makes the router implement the fasthttp.ListenAndServe interface.
func (r *Router) Handler(ctx *fasthttp.RequestCtx) {
	if r.PanicHandler != nil {
		defer r.recv(ctx)
	}

	path := string(ctx.Path())
	method := string(ctx.Method())
	if root := r.trees[method]; root != nil {
		if f, ps, tsr := root.getValue(path); f != nil {
			f(ctx, ps)
			return
		} else if method != "CONNECT" && path != "/" {
			code := 301 // Permanent redirect, request with GET method
			if method != "GET" {
				// Temporary redirect, request with same method
				// As of Go 1.3, Go does not support status code 308.
				code = 307
			}

			if tsr && r.RedirectTrailingSlash {
				var uri string
				if len(path) > 1 && path[len(path)-1] == '/' {
					uri = path[:len(path)-1]
				} else {
					uri = path + "/"
				}
				ctx.Redirect(uri, code)
				return
			}

			// Try to fix the request path
			if r.RedirectFixedPath {
				fixedPath, found := root.findCaseInsensitivePath(
					CleanPath(path),
					r.RedirectTrailingSlash,
				)
				if found {
					uri := string(fixedPath)
					ctx.Redirect(uri, code)
					return
				}
			}
		}
	}

	if method == "OPTIONS" {
		// Handle OPTIONS requests
		if r.HandleOPTIONS {
			if allow := r.allowed(path, method); len(allow) > 0 {
				ctx.Response.Header.Set("Allow", allow)
				return
			}
		}
	} else {
		// Handle 405
		if r.HandleMethodNotAllowed {
			if allow := r.allowed(path, method); len(allow) > 0 {
				ctx.Response.Header.Set("Allow", allow)
				if r.MethodNotAllowed != nil {
					r.MethodNotAllowed(ctx)
				} else {
					ctx.SetStatusCode(fasthttp.StatusMethodNotAllowed)
					ctx.SetContentTypeBytes(defaultContentType)
					ctx.SetBodyString(fasthttp.StatusMessage(fasthttp.StatusMethodNotAllowed))
				}
				return
			}
		}
	}

	// Handle 404
	if r.NotFound != nil {
		r.NotFound(ctx)
	} else {
		ctx.Error(fasthttp.StatusMessage(fasthttp.StatusNotFound),
			fasthttp.StatusNotFound)
	}
}
Пример #13
0
// request handler in net/http style, i.e. method bound to MyHandler struct.
func (h *MyHandler) HandleFastHTTP(ctx *fasthttp.RequestCtx) {
	// notice that we may access MyHandler properties here - see h.foobar.
	fmt.Fprintf(ctx, "Hello, world! Requested path is %q. Foobar is %q", ctx.Path(), h.foobar)
}