Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help with intercepting middleware, and writing responses #796

Closed
gfffrtt opened this issue Jun 15, 2024 · 4 comments
Closed

Help with intercepting middleware, and writing responses #796

gfffrtt opened this issue Jun 15, 2024 · 4 comments

Comments

@gfffrtt
Copy link

gfffrtt commented Jun 15, 2024

Hello everyone, I'm just building a project with templ and go, and need help with understanding something.

func isHtml(w http.ResponseWriter) bool {
	return strings.HasPrefix(w.Header().Get("content-type"), "text/html")
}

type App struct {
	Router *http.ServeMux
}

func NewApp() *App {
	return &App{
		Router: http.NewServeMux(),
	}
}

func (a *App) Middleware(next http.HandlerFunc) http.HandlerFunc {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if !isHtml(w) {
			next.ServeHTTP(w, r)
		}

		w.Write([]byte("<p>Loading...</p>"))
		next.ServeHTTP(w, r)
	})
}

func (a *App) Component(route string, handler http.HandlerFunc) {
	a.Router.HandleFunc(route, a.Middleware(handler))
}

func (a *App) Listen(port string) {
	http.ListenAndServe(port, a.Router)
}

func main() {
	app := NewApp()

	app.Component("/", func(w http.ResponseWriter, r *http.Request) {
		views.Component().Render(context.Background(), w)
	})

	app.Listen(":3000")
}

Here is the code I've simplified it a bit but this is the essence of it, I'm adding some middleware that intercepts "text/html" responses and writes some extra html on the, but the result is unexpected, instead of adding the extra html to the bottom of the page, I'm getting a duplication of the html.

image

Am I doing something really wrong here, or is this expected?

@joerdav
Copy link
Collaborator

joerdav commented Jun 15, 2024

I believe you might need to return here:

if !isHtml(w) {
			next.ServeHTTP(w, r)
			return
}

@gfffrtt
Copy link
Author

gfffrtt commented Jun 15, 2024

I believe you might need to return here:

if !isHtml(w) {
			next.ServeHTTP(w, r)
			return
}

Yes it was that, but now I cant get the content type from the header, every time I print it print []map

func isHtml(w http.ResponseWriter) bool {
	return strings.HasPrefix(w.Header().Get("Content-Type"), "text/html")
}

type App struct {
	Router *chi.Mux
}

func NewApp() *App {
	router := chi.NewRouter()
	router.Use(middleware.Logger)
	return &App{
		Router: chi.NewRouter(),
	}
}

func (a *App) Middleware(next http.HandlerFunc) http.HandlerFunc {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if !isHtml(w) {
			next.ServeHTTP(w, r)
			return
		}

		w.Write([]byte("<p>Loading...</p>"))
		next.ServeHTTP(w, r)
	})
}

func (a *App) Component(route string, handler http.HandlerFunc) {
	a.Router.Get(route, a.Middleware(handler))
}

func (a *App) Listen(port string) {
	http.ListenAndServe(port, a.Router)
}

func main() {
	app := NewApp()

	app.Component("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Add("Content-Type", "text/html")
		views.Component().Render(context.Background(), w)
	})

	app.Listen(":3000")
}

@joerdav
Copy link
Collaborator

joerdav commented Jun 16, 2024

This may not be the only issue, but I can see that you are writing to the response before setting headers, you should set the header in the middleware.

@gfffrtt
Copy link
Author

gfffrtt commented Jun 16, 2024

@joerdav Thank you for your help, but I figured out what I actually had to do, what I wanted is to intercept the reponse, so I had to first run the next handler than modify the response if it is html, but thank you man.

image

@gfffrtt gfffrtt closed this as completed Jun 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants