文章目录
- 前言
- 一、常用网关过滤器
- 1. 常用过滤器
- 2. 示例
- 3. Default Filters
- 二、定义接口服务
- 1. 定义接口
- 三、自定义过滤器
- 1. 过滤器类
- 2. 应用配置
- 四、单元测试
- 1. 正常
- 2. 黑名单
- 总结
前言
上一章我们通过,路由断言根据请求IP地址的黑名单功能,作用范围比较大。
这一章,我们通过网关过滤器来实现特定请求url的黑名单功能,作用范围进一步细化到接口。
一、常用网关过滤器
官方内置的网关过滤器太多了,这里我只介绍常用的部分
网关过滤器又分为前置和后置,比较典型的有:AddRequestHeader
(前),AddResponseHeader
(后)
1. 常用过滤器
过滤器类型 | 用法 | 描述 |
---|---|---|
AddRequestHeader | - AddRequestHeader=X-Request-red, blue | 将X-Request-red:blue请求头添加到所有匹配请求的下游请求头中。 |
AddRequestHeadersIfNotPresent | - AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-2:green | 在请求头不存在的情况下,为所有匹配请求的下游请求标头添加了2个标头X-Request-Color-1:bule和X-Request-Color-2:green |
AddRequestParameter | - AddRequestParameter=red, blue | 将为所有匹配的请求在下游请求的查询参数中添加red=blue。 |
AddResponseHeader | - AddResponseHeader=X-Response-Red, Blue | 这会将X-Response-Red:Blue添加到所有匹配请求的下游响应头中。 |
RemoveRequestHeader | - RemoveRequestHeader=X-Request-Foo | 这将在X-Request-Foo请求头头被发送到下游之前将其删除。 |
RemoveRequestParameter | - RemoveRequestParameter=red | 这将在向下游发送请求之前删除红色查询参数。 |
RemoveResponseHeader | - RemoveResponseHeader=X-Response-Foo | 这将在响应返回给网关客户端之前从响应头中删除X-Response-Foo。 |
PrefixPath | - PrefixPath=/mypath | 将为所有匹配请求添加前缀/mypath。因此,对/hello的请求被发送到/mypath/hello。 |
StripPrefix | - StripPrefix=2 | 当通过网关向/name/blue/red发出请求时,向nameservice发出的请求替换为nameservice/red。 |
2. 示例
RewritePath
对于
/red/blue
的请求路径,这会在发出下游请求之前将路径设置为/blue
。请注意,由于YAML规范,$
应该替换为$\
。
spring:cloud:gateway:routes:- id: rewritepath_routeuri: https://example.orgpredicates:- Path=/red/**filters:- RewritePath=/red/?(?<segment>.*), /$\{segment}
ModifyRequestBody
修改请求正文
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {return builder.routes().route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org").filters(f -> f.prefixPath("/httpbin").modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,(exchange, s) -> Mono.just(new Hello(s.toUpperCase())))).uri(uri)).build();
}static class Hello {String message;public Hello() { }public Hello(String message) {this.message = message;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}
ModifyResponseBody
修改响应正文
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {return builder.routes().route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org").filters(f -> f.prefixPath("/httpbin").modifyResponseBody(String.class, String.class,(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri)).build();
}
3. Default Filters
要添加过滤器并将其应用于所有路由,可以使用
spring.cloud.gateway.default-filters
。此属性接受过滤器列表。以下列表定义了一组默认过滤器:
spring:cloud:gateway:default-filters:- AddResponseHeader=X-Response-Default-Red, Default-Blue- PrefixPath=/httpbin
更多网关过滤器请查看
二、定义接口服务
上一章我们使用的是提供者服务,这里就使用消费者服务,配置看起来会更加直观。
1. 定义接口
定义三个服务,分别是:
- user-service/hello
- user-service/hello1
- user-service/hello2
package org.example.nacos.consumer.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** Create by zjg on 2024/7/21*/
@RestController
@RequestMapping("/consumer/")
public class HelloController {@RequestMapping("hello")public String hello(){return "hello consumer";}@RequestMapping("hello1")public String hello1(){return "hello consumer";}@RequestMapping("hello2")public String hello2(){return "hello consumer";}
}
三、自定义过滤器
1. 过滤器类
package org.example.gateway.filter;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.validation.constraints.NotEmpty;
import org.example.common.model.Result;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import reactor.core.publisher.Flux;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
import static org.springframework.cloud.gateway.support.ShortcutConfigurable.ShortcutType.GATHER_LIST;/*** Create by zjg on 2024/7/24*/
@Component
public class BlackListGatewayFilterFactory extends AbstractGatewayFilterFactory<BlackListGatewayFilterFactory.Config> {public BlackListGatewayFilterFactory() {super(Config.class);}@Overridepublic GatewayFilter apply(Config config) {return (exchange, chain) -> {Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();String path = request.getURI().getPath();if (config.url.contains(path)) {response.setStatusCode(HttpStatus.NOT_ACCEPTABLE);Result result = Result.error(HttpStatus.NOT_ACCEPTABLE.value(), "接口服务禁用", "该接口服务已加入黑名单,禁止访问!");ObjectMapper objectMapper = new ObjectMapper();try {return response.writeWith(Flux.just(response.bufferFactory().wrap(objectMapper.writeValueAsBytes(result))));} catch (JsonProcessingException e) {throw new RuntimeException(e);}}return chain.filter(exchange);};}@Overridepublic ShortcutType shortcutType() {return GATHER_LIST;}@Overridepublic List<String> shortcutFieldOrder() {return Collections.singletonList("url");}@Validatedpublic static class Config {@NotEmptyprivate List<String> url = new ArrayList<>();public List<String> getUrl() {return url;}public void setUrl(List<String> url) {this.url = url;}}
}
2. 应用配置
spring:cloud:gateway:routes:- id: provider-serviceuri: lb://provider-servicepredicates:- Path=/provider/**- BlackRemoteAddr=192.168.1.1/24,127.0.0.1,192.168.0.102- id: consumer-serviceuri: lb://consumer-servicepredicates:- Path=/consumer/**filters:- BlackList=/consumer/hello1,/consumer/hello2
四、单元测试
1. 正常
localhost:8888/consumer/hello
2. 黑名单
localhost:8888/consumer/hello1
localhost:8888/consumer/hello2
总结
回到顶部
这样我们就可以通过配置文件轻松地控制接口的对外服务。