Code Monkey home page Code Monkey logo

Comments (16)

ricmoreira avatar ricmoreira commented on May 19, 2024 2

Hello,

I have finally a working example:

package main

import (
	"flag"
	"io"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/gin-gonic/gin"
	"gopkg.in/gin-contrib/cors.v1"

	"api_gateway_admin/middleware"

	"github.com/devopsfaith/krakend/config"
	"github.com/devopsfaith/krakend/logging"
	"github.com/devopsfaith/krakend/proxy"
	krakendgin "github.com/devopsfaith/krakend/router/gin"
)

func main() {
	port := flag.Int("p", 0, "Port of the service")
	logLevel := flag.String("l", "ERROR", "Logging level")
	debug := flag.Bool("d", false, "Enable the debug")
	configFile := flag.String("c", "{{path to file}}/configuration.json", "Path to the configuration filename")
	flag.Parse()

	parser := config.NewParser()
	serviceConfig, err := parser.Parse(*configFile)
	if err != nil {
		log.Fatal("ERROR:", err.Error())
	}

	// render that does not change response
	noTransformRender := func(c *gin.Context, response *proxy.Response) {
		if response == nil {
			c.Status(http.StatusInternalServerError)
			return
		}
		c.Status(response.Metadata.StatusCode)
		for k, v := range response.Metadata.Headers {
			c.Header(k, v[0])
		}
		io.Copy(c.Writer, response.Io)
	}

	// register the render at the router level
	krakendgin.RegisterRender("NoTransformRender", noTransformRender)

	// assign NoTransformRender to all endpoints loaded from config file
	for _, v := range serviceConfig.Endpoints {
		v.OutputEncoding = "NoTransformRender"
	}

	serviceConfig.Debug = serviceConfig.Debug || *debug
	if *port != 0 {
		serviceConfig.Port = *port
	}

	logger, err := logging.NewLogger(*logLevel, os.Stdout, "[KRAKEND]")
	if err != nil {
		log.Println("ERROR:", err.Error())
		return
	}

	backendFactory := func(backendCfg *config.Backend) proxy.Proxy {

		// status handler that does change status
		ns := proxy.NoOpHTTPStatusHandler

		// the default request executor
		re := proxy.DefaultHTTPRequestExecutor(proxy.NewHTTPClient)

		// response parser that copies Backend response body to proxy Response IO reader
		rp := proxy.NoOpHTTPResponseParser

		// build and return the new backend proxy
		return proxy.NewHTTPProxyDetailed(backendCfg, re, ns, rp)
	}

	// build the pipes on top of the custom backend factory
	proxyFactory := proxy.NewDefaultFactory(backendFactory, logger)

	engine := gin.Default()

	routerConfig := krakendgin.Config{
		Engine:         engine,
		ProxyFactory:   proxyFactory,
		Logger:         logger,
		HandlerFactory: krakendgin.EndpointHandler,
		Middlewares: []gin.HandlerFunc{
			cors.New(cors.Config{
				AllowOrigins: []string{"http://localhost:4200", "http://127.0.0.1:4200", "http://localhost:8089", "http://localhost:8069", "http://localhost:8080", "http://localhost:8099"},
				AllowMethods: []string{"PUT", "PATCH", "POST", "GET", "DELETE", "OPTIONS"},
				AllowHeaders: []string{"Accept",
					"Accept-Encoding",
					"Accept-Language",
					"access-control-allow-origin",
					"Access-Control-Request-Headers",
					"Access-Control-Request-Method",
					"authorization",
					"Cache-Control",
					"Connection",
					"Content-Type",
					"Host",
					"If-Modified-Since",
					"Keep-Alive",
					"Key",
					"Origin",
					"Pragma",
					"User-Agent",
					"X-Custom-Header"},
				ExposeHeaders:    []string{"Content-Length", "Content-Type"},
				AllowCredentials: true,
				MaxAge:           48 * time.Hour,
			}),
			middleware.JwtCheck(),
		},
	}

	routerFactory := krakendgin.NewFactory(routerConfig)

	routerFactory.New().Run(serviceConfig)
}

Thank you very much for your quick feedback.
Congrats for your great project.

Thanks!

from krakend-ce.

nadim500 avatar nadim500 commented on May 19, 2024 2

Hello.

I am using the example of ricomeira to return the original status and response of a request, which works well, but when doing a merge of three requests, it does not show any results

image

main.go

package main

import (
	"flag"
	"io"
	"log"
	"net/http"
	"os"

	limit "github.com/aviddiviner/gin-limit"
	"github.com/gin-gonic/gin"

	"github.com/devopsfaith/krakend/config"
	"github.com/devopsfaith/krakend/logging"
	"github.com/devopsfaith/krakend/proxy"
	"github.com/devopsfaith/krakend/router"
	krakendgin "github.com/devopsfaith/krakend/router/gin"
	"github.com/devopsfaith/krakend/transport/http/client"
)

func main() {
	port := flag.Int("p", 0, "Port of the service")
	logLevel := flag.String("l", "ERROR", "Logging level")
	debug := flag.Bool("d", false, "Enable the debug")
	configFile := flag.String("c", "./krakend.json", "Path to the configuration filename")
	flag.Parse()

	parser := config.NewParser()
	serviceConfig, err := parser.Parse(*configFile)
	if err != nil {
		log.Fatal("ERROR:", err.Error())
	}

	// render that does not change response
	noTransformRender := func(c *gin.Context, response *proxy.Response) {
		if response == nil {
			c.Status(http.StatusInternalServerError)
			return
		}
		c.Status(response.Metadata.StatusCode)
		for k, v := range response.Metadata.Headers {
			c.Header(k, v[0])
		}
		io.Copy(c.Writer, response.Io)
	}

	// register the render at the router level
	krakendgin.RegisterRender("NoTransformRender", noTransformRender)

	serviceConfig.Debug = serviceConfig.Debug || *debug
	if *port != 0 {
		serviceConfig.Port = *port
	}

	logger, err := logging.NewLogger(*logLevel, os.Stdout, "[KRAKEND]")
	if err != nil {
		log.Fatal("ERROR:", err.Error())
	}

	backendFactory := func(backendCfg *config.Backend) proxy.Proxy {

		// status handler that does change status
		ns := client.NoOpHTTPStatusHandler

		// the default request executor
		re := client.DefaultHTTPRequestExecutor(client.NewHTTPClient)

		// response parser that copies Backend response body to proxy Response IO reader
		rp := proxy.NoOpHTTPResponseParser

		// build and return the new backend proxy
		return proxy.NewHTTPProxyDetailed(backendCfg, re, ns, rp)
	}

	// build the pipes on top of the custom backend factory
	proxyFactory := proxy.NewDefaultFactory(backendFactory, logger)

	// store := cache.NewInMemoryStore(time.Minute)

	mws := []gin.HandlerFunc{
		limit.MaxAllowed(20),
	}

	// routerFactory := krakendgin.DefaultFactory(proxy.DefaultFactory(logger), logger)

	routerFactory := krakendgin.NewFactory(krakendgin.Config{
		Engine:         gin.Default(),
		ProxyFactory:   proxyFactory,
		Middlewares:    mws,
		Logger:         logger,
		HandlerFactory: krakendgin.EndpointHandler,
		RunServer:      router.RunServer,
	})

	routerFactory.New().Run(serviceConfig)
}

krakend.json

{
    "version": 2,
    "name": "kraken_test",
    "port": 8000,
    "cache_ttl": "3600s",
    "timeout": "3000ms",
    "extra_config": {
        "github_com/devopsfaith/krakend-gologging": {
            "level": "DEBUG",
            "prefix": "[KRAKEND]",
            "syslog": false,
            "stdout": true
        },
        "github_com/devopsfaith/krakend-metrics": {
            "collection_time": "60s",
            "proxy_disabled": false,
            "router_disabled": false,
            "backend_disabled": false,
            "endpoint_disabled": false,
            "listen_address": ":8090"
        },
        "github_com/devopsfaith/krakend-cors": {
            "allow_origins": [
                "http://192.168.99.100:3000",
                "http://localhost:8080"
            ],
            "allow_methods": [
                "POST",
                "GET"
            ],
            "allow_headers": [
                "Origin",
                "Authorization",
                "Content-Type"
            ],
            "expose_headers": [
                "Content-Length"
            ],
            "max_age": "12h"
        }
    },
    "endpoints": [
        {
            "endpoint": "/abc",
            "method": "GET",
            "headers_to_pass": [
                "Authorization",
                "Content-Type"
            ],
            "backend": [
                {
                    "host": [
                        "http://127.0.0.1:8080"
                    ],
                    "url_pattern": "/v1/test/a",
                    "encoding": "json"
                },
                {
                    "host": [
                        "http://127.0.0.1:8080"
                    ],
                    "url_pattern": "/v1/test/b",
                    "encoding": "json"
                },
                {
                    "host": [
                        "http://127.0.0.1:8080"
                    ],
                    "url_pattern": "/v1/test/c",
                    "encoding": "json"
                }
            ]
        },
        {
            "endpoint": "/200",
            "method": "GET",
            "headers_to_pass": [
                "Authorization",
                "Content-Type"
            ],
            "backend": [
                {
                    "host": [
                        "http://127.0.0.1:8080"
                    ],
                    "url_pattern": "/v1/test/200",
                    "encoding": "json",
                    "extra_config": {
                        "github.com/devopsfaith/krakend-ratelimit/juju/proxy": {
                            "maxRate": 1,
                            "capacity": 1
                        },
                        "github.com/devopsfaith/krakend-circuitbreaker/gobreaker": {
                            "interval": 60,
                            "timeout": 10,
                            "maxErrors": 1
                        }
                    }
                }
            ],
            "output_encoding": "NoTransformRender"
        },
        {
            "endpoint": "/201",
            "method": "GET",
            "headers_to_pass": [
                "Authorization",
                "Content-Type"
            ],
            "backend": [
                {
                    "host": [
                        "http://127.0.0.1:8080"
                    ],
                    "url_pattern": "/v1/test/201",
                    "encoding": "json",
                    "extra_config": {
                        "github.com/devopsfaith/krakend-ratelimit/juju/proxy": {
                            "maxRate": 1,
                            "capacity": 1
                        },
                        "github.com/devopsfaith/krakend-circuitbreaker/gobreaker": {
                            "interval": 60,
                            "timeout": 10,
                            "maxErrors": 1
                        }
                    }
                }
            ],
            "output_encoding": "NoTransformRender"
        },
        {
            "endpoint": "/400",
            "method": "GET",
            "headers_to_pass": [
                "Authorization",
                "Content-Type"
            ],
            "backend": [
                {
                    "host": [
                        "http://127.0.0.1:8080"
                    ],
                    "url_pattern": "/v1/test/400",
                    "encoding": "json",
                    "extra_config": {
                        "github.com/devopsfaith/krakend-ratelimit/juju/proxy": {
                            "maxRate": 1,
                            "capacity": 1
                        },
                        "github.com/devopsfaith/krakend-circuitbreaker/gobreaker": {
                            "interval": 60,
                            "timeout": 10,
                            "maxErrors": 1
                        }
                    }
                }
            ],
            "output_encoding": "NoTransformRender"
        },
        {
            "endpoint": "/401",
            "method": "GET",
            "headers_to_pass": [
                "Authorization",
                "Content-Type"
            ],
            "backend": [
                {
                    "host": [
                        "http://127.0.0.1:8080"
                    ],
                    "url_pattern": "/v1/test/401",
                    "encoding": "json",
                    "extra_config": {
                        "github.com/devopsfaith/krakend-ratelimit/juju/proxy": {
                            "maxRate": 1,
                            "capacity": 1
                        },
                        "github.com/devopsfaith/krakend-circuitbreaker/gobreaker": {
                            "interval": 60,
                            "timeout": 10,
                            "maxErrors": 1
                        }
                    }
                }
            ],
            "output_encoding": "NoTransformRender"
        },
        {
            "endpoint": "/404",
            "method": "GET",
            "headers_to_pass": [
                "Authorization",
                "Content-Type"
            ],
            "backend": [
                {
                    "host": [
                        "http://127.0.0.1:8080"
                    ],
                    "url_pattern": "/v1/test/404",
                    "encoding": "json",
                    "extra_config": {
                        "github.com/devopsfaith/krakend-ratelimit/juju/proxy": {
                            "maxRate": 1,
                            "capacity": 1
                        },
                        "github.com/devopsfaith/krakend-circuitbreaker/gobreaker": {
                            "interval": 60,
                            "timeout": 10,
                            "maxErrors": 1
                        }
                    }
                }
            ],
            "output_encoding": "NoTransformRender"
        },
        {
            "endpoint": "/500",
            "method": "GET",
            "headers_to_pass": [
                "Authorization",
                "Content-Type"
            ],
            "backend": [
                {
                    "host": [
                        "http://127.0.0.1:8080"
                    ],
                    "url_pattern": "/v1/test/500",
                    "encoding": "json",
                    "extra_config": {
                        "github.com/devopsfaith/krakend-ratelimit/juju/proxy": {
                            "maxRate": 1,
                            "capacity": 1
                        },
                        "github.com/devopsfaith/krakend-circuitbreaker/gobreaker": {
                            "interval": 60,
                            "timeout": 10,
                            "maxErrors": 1
                        }
                    }
                }
            ],
            "output_encoding": "NoTransformRender"
        }
    ]
}

This is my test server where I generate the APIs : webnode

Could you please help me?
Thank you.

from krakend-ce.

taik0 avatar taik0 commented on May 19, 2024

Hi @ricmoreira

Check this link for information about this behaviour:
http://www.krakend.io/docs/faq/#i-am-getting-a-500-status-when-the-backend-returns-anything-but-200-201-or-redirects.

Although now you can use the NoOpHTTPStatusHandler to send the same response of the backend.

from krakend-ce.

ricmoreira avatar ricmoreira commented on May 19, 2024

Thank you for the quick response.
I've been through that documentation and I've understood that I've to inject my "own HTTPStatusHandler". In this case, as you said, the "NoOpHTTPStatusHandler" would solve my issue.
But where do I put it?

from krakend-ce.

taik0 avatar taik0 commented on May 19, 2024

You need to add your own custom BackendFactory if you are not using the default Factories.

NewHTTPProxyDetailed will allow you to add your custom status handler.

Check this link for an example:
luraproject/lura#102 (comment)

from krakend-ce.

ricmoreira avatar ricmoreira commented on May 19, 2024

This is what I've done now:

(...)
	backendFactory := func(backendCfg *config.Backend) proxy.Proxy {

		ns := proxy.NoOpHTTPStatusHandler

		// the default request executor
		re := proxy.DefaultHTTPRequestExecutor(proxy. NewHTTPClient)
	
		// default entity formatter for the given backend
		ef := proxy.NewEntityFormatter(backendCfg)
	
		// the default response parser with the required config
		rp := proxy.DefaultHTTPResponseParserFactory(proxy.HTTPResponseParserConfig{backendCfg.Decoder, ef})
	
		// build and return the new backend proxy
		return proxy.NewHTTPProxyDetailed(backendCfg, re, ns, rp)
	}

	// build the pipes on top of the custom backend factory
	proxyFactory := proxy.NewDefaultFactory(backendFactory, logger)

	routerFactory := krakendgin.NewFactory(krakendgin.Config{
		Engine:         gin.Default(),
		ProxyFactory:   proxyFactory,

(...)

I've managed to get the response body but now an error response (e.g. 400) is transformed to a 200 response.

from krakend-ce.

kpacha avatar kpacha commented on May 19, 2024

hi, @ricmoreira

the renders are responsible for the behaviour you're describing (as you can see here: https://github.com/devopsfaith/krakend/blob/master/router/gin/render.go#L90) but you can inject your own render at the router level by registering it with gin.RegisterRender and adding its name in the endpoint configuration (config.EndpointConfig.OutputEncoding).

your implementation should copy the proxy.Response.Metadata.StatusCode like in https://github.com/devopsfaith/krakend/blob/master/router/gin/render.go#L124

on the other hand, please notice you can use the CORS module already available in the master branch. the JOSE package is not ready yet, but we expect to finish it in a couple of weeks.

cheers!

from krakend-ce.

kpacha avatar kpacha commented on May 19, 2024

@ricmoreira that's amazing!

remember you can avoid some of that code by just defining the extra_config for the CORS module like in this example: https://github.com/devopsfaith/krakend-cors#configuration-example

also, you can add "output_encoding": "NoTransformRender" to each endpoint definition in the same config file, so you'll have more control.

enjoy playing with the KrakenD!!!

from krakend-ce.

ricmoreira avatar ricmoreira commented on May 19, 2024

Thank you very much!
Much better now.

I'll leave here my main and my config file for whoever needs an example.

main.go

package main

import (
	"flag"
	"io"
	"log"
	"net/http"
	"os"

	"github.com/gin-gonic/gin"

	"api_gateway_admin/middleware"

	"github.com/devopsfaith/krakend/config"
	"github.com/devopsfaith/krakend/logging"
	"github.com/devopsfaith/krakend/proxy"
	krakendgin "github.com/devopsfaith/krakend/router/gin"
)

func main() {
	port := flag.Int("p", 0, "Port of the service")
	logLevel := flag.String("l", "ERROR", "Logging level")
	debug := flag.Bool("d", false, "Enable the debug")
	configFile := flag.String("c", "{{path to file}}/configuration.json", "Path to the configuration filename")
	flag.Parse()

	parser := config.NewParser()
	serviceConfig, err := parser.Parse(*configFile)
	if err != nil {
		log.Fatal("ERROR:", err.Error())
	}

	// render that does not change response
	noTransformRender := func(c *gin.Context, response *proxy.Response) {
		if response == nil {
			c.Status(http.StatusInternalServerError)
			return
		}
		c.Status(response.Metadata.StatusCode)
		for k, v := range response.Metadata.Headers {
			c.Header(k, v[0])
		}
		io.Copy(c.Writer, response.Io)
	}

	// register the render at the router level
	krakendgin.RegisterRender("NoTransformRender", noTransformRender)

	serviceConfig.Debug = serviceConfig.Debug || *debug
	if *port != 0 {
		serviceConfig.Port = *port
	}

	logger, err := logging.NewLogger(*logLevel, os.Stdout, "[KRAKEND]")
	if err != nil {
		log.Println("ERROR:", err.Error())
		return
	}

	backendFactory := func(backendCfg *config.Backend) proxy.Proxy {

		// status handler that does change status
		ns := proxy.NoOpHTTPStatusHandler

		// the default request executor
		re := proxy.DefaultHTTPRequestExecutor(proxy.NewHTTPClient)

		// response parser that copies Backend response body to proxy Response IO reader
		rp := proxy.NoOpHTTPResponseParser

		// build and return the new backend proxy
		return proxy.NewHTTPProxyDetailed(backendCfg, re, ns, rp)
	}

	// build the pipes on top of the custom backend factory
	proxyFactory := proxy.NewDefaultFactory(backendFactory, logger)

	engine := gin.Default()

	routerConfig := krakendgin.Config{
		Engine:         engine,
		ProxyFactory:   proxyFactory,
		Logger:         logger,
		HandlerFactory: krakendgin.EndpointHandler,
		Middlewares: []gin.HandlerFunc{
			middleware.JwtCheck(),
		},
	}

	routerFactory := krakendgin.NewFactory(routerConfig)

	routerFactory.New().Run(serviceConfig)
}

configuration.json

{
  "version": 2,
  "name": "ecommerce-service",
  "port": 8080,
  "cache_ttl": "1s",
  "timeout": "10s",
  "host": [
    "http://localhost"
  ],
  "extra_config": {
    "github_com/devopsfaith/krakend-cors": {
      "allow_origins": [ "http://localhost:4200", "http://127.0.0.1:4200", "http://localhost:8089", "http://localhost:8069", "http://localhost:8080", "http://localhost:8099" ],
      "allow_methods": [ "PUT", "PATCH", "POST", "GET", "DELETE", "OPTIONS"],
      "allow_heathers": [ "Accept-Encoding",
        "Accept-Language",
        "access-control-allow-origin",
        "Access-Control-Request-Headers",
        "Access-Control-Request-Method",
        "authorization",
        "Cache-Control",
        "Connection",
        "Content-Type",
        "Host",
        "If-Modified-Since",
        "Keep-Alive",
        "Key",
        "Origin",
        "Pragma",
        "User-Agent",
        "X-Custom-Header"],
      "max_age": "48h",
      "allow_credentials": true,
      "expose_headers": ["Content-Length", "Content-Type"]
    }
  },
  "endpoints": [
    {
      "endpoint": "/api/v1/product",
      "timeout": "800ms",
      "method": "POST",
      "backend": [
        {
          "url_pattern": "/api/v1/product",
          "host": [
            "http://localhost:8069"
          ]
        }
      ],
      "output_encoding": "NoTransformRender"
    },
    {
      "endpoint": "/api/v1/product",
      "timeout": "800ms",
      "method": "GET",
      "querystring_params": [
        "page",
        "per_page"
      ],
      "backend": [
        {
          "url_pattern": "/api/v1/product",
          "host": [
            "http://localhost:8069"
          ]
        }
      ],
      "output_encoding": "NoTransformRender"
    },
    {
      "endpoint": "/api/v1/saft/upload",
      "timeout": "800ms",
      "method": "POST",
      "headers_to_pass": [
        "content-type",
        "Content-Type"
      ],
      "backend": [
        {
          "url_pattern": "/api/v1/saft/upload",
          "host": [
            "http://localhost:8099"
          ]
        }
      ],
      "output_encoding": "NoTransformRender"
    }
  ]
}

from krakend-ce.

dominiksimek avatar dominiksimek commented on May 19, 2024

Hello,
I'm trying to modify default krakend-ce backendFactory to make it works with NoOpHTTPStatusHandler. Original backendFactory code is (backend_factory.go):

// NewBackendFactory creates a BackendFactory by stacking all the available middlewares:
// - oauth2 client credentials
// - martian
// - rate-limit
// - circuit breaker
// - metrics collector
// - opencensus collector
func NewBackendFactory(logger logging.Logger, metricCollector *metrics.Metrics) proxy.BackendFactory {
	requestExecutorFactory := func(cfg *config.Backend) client.HTTPRequestExecutor {
		var clientFactory client.HTTPClientFactory
		if _, ok := cfg.ExtraConfig[oauth2client.Namespace]; ok {
			clientFactory = oauth2client.NewHTTPClient(cfg)
		} else {
			clientFactory = httpcache.NewHTTPClient(cfg)
		}
		return opencensus.HTTPRequestExecutor(clientFactory)
	}
	backendFactory := martian.NewConfiguredBackendFactory(logger, requestExecutorFactory)
	backendFactory = juju.BackendFactory(backendFactory)
	backendFactory = cb.BackendFactory(backendFactory)
	backendFactory = metricCollector.BackendFactory("backend", backendFactory)
	backendFactory = opencensus.BackendFactory(backendFactory)
	return backendFactory
}

Is it possible to use NoOpHTTPStatusHandler together with all middlewares metioned in the NewBackendFactory function?

I'm a little confused about how krakend deals with middlewares listed in the krakend.json vs. middlewares "hardcoded" in the NewBackendFactory function. It is possible to use some middleware configured in the krakend.json even if it's not explicitly mentioned in the code of the NewBackendFactory function?

Thank you.

from krakend-ce.

kpacha avatar kpacha commented on May 19, 2024

hi @dominiksimek

Is it possible to use NoOpHTTPStatusHandler together with all middlewares metioned in the NewBackendFactory function?

yes, it is. You can do it without touching the code by adding "output_encoding": "no-op" at the endpoint config and "encoding": "no-op" at the backend

I'm a little confused about how krakend deals with middlewares listed in the krakend.json vs. middlewares "hardcoded" in the NewBackendFactory function. It is possible to use some middleware configured in the krakend.json even if it's not explicitly mentioned in the code of the NewBackendFactory function?

The system loads all the factories required to support/enable the modules/middlewares included. Each factory looks for its configuration at some part of the config file. If it is not configured, the module/middleware is not added to the final pipe. That's why the config of a not included component is ignored.

cheers

from krakend-ce.

dominiksimek avatar dominiksimek commented on May 19, 2024

Great, it works well.

However, I have an issue with endpoint used to sign JWT (github.com/devopsfaith/krakend-jose/signer). Signed token is not returned from Krakend when using Backend "encoding": "no-op" (it returns only empty JSON).
On the other hand, response from Krakend contains valid json with signed token when using Backend "encoding": "json". But StatusCode from Krakend response can be only 200 or 400. In the case of unsuccessful user authentication (e.g. wrong password), my backend sends 401 with additional JSON in the response body. Is it possible to proxy such response from backend through Krakend?

Thank you

from krakend-ce.

kpacha avatar kpacha commented on May 19, 2024

@dominiksimek in order to avoid polluting this issue, I'd suggest you to move the discussion to the slack

from krakend-ce.

kpacha avatar kpacha commented on May 19, 2024

@nadim500, notice the pipe of that example has two important customizations:

  • its backend proxy does not decode the response, keeping it as received into the Response.Io.
  • its response render function does not encode the response data. It just copies Response.Io into the output buffer

These two details are very important because they make the pipe behave like a no-op pipe, so no merging is supported because merging requires the data from the backends to be already decoded and it ignores the Response.Io.

from krakend-ce.

muhammadluth avatar muhammadluth commented on May 19, 2024

Great, it works well.

However, I have an issue with endpoint used to sign JWT (github.com/devopsfaith/krakend-jose/signer). Signed token is not returned from Krakend when using Backend "encoding": "no-op" (it returns only empty JSON). On the other hand, response from Krakend contains valid json with signed token when using Backend "encoding": "json". But StatusCode from Krakend response can be only 200 or 400. In the case of unsuccessful user authentication (e.g. wrong password), my backend sends 401 with additional JSON in the response body. Is it possible to proxy such response from backend through Krakend?

Thank you

It's the same for me. I can't get response body from backend when my backend return invalid password but krakend returns response 400 with empty response body.
Can anyone help me ?

from krakend-ce.

github-actions avatar github-actions commented on May 19, 2024

This issue was marked as resolved a long time ago and now has been automatically locked as there has not been any recent activity after it. You can still open a new issue and reference this link.

from krakend-ce.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.