Maison  >  Article  >  développement back-end  >  Panique de type de nœud non valide lors de l'implémentation du plugin pour KrakenD

Panique de type de nœud non valide lors de l'implémentation du plugin pour KrakenD

WBOY
WBOYavant
2024-02-09 10:21:09994parcourir

为 KrakenD 实现插件时无效的节点类型恐慌

L'éditeur php Baicao vous présente aujourd'hui un problème courant dans le développement du plug-in KrakenD : "Panique de type de nœud invalide lors de l'implémentation des plug-ins pour KrakenD". KrakenD est une passerelle API rapide et hautes performances qui offre des fonctionnalités riches et un système de plug-in flexible. Cependant, lors du développement d'un plug-in KrakenD, vous rencontrez parfois le problème de types de nœuds non valides, ce qui peut empêcher le plug-in de fonctionner correctement. Dans cet article, nous explorerons les causes de ce problème ainsi que des solutions pour aider les développeurs à surmonter cette panique.

Contenu de la question

Je développe un plugin sans redirections. J'utilise krakend-ce 2.2.1 (en utilisant golang 1.19) et je panique :

gw_krakend_1  | [krakend] 2023/03/15 - 21:09:06.675 ? debug no_redirect_plugin: request received https://127.0.0.1:8443/abc
gw_krakend_1  | [krakend] 2023/03/15 - 21:09:06.689 ? debug no_redirect_plugin: redirect detected https://127.0.0.1:8443/abc
gw_krakend_1  | [krakend] 2023/03/15 - 21:09:06.689 ? debug status code 302
gw_krakend_1  | 2023/03/15 21:09:06 http: panic serving [::1]:54778: invalid node type
gw_krakend_1  | goroutine 84 [running]:
gw_krakend_1  | net/http.(*conn).serve.func1()
gw_krakend_1  |         /usr/local/go/src/net/http/server.go:1854 +0xbf
gw_krakend_1  | panic({0x28cbb60, 0x34b5810})
gw_krakend_1  |         /usr/local/go/src/runtime/panic.go:890 +0x263
gw_krakend_1  | github.com/gin-gonic/gin.(*node).findcaseinsensitivepathrec(0x0?, {0xc0016ac2ec?, 0x0?}, {0xc0010fe800?, 0xc0016ac2ed?, 0xc000ced928?}, {0x0, 0x0, 0x0, 0x0}, ...)
gw_krakend_1  |         /go/pkg/mod/github.com/gin-gonic/[email protected]/tree.go:862 +0xa9d
gw_krakend_1  | github.com/gin-gonic/gin.(*node).findcaseinsensitivepath(0xc0016ac2ec?, {0xc0016ac2ec, 0x5}, 0x30?)
gw_krakend_1  |         /go/pkg/mod/github.com/gin-gonic/[email protected]/tree.go:669 +0x9c
gw_krakend_1  | github.com/gin-gonic/gin.redirectfixedpath(0xc000664300, 0xc0016ac2ec?, 0x60?)
gw_krakend_1  |         /go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:684 +0x5b
gw_krakend_1  | github.com/gin-gonic/gin.(*engine).handlehttprequest(0xc000602b60, 0xc000664300)

Il y ressemble https://github.com/gin-gonic/gin/issues/2959, mais la version de gin a été mise à niveau par rapport à la version précédente de krakend. Ce serait bizarre s'il s'agissait vraiment de majuscules, cela fonctionne parfaitement sans le plugin. J'ai aussi coupé le dernier / (il a été ajouté à un moment donné pour une raison quelconque)

BTW, j'utilise la même version de Krakend pour compiler le plugin.

package main

import (
    "context"
    "errors"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "strings"
)

func main() {}

var clientregisterer = registerer("no_redirect_plugin")

type registerer string

type logger interface {
    debug(v ...interface{})
    info(v ...interface{})
    warning(v ...interface{})
    error(v ...interface{})
    critical(v ...interface{})
    fatal(v ...interface{})
}

var logger logger = nil

func (registerer) registerlogger(v interface{}) {
    l, ok := v.(logger)
    if !ok {
        return
    }
    logger = l
    logger.info(fmt.sprintf("[plugin: %s] logger loaded", clientregisterer))
}

func (r registerer) registerclients(f func(
    name string,
    handler func(context.context, map[string]interface{}) (http.handler, error),
)) {
    f(string(r), r.registerclients)
}

func (r registerer) registerclients(_ context.context, extra map[string]interface{}) (http.handler, error) {
    name, ok := extra["name"].(string)
    if !ok {
        return nil, errors.new("wrong config")
    }

    if name != string(r) {
        return nil, fmt.errorf("unknown register %s", name)
    }

    httpclient := &http.client{
        checkredirect: func(req *http.request, via []*http.request) error {

            // trim the last "/" character from the url if it exists
            urlstr := strings.trimright(req.url.string(), "/")
            req.url, _ = url.parse(urlstr)

            logger.debug("no_redirect_plugin: redirect detected", req.url.string())
            return http.erruselastresponse
        },
    }

    return http.handlerfunc(func(w http.responsewriter, req *http.request) {

        // trim the last "/" character from the url if it exists
        urlstr := strings.trimright(req.url.string(), "/")
        req.url, _ = url.parse(urlstr)

        logger.debug("no_redirect_plugin: request received", req.url.string())
        resp, err := httpclient.do(req)
        if err != nil {
            logger.debug("error while proxying request", err.error())
            http.error(w, err.error(), http.statusinternalservererror)
            return
        }

        defer resp.body.close()

        for k, hs := range resp.header {
            for _, h := range hs {
                w.header().add(k, h)
            }
        }

        w.writeheader(resp.statuscode)
        logger.debug("status code", resp.statuscode)
        if resp.body == nil {
            return
        }

        _, err = io.copy(w, resp.body)
        if err != nil {
            logger.debug("error while proxying request 2", err.error())
            http.error(w, err.error(), http.statusinternalservererror)
            return
        }

    }), nil
}

Mon point de terminaison est défini comme suit :

{
     "endpoint": "/",
     "input_headers":[
       "*"
     ],
     "input_query_strings":[
       "*"
     ],
     "method": "GET",
     "output_encoding": "no-op",
     "extra_config": {},
     "backend": [{
       "url_pattern": "",
       "encoding": "no-op",
       "sd": "static",
       "method": "GET",
       "extra_config": {
         "plugin/http-client": {
           "name": "no_redirect_plugin"
         }
       },
       "host": [
         "{{ env "HOST" }}"
       ],
       "disable_host_sanitize": false
   }]
},{
     "endpoint": "/{level1}",
     "input_headers":[
       "*"
     ],
     "input_query_strings":[
       "*"
     ],
     "method": "GET",
     "output_encoding": "no-op",
     "extra_config": {
     },
     "backend": [{
       "url_pattern": "/{level1}",
       "encoding": "no-op",
       "sd": "static",
       "method": "GET",
       "extra_config": {
         "plugin/http-client": {
           "name": "no_redirect_plugin"
         }
       },
       "host": [
         "{{ env "HOST" }}"
       ],
       "disable_host_sanitize": false
   }]
},{
     "endpoint": "/{level1}/{level2}",
     "input_headers":[
       "*"
     ],
     "input_query_strings":[
       "*"
     ],
     "method": "GET",
     "output_encoding": "no-op",
     "extra_config": {
     },
     "backend": [{
       "url_pattern": "/{level1}/{level2}",
       "encoding": "no-op",
       "sd": "static",
       "method": "GET",
       "extra_config": {
         "plugin/http-client": {
           "name": "no_redirect_plugin"
         }
       },
       "host": [
         "{{ env "HOST" }}"
       ],
       "disable_host_sanitize": false
   }]
}

EDIT : Mon navigateur affiche toujours /abc/ au lieu de /abc, ce qui pourrait créer d'éventuelles collisions entre les routes (comme vu ici : https://github.com/krakendio/krakend-ce/issues/386 ) Quoi qu'il en soit, je ne le fais pas je sais où ajouter la barre oblique (je pensais l'avoir coupée de façon permanente... on dirait que non)

edit2 : j'ai trouvé ceci https://www.krakend.io/docs/service-settings/router-options/ et utilisé "disable_redirect_fixed_path": true et "disable_redirect_trailing_slash" : vrai, ça ne panique plus... Maintenant j'ai un autre problème : des redirections infinies (juste 10 je plaisante) quand mon rocher essaie de rediriger vers /a/ ou quoi que ce soit avec une route slash finale, c'est dans le plugin car krakend gérait les redirections à sa manière...

Je suppose que le principal problème ici est le conflit de routage, lorsque /{level1} et /{level1}/{level2} correspondent à /abc/ en même temps

Des idées ?

Workaround

est bonne, pour résoudre ce problème j'ai essayé de créer un plugin wildcard+no_redirect en utilisant cette https://www.php.cn/link/ba530cdf0a884348613f2aaa3a5ba5e8 configuration, mais même avec copilot&gpt4 j'ai échoué, je vous défie pour y parvenir. J'ai donc résolu le problème d'une autre manière : j'ai placé la passerelle devant mon rocher et à chaque fois que la requête échouait, j'ajoutais l'itinéraire... parce que nous n'avions pas d'itinéraire enregistré (*sanglots). Cela fonctionne très bien pour les fichiers nécessitant un plugin sans redirection. Une excellente solution mais elle a fonctionné jusqu'à présent et pas aussi longtemps que je le pensais

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer