fasthttp icon indicating copy to clipboard operation
fasthttp copied to clipboard

How to hijack writer?

Open ivanjaros opened this issue 2 years ago • 4 comments

In standard http i hijack the writer by wrapping it into my struct and log response data(method, path, code..) based on response codes. It does not seem that fasthttp has a way to set the response writer. Is that so or am I overlooking a method somewhere?

ivanjaros avatar Jan 18 '23 09:01 ivanjaros

Maybe you can use this way wrapper and fasthttp and net/http are not the same here.

import (
	"flag"
	"fmt"
	"log"

	"github.com/valyala/fasthttp"
)

var addr = flag.String("addr", ":8080", "TCP address to listen to")

func main() {
	flag.Parse()

	h := requestHandler
	if err := fasthttp.ListenAndServe(*addr, CORS(h)); err != nil {
		log.Fatalf("Error in ListenAndServe: %v", err)
	}
}

func CORS(next fasthttp.RequestHandler) fasthttp.RequestHandler {
	return func(ctx *fasthttp.RequestCtx) {

		ctx.Response.Header.Set("Access-Control-Allow-Credentials", corsAllowCredentials)
		ctx.Response.Header.Set("Access-Control-Allow-Headers", corsAllowHeaders)
		ctx.Response.Header.Set("Access-Control-Allow-Methods", corsAllowMethods)
		ctx.Response.Header.Set("Access-Control-Allow-Origin", corsAllowOrigin)

		next(ctx)
	}
}

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)
}

li-jin-gou avatar Jan 21 '23 12:01 li-jin-gou

That is not what I asked. I want to hijack Write() method, not add headers with wrappers. It's not just for logging but also for wrapping responses with etag handler that allows me to bypass handlers altogether and return http 304.

ivanjaros avatar Jan 21 '23 13:01 ivanjaros

Tweaking the logic of the wrap function should work, the above is just a sample code. It can modify the body, as well as the status code, header.

li-jin-gou avatar Jan 21 '23 13:01 li-jin-gou

Not true in general

You can rewrite response writer after next call (see my example), but streams or early flush() breaks this logic and atm i dont know how to solve this issue

Could someone post an example with hijack writer to replace passwords by asterisks (*)?

alexdyukov avatar Oct 25 '23 12:10 alexdyukov