Skip to content

The proxy middleware is not forwarding requests #1808

Closed
@gustavosbarreto

Description

@gustavosbarreto

Issue Description

The proxy middleware is not forwarding requests

Expected behaviour

Middleware should be called to forward request to the another echo instance

> GET http://localhost:8081/resource/1
< HTTP 200

> PUT http://localhost:8081/resource/1
< HTTP 200

Actual behaviour

Middleware is not called and I'm getting back a 405 status code (method not allowed)

> GET http://localhost:8081/resource/1
< HTTP 405

> PUT http://localhost:8081/resource/1
< HTTP 200

Steps to reproduce

GET http://localhost:8081/resource/1

Working code to debug

package main

import (
	"net/http"
	"net/url"

	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
)

func main() {
        // echo instance 1
	e1 := echo.New()
	g1 := e1.Group("/api")
	g1.GET("/resource/:id", func(c echo.Context) error {
		return c.NoContent(http.StatusOK)
	})

	e1url, _ := url.Parse("http://localhost:8080")

	// echo instance 2
	e2 := echo.New()
	g2 := e2.Group("/api")
	g2.PUT("/resource/:id", func(c echo.Context) error {
		return c.NoContent(http.StatusOK)
	})
	g2.Use(middleware.Proxy(middleware.NewRoundRobinBalancer([]*middleware.ProxyTarget{
		{
			URL: e1url, // forward all requests with /api prefix to server running on port 8080 (except PUT /resource/:id)
		},
	})))

	go e1.Start(":8080")
	e2.Start(":8081")
}

Activity

aldas

aldas commented on Mar 12, 2021

@aldas
Contributor

This is current limitation of Echo router. It finds match for /resource/:id route and stops searching for matching path. Then tries to look up method but GET (only PUT is for that path) is not registered and sends 405

Unless you want to wait for fix you can work around this problem by using skipper method for proxy and registering additional Any route on echo that does proxying. This Any will not be called but it will fool router to match and execute proxy middleware.

func TestProxy(t *testing.T) {
	targetEcho := echo.New()
	g1 := targetEcho.Group("/api")

	g1.Any("/*", func(c echo.Context) error {
		fmt.Println("targetEcho: " + c.Path())
		return c.String(http.StatusOK, fmt.Sprintf("response from targetEcho: %v\n", c.Path()))
	})

	g1.GET("/resource/:id", func(c echo.Context) error {
		fmt.Println("targetEcho: " + c.Path())
		return c.String(http.StatusOK, fmt.Sprintf("response from targetEcho: %v\n", c.Path()))
	})

	e1url, _ := url.Parse("http://localhost:8084")

	proxyingEcho := echo.New()
	g2 := proxyingEcho.Group("/api")
	g2.Use(middleware.ProxyWithConfig(middleware.ProxyConfig{
		Skipper: func(e echo.Context) bool {
			if e.Request().Method == http.MethodPut && strings.HasPrefix(e.Request().URL.Path, "/api/resource/") {
				return true
			}
			return false
		},
		Balancer: middleware.NewRoundRobinBalancer([]*middleware.ProxyTarget{
			{
				URL: e1url, // forward all requests with /api prefix to server running on port 8084 (except PUT /resource/:id)
			},
		}),
	}),
	)
	g2.Any("/resource/:id", func(c echo.Context) error {
		return errors.New("never reached")
	})
	g2.PUT("/resource/:id", func(c echo.Context) error {
		fmt.Println("proxyingEcho: " + c.Path())
		return c.String(http.StatusOK, fmt.Sprintf("response from proxyingEcho: %v\n", c.Path()))
	})

	go targetEcho.Start(":8084")
	if err := proxyingEcho.Start(":8088"); err != nil {
		log.Fatal(err)
	}
}
x@x:~/code$ curl -X GET http://localhost:8088/api/resource/1
response from targetEcho: /api/resource/:id

x@x:~/code$ curl -X PUT http://localhost:8088/api/resource/1
response from proxyingEcho: /api/resource/:id

x@x:~/code$ curl -X PUT http://localhost:8088/api/should_proxy
response from targetEcho: /api/*

x@x:~/code$ curl -X GET http://localhost:8088/api/should_proxy
response from targetEcho: /api/*
gustavosbarreto

gustavosbarreto commented on Mar 12, 2021

@gustavosbarreto
Author

Unless you want to wait for fix you can work around this problem by using skipper method for proxy and registering additional Any route on echo that does proxying. This Any will not be called but it will fool router to match and execute proxy middleware.

Is there any future plan to fix this issue?

added a commit that references this issue on Mar 16, 2021
546a1e5
added a commit that references this issue on Apr 27, 2021
6430665
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @gustavosbarreto@aldas

      Issue actions

        The proxy middleware is not forwarding requests · Issue #1808 · labstack/echo