当前位置: 首页 > 知识库问答 >
问题:

Spring Cloud Gateway自定义路由

锺离锦
2023-03-14

这是我目前得到的。

@Bean
public RouteLocator customRouteLocator( RouteLocatorBuilder builder,
                                        RouteServiceForwardingFilter forwardingFilter) {

    return builder.routes()
            .route(r ->
                    r.query("token")
                            .filters(f -> {
                                f.filter(forwardingFilter, ROUTE_TO_URL_FILTER_ORDER + 1);
                                return f;
                            })
                            .uri("http://google.com:80")
                            .id("token_route"))
            .build();
}

这是我创建的过滤器

@Component
public class RouteServiceForwardingFilter implements GatewayFilter {

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    try {
        String forwardUrl = exchange.getRequest().getURI().toString();
        forwardUrl = forwardUrl.substring(0, forwardUrl.lastIndexOf("?"));
        exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, new URI(forwardUrl));
        return chain.filter(exchange);
    } catch (URISyntaxException e) {
        exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        return Mono.empty();
    }
}

}

共有1个答案

宗政燕七
2023-03-14

因此,在仔细研究了一下这里和那里之后,我想到了这个实现,它完全符合我的要求。

我这样编辑了问题中描述的过滤器:

/**
 * Checks whether the user is using a valid token or not.
 * If the token is a valid one, a header named AUTHENTICATED is added
 * to the request and the user is forwarded to the same url with the new request.
 * If not, we forward to the same url but removing the token from it.
 */
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    String forwardUrl = exchange.getRequest().getURI().toString();
    String queryParam = exchange.getRequest().getQueryParams().getFirst(Constants.TOKEN);
    try {

        // 1 means he is connected
        if (queryParam.equals("1")) {
            ServerHttpRequest request = exchange.getRequest().mutate().
                    header(Constants.AUTHENTICATED, "true").
                    build();
            return chain.filter(exchange.mutate().request(request).build());
        }

        if (forwardUrl.contains("?")) {
            forwardUrl = removeQueryParam(forwardUrl, Constants.TOKEN);
        }
        exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, new URI(forwardUrl));
        return chain.filter(exchange);
    } catch (URISyntaxException e) {
        return Mono.empty();
    }
}

/**
 * Removes a query param and its value from a given url
 * @param   url   the url to be modified.
 * @param   queryParam   the parameter to be removed.
 * @return  the url wihtout the query param to be removed 
 *          or the same url in case that query param isn't in that given url
 */
public static String removeQueryParam( String url, String queryParam ) {
    String result = "";
    String[] urlParts = url.split("\\?");
    if (urlParts.length >= 2) {
        String[] urlParams = urlParts[urlParts.length - 1].split("&");
        for (String urlParam : urlParams) {
            String[] param = urlParam.split("=");
            if (!param[0].equals(queryParam)) {
                result += urlParam + "&";
            }
        }
        result = urlParts[0] + (result.length() > 0 ? "?" + result.substring(0, result.length() - 1) : "");
    } else {
        result = url;
    }

    return result;
}

然后我又增加了这两条路线:

/**
 * Adds custom routes to the application
 */
@Bean
public RouteLocator customRouteLocator( RouteLocatorBuilder builder,
                                        SimpleLoggingFilter loggingFilter,
                                        RouteServiceForwardingFilter forwardingFilter) {

    return builder.routes()
            .route(r ->
                    r.query(Constants.TOKEN).negate()
                            .filters(f -> {
                                f.filter(loggingFilter);
                                try {
                                    f.redirect(HttpStatus.UNAUTHORIZED, new URL("http://www.example.com/401"));
                                } catch (MalformedURLException e) {
                                    LOGGER.error(e.getMessage());
                                }
                                return f;
                            })
                            .uri("http://www.example.com/401")
                            .id("WITHOUT_token"))
            .route(r ->
                    r.query(Constants.TOKEN)
                            .and()
                            .header(Constants.AUTHENTICATED).negate()
                            .filters(f -> {
                                f.filter(loggingFilter);                            
                                f.filter(forwardingFilter, Constants.ROUTE_TO_URL_FILTER_ORDER + 1);
                                return f;
                            })
                            .uri("http://localhost:8008")
                            .id("with_token"))
            .build();
}
 类似资料:
  • 在Swoole::$php->runMVC() 调用之前可以修改默认的路由函数。 Swoole::$php->router(function(){ return array('controller' => 'YourController', 'view' => 'YourView'); }); Swoole::$php->runMVC(); 设置后将使用制定的函数作为路由,路由函数务必要

  • phpGrace 追求极致的效率,我们并不认同在url的基础上继续进行复杂的正则匹配是一种高效的、明智的选择!方便的调用规则比不上轻快的效率!所以我们并不建议您使用复杂的路由规则!尽管如此为了满足开发者的需求和习惯我们还是开放了简单路由!在入口页开启路由配置 <?php define('PG_ROUTE', true);//在框架核心文件引用前定义 include 'phpGrace/phpGra

  • SOFARPC 中对服务地址的选择也抽象为了一条处理链,由每一个 Router 进行处理。同 Filter 一样, SOFARPC 对 Router 提供了同样的扩展能力。 @Extension(value = "customerRouter") @AutoActive(consumerSide = true) public class CustomerRouter extends Router

  • 当然, 这个世界上没有绝对的事情. 所以万一现在所有的路由协议都不能满足你的需求, 那么你可以自己实现你自己的路由协议, 你要做的是, 申明你的路由协议实现了Yaf_Route_Interface接口即可.

  • HTTP路由 HTTP路由组件负责将HTTP请求交到对应的函数处理(或者是一个struct的方法),如前面小节所描述的结构图,路由在框架中相当于一个事件处理器,而这个事件包括: 用户请求的路径(path)(例如:/user/123,/article/123),当然还有查询串信息(例如?id=11) HTTP的请求方法(method)(GET、POST、PUT、DELETE、PATCH等) 路由器就

  • Examples Basic custom server Express integration Hapi integration Koa integration Parameterized routing SSR caching 一般你使用next start命令来启动 next 服务,你还可以编写代码来自定义路由,如使用路由正则等。 当使用自定义服务文件,如下面例子所示叫 server.js