how to implement fasthttp framework - go

I want to start learning about the fasthttps server from this link https://github.com/valyala/fasthttp but I dont know that how will I implement a small piece of code in this framework. Can anybody tell me that how i will implement a small piece of code in this? example please.
Code I tried
package main
import "fmt"
type MyHandler struct {
foobar string
}
func main() {
// pass bound struct method to fasthttp
myHandler := &MyHandler{
foobar: "foobar",
}
fasthttp.ListenAndServe(":8080", myHandler.HandleFastHTTP)
// pass plain function to fasthttp
fasthttp.ListenAndServe(":8081", fastHTTPHandler)
}
// 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)
}
// request handler in fasthttp style, i.e. just plain function.
func fastHTTPHandler(ctx *fasthttp.RequestCtx) {
fmt.Fprintf(ctx, "Hi there! RequestURI is %q", ctx.RequestURI())
}
Can you please tell me that how I will implement this code.

This code seems to be working. I pasted it to a .go file, added:
import "github.com/valyala/fasthttp"
Then you have to install this package, either by using go get github.com/valyala/fasthttp or by writing a go.mod file if you want to use the new module support.
Then run this file and open localhost:8080 in a browser.
Maybe you have a more concrete question?
As #Volker said in a comment, for newbies it's highly recommended to stick to the standard library - net/http in this case; there are way more examples and code/tutorials you can find by googling, no need to install special packages, etc.

Related

GoDoc Example function for type/struct functions

Problem
I have written some example functions located in a *_test.go file to help clarify context for standalone public functions without issue. The problem on displaying comes when writing example functions for functions tied to a type.
Example
Here's a basic example of what I'm encountering.
Say we have a function in main.go like below:
type Client struct {
user string
ip string
}
func (c *Client) SendNotification(message string) error {
return nil
}
I want to create an example function for such in main_test.go, like below
func ExampleSendNotification() {
//Showoff code here
}
VSCode throws an error for that specific example, saying "ExampleSendNotification refers to unknown identifier: SendNotification". Also, it just does not appear as an example when running the godoc.
I've also tried this format:
func (c *Client) ExampleSendNotification() {
//Showoff code here
}
But then it just removes it as a test in VSCode, and doesn't appear
I found the answer just as I was finishing writing this. Thought I would still post for anybody else.
The trick is writing Example[Type]_[Method], so practically in my example, that would look like:
func ExampleClient_SendNotification() {
//Showoff code here
}

Golang fasthttp router custom logger

I'm playing with fasthttp and it's router, I have no issues with basic things, I have a working server and a router, that is the easy part.
The issue is with the logger, I would like to be able to customize that one, but it does not seem possible with the ctx.Logger() as it only takes a Printf argument and the format is not what I'm looking for.
Does anyone knows where in the documentation I can find a working example of what I want to do?
Example of code I currently have:
package server
import (
"github.com/fasthttp/router"
"github.com/valyala/fasthttp"
)
// Router will manage the routes of our API server
func Router() *router.Router {
r := router.New()
r.GET("/", index)
return r
}
func index(ctx *fasthttp.RequestCtx) {
ctx.Logger().Printf("/")
ctx.WriteString("Welcome!")
}
As I'm still trying my hand with the web servers and I still don't understand some things with it and Go also. So An example would be welcome.
For example I would like to be able to do something like that using a logger define in the main package:
package server
import (
"github.com/fasthttp/router"
"github.com/valyala/fasthttp"
"go.uber.org/zap"
)
// Router will manage the routes of our API server
func Router(loger *zap.Logger) *router.Router {
r := router.New()
r.GET("/", index)
return r
}
func index(ctx *fasthttp.RequestCtx) {
ctx.Logger().Printf("/") // Here should print in the zap format of my choice.
ctx.WriteString("Welcome!")
}
If you look at the source code, it's apparent that all you have is the ability to write standard Go-formatted strings:
func (cl *ctxLogger) Printf(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
ctxLoggerLock.Lock()
cl.logger.Printf("%.3f %s - %s", time.Since(cl.ctx.ConnTime()).Seconds(), cl.ctx.String(), msg)
ctxLoggerLock.Unlock()
}
The logger simply adds some additional information from the context. So further cutomisation beyond the standard Go formatting does not seem possible. I'm not sure what "zap format of my choice" is, so I can't say if there's a workaround or even if standard Go formatting options will serve for you here.

Function as argument, access inner parameter

The package valyala/fasthttp implements the following function type:
type RequestHandler func(ctx *RequestCtx)
It is used in buaazp/fasthttprouter like this:
func (r *Router) Handle(method, path string, handle fasthttp.RequestHandler) {
//...
}
I am trying to wrap these like this (open for suggestions on implementation):
//myapp/router
type Request struct {
fasthttp.RequestCtx
}
type RequestHandler func(*Request)
func Handle(method string, path string, handler RequestHandler) {
//I need to access the fasthttp.RequestCtx stuff in here...
}
How can I achieve this? Or, if this is not the way to go at all, how can I achieve my goal as mentioned below for a router package?
BACKGROUND
Goal: My wish is to wrap tooling packages (sessions, database, routing, etc.) in order to make my app agnostic to the implementation of these packages. I wish to do this primarily for the purpose of being able to extend these with domain-specific functionality, and being able to switch one 3rd party lib for another, if I ever would need to do so. It also makes debugging and logging easier.
Method: I create native types and functions, which map to the functionality of the imported packages.
Problem: I am stuck on how to wrap a foreign (i.e. imported) function type properly.
At all your idea looks very good. Some things you could change:
//myapp/router
// Using a composition is idiomatic go code
// this should work. It can't get better.
type Request struct {
fasthttp.RequestCtx
}
// I would make the RequestHandler as a real Handler. In go it would be
// a interface
type RequestHandler interface{
Request(*Request)
}
// If you have a function, which needs to access parameters from `Request`
// you should take this as an input.
func Handle(method string, path string, req *Request) {
//Access Request via req.Request ...
}
Because if you pass a function or an interface into your function, which needs also Request as input the caller needs to create that before he calls your Handle function. Why not change that function just for the input you really need?

In go, Manually Invoke an http.FileServer and/or What is an http Handler

I'm an experienced programmer, but new to go. Apologies in advance if this is an obvious question or well tread path. I'm still getting my bearings in the language and its semantics.
I'm trying to create a web server in go that
Examines the HTTP request
Based on the results of the request, serves a specific static folder
i.e., something where the simplified pseudo code looks like
import (
"io"
"net/http"
"fmt"
"strings"
"encoding/base64"
)
func examineRequest(request *http.Request) {
//looks at request header
if(request headers have one thing){
return "foo"
}
return "bar"
}
func processRequest(responseWriter http.ResponseWriter, request *http.Request) {
folderToServe = examineRequest(request);
if folderToServe == "bar" {
//serve static files from the ./static/bar folder
//go freaks out if I try these
//http.Handle("/", http.FileServer(http.Dir("./static/bar")))
//http.FileServer(http.Dir("./static/bar")()
}
else if folderToServer == "foo" {
//serve static files from the ./static/foo folder
//go freaks out if I try these
//http.Handle("/", http.FileServer(http.Dir("./static/foo")))
//http.FileServer(http.Dir("./static/foo")()
}
}
func main(){
http.HandleFunc("/", processRequest)
//http.Handle("/", http.FileServer(http.Dir("./static")))
}
Experienced go programmers may have already spotted the problem. I'm performing my examination in processRequest, and because of that, its too late to to call Handle -- however, you can't register more than one handle for the same path in go, and nested handle calls freak go out.
I though the handler might be similar to an anonymous function in other languages and tried call it -- but go did like that either.
So -- is there a way to manually invoke the handler returned from the call to http.FileServer(http.Dir("./static"))?
Is that even the right question to be asking here?
What exactly is a handler in the context of the http module?
Use http.FileServer(http.Dir("./static/foo")).ServeHTTP(w, req).
//edit
http.FileServer returns an http.Handler which in turn provides the ServerHTTP method.

Capturing net.Listener passed to http.Server.Serve

I'd like to extend the http.Server functionality by performing a graceful shutdown and some other gadgets that I would share across my HTTP services. Currently my code says more or less:
type MyServer struct {
server *http.Server
// ...
}
func (s *MyServer) ListenAndServe() {
// Create listener and pass to s.server.Serve()
}
This works great, but requires exposing all necessary methods and variables of http.Server manually.
Wrapping most of the methods wouldn't be a big problem, but I can't find a sensible way to expose access to http.Server.ListenAndServeTLS without actually copying implementation from the source. The last line in the method says srv.Serve(tlsListener) and I'd love to provide my own Serve method, so modification of net.Listener is possible before passing it to http.Server.Serve.
I started to pencil my wrapper by putting simply:
type MyServer struct {
http.Server
}
func (s *MyServer) Serve(l net.Listener) {
// Wrap l with MyListener, pass to s.Server.Serve()
}
but obviously neither http.ListenAndServe nor http.ListenAndServeTLS would start using my implementation of Serve. And I'd like to ask them to... Is there any way I can tackle the problem or does the design of http.Server effectively prevent me from solving this?
Hacks welcome: even if I don't use them in production, I'll gain some knowledge.
The http.ListenAndServe* methods will work on the embedded type. The other way around works:
type MyServer struct {
http.Server
// ...
}
func (s *MyServer) ListenAndServe() error {
// create listener
// s.Server.Serve(s.listener)
}
func (s *MyServer) ListenAndServeTLS() error {
// create listener
// s.Server.Serve(s.tlsListener)
}

Resources