文章目录
路由是⽹关配置的基本组成模块,和Zuul的路由配置模块类似。⼀个Route模块由⼀个 ID,⼀个⽬标 URI,⼀组断⾔和⼀组过滤器定义。如果断⾔为真,则路由匹配,⽬标URI会被访问。
如果请求的⽬标地址,是单个的URI资源路径,配置⽂件实例如下:
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: service1
uri: https://blog.csdn.net
predicates:
- Path=/csdn
各字段含义如下。
id:我们⾃定义的路由 ID,保持唯⼀
uri:⽬标服务地址
predicates:路由条件,Predicate 接受⼀个输⼊参数,返回⼀个布尔值结果。该接⼝包含多种默
认⽅法来将 Predicate 组合成其他复杂的逻辑(⽐如:与,或,⾮)。
上⾯这段配置的意思是,配置了⼀个 id 为 url-proxy-1的URI代理规则,路由的规则为,当访问地址
http://localhost:8080/csdn/1.jsp时,会路由到上游地址https://blog.csdn.net/1.jsp。
转发功能同样可以通过代码来实现,我们可以在启动类 GateWayApplication 中添加⽅法 customRouteLocator() 来定制转发规则。
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes().route("path_route", r -> r.path("/csdn").uri("https://blog.csdn.net")).build();
}
}
在uri的schema协议部分为⾃定义的lb:类型,表示从微服务注册中⼼(如Eureka)订阅服 务,并且通过负载均衡进⾏服务的路由。代码如下。
server:
port: 9005
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: service1
uri: https://blog.csdn.net
predicates:
- Path=/csdn
- id: service2
# uri: http://127.0.0.1:9001
uri: lb://cloud-payment-service
predicates:
- Path=/payment/**
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9004/eureka
注册中⼼相结合的路由配置⽅式,与单个URI的路由配置,区别其实很⼩,仅仅在于URI的 schema协议不同。单个URI的地址的schema协议,⼀般为http或者https协议。启动多个⽀付微 服务,会发现端⼝9000,9001轮流出现。
Spring Cloud Gateway的主要功能之⼀是转发请求,转发规则的定义主要包含三个部分,如表所示。
| Route(路由) | 路由是⽹关的基本单元,由ID、URI、⼀组Predicate、⼀组Filter组成,根据Predicate进⾏匹配转发。 |
| Predicate(谓语、断⾔) | 路由转发的判断条件,⽬前SpringCloud Gateway⽀持多种⽅式,常⻅如:Path、Query、Method、Header等,写法必须遵循 key=vlue的形式 |
| Filter(过滤器) | 过滤器是路由转发请求时所经过的过滤逻辑,可⽤于修改请求、响应内容 |
说⽩了 Predicate 就是为了实现⼀组匹配规则,⽅便让请求过来找到对应的 Route 进⾏处理,接下来我们接下 Spring Cloud GateWay 内置⼏种 Predicate 的使⽤。转发规则(predicates),假设 转发uri都设定为http://localhost:9001,常⻅Predicate,如表所示
| 规则 | 实例 | 说明 |
|---|---|---|
| Path | - Path=/gate/,/rule/ | 当请求的路径为gate、rule开头的时,转发到 http://localhost:9001服务器上 |
| Before | - Before=2017-01-20T17:42:47.789-07:00[America/Denver] | 在某个时间之前的请求才会被转发到 http://localhost:9001 服务器上 |
| After | - After=2017-01-20T17:42:47.789- 07:00[America/Denver] | 在某个时间之后的请求才会被转发 |
| Between | - Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01- 21T17:42:47.789-07:00[America/Denver] | 在某个时间段之间的才会被转发 |
| Cookie | - Cookie=chocolate, ch.p | 名为chocolate的表单或者满⾜正则ch.p的表单才会被匹配到 进⾏请求转发 |
| Header | - Header=X-Request-Id, \d+ | 携带参数X-Request-Id或者满⾜\d+的请求头才会匹配 |
| Host | - Host=www.hd123.com | 当主机名为www.hd123.com的时候直接转发到 http://localhost:9001服务器上 |
| Method | - Method=GET | 只有GET⽅法才会匹配转发请求,还可以限定POST、PUT等 |
Query Route Predicate ⽀持传⼊两个参数,⼀个是属性名⼀个为属性值,属性值可以是正则表达 式
spring:
cloud:
gateway:
routes:
- id: service3
uri: https://www.baidu.com
order: 0
predicates:
- Query=smile
这样配置,只要请求中包含 smile 属性的参数即可匹配路由。使⽤ curl 测试,命令⾏输⼊:curl localhost:9005?smile=x&id=2,经过测试发现只要请求汇总带有 smile 参数即会匹配路由,不带 smile 参数则不会匹配。 还可以将 Query 的值以键值对的⽅式进⾏配置,这样在请求过来时会对属性值和正则进⾏匹配,匹配上才会⾛路由。
spring:
cloud:
gateway:
routes:
- id: service3
uri: https://www.baidu.com
order: 0
predicates:
- Query=keep, pu.
这样只要当请求中包含 keep 属性并且参数值是以 pu 开头的⻓度为三位的字符串才会进⾏匹配和路由。 使⽤ curl 测试,命令⾏输⼊:curl localhost:8080?keep=pub,测试可以返回⻚⾯代码,将 keep 的属 性值改为 pubx 再次访问就会报 404,证明路由需要匹配正则表达式才会进⾏路由。
Header Route Predicate 和 Query Route Predicate ⼀样,也是接收 2 个参数,⼀个 header 中属性名称和⼀个正则表达式,这个属性值和正则表达式匹配则执⾏。
spring:
cloud:
gateway:
routes:
- id: service4
uri: https://www.baidu.com
order: 0
predicates:
- Header=X-Request-Id, \d+
使⽤ curl 测试,命令⾏输⼊:curl http://localhost:9005 -H “X-Request-Id:88”,则返回⻚⾯代 码证明匹配成功。将参数-H "X-Request-Id:88"改为-H “X-Request-Id:spring”,再次执⾏时返回 404证明没有匹配。
Cookie Route Predicate 可以接收两个参数,⼀个是 Cookie name ,⼀个是正则表达式,路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执⾏路由,如果没有匹配 上则不执⾏。
spring:
cloud:
gateway:
routes:
- id: service5
uri: https://www.baidu.com
predicates:
- Cookie=sessionId, test
使⽤ curl 测试,命令⾏输⼊,curl http://localhost:9005 --cookie “sessionId=test”,则会返回⻚⾯代码,如果去掉–cookie “sessionId=test”,后台汇报 404 错误。
Host Route Predicate 接收⼀组参数,⼀组匹配的域名列表,这个模板是⼀个 ant 分隔的模板, ⽤.号作为分隔符。它通过参数中的主机地址作为匹配规则。
spring:
cloud:
gateway:
routes:
- id: service6
uri: https://www.baidu.com
predicates:
- Host=**.baidu.com
使⽤ curl 测试,命令⾏输⼊,curl http://localhost:9005 -H "Host: www.baidu.com"或者curl http://localhost:8080 -H “Host: md.baidu.com”,经测试以上两种 host 均可匹配到 host_route 路由,去掉 host 参数则会报 404 错误。
spring:
cloud:
gateway:
routes:
- id: service7
uri: https://www.baidu.com
predicates:
- Method=PUT
使⽤ curl 测试,命令⾏输⼊,curl -X PUT http://localhost:9005,测试返回⻚⾯代码,证明匹配 到路由,以其他⽅式,返回 404 没有找到,证明没有匹配上路由
Path RoutePredicate 接收⼀个匹配路径的参数来判断是否路由。
spring:
cloud:
gateway:
routes:
- id: service8
uri: https://www.baidu.com
predicates:
- Path=/payment/{segment}
如果请求路径符合要求,则此路由将匹配, curl 测试,命令⾏输⼊,curl http://localhost:9005/payment/1, 可以正常获取到⻚⾯返回值,curl http://localhost:9005/payment2/1,报404,证明路由是通过指定路由来匹配
spring:
cloud:
gateway:
routes:
- id: service9
uri: http://127.0.0.1:9001
predicates:
- Host=**.foo.org
- Path=/headers
- Method=GET
- Header=X-Request-Id, \d+
- Query=foo, ba.
- Query=baz
- Cookie=chocolate, ch.p
各种 Predicates 同时存在于同⼀个路由时,请求必须同时满⾜所有的条件才被这个路由匹配。 ⼀个请求满⾜多个路由的断⾔条件时,请求只会被⾸个成功匹配的路由转发
列举⼏个过滤器,如表所示。
| 过滤规则 | 实例 | 说明 |
|---|---|---|
| PrefixPath | - PrefixPath=/app | 在请求路径前加上app |
| RewritePath | - RewritePath=/test, /app/test | 访问localhost:9022/test,请求会转发到 localhost:8001/app/test |
| SetPath | SetPath=/app/{path} | 通过模板设置路径,转发的规则时会在路径前增加 app,{path}表示原请求路径 |
| RedirectTo | 重定向 | |
| RemoveRequestHea | 去掉某个请求头信息\1. PrefixPath |
对所有的请求路径添加前缀
spring:
cloud:
gateway:
routes:
- id: service10
uri: http://127.0.0.1:9001
predicates:
- Path=/payment/{segment}
filters:
- PrefixPath=/payment
访问/123请求被发送到http://127.0.0.1:9001/payment/123。
跳过指定的路径
spring:
cloud:
gateway:
routes:
- id: service11
uri: http://127.0.0.1:9001
predicates:
- Path=/payment/{segment}
filters:
- StripPrefix=1
- PrefixPath=/payment
此时访问http://localhost:9005/api/123,⾸先StripPrefix过滤器去掉⼀个/api,然后PrefixPath 过滤器加上⼀个/payment,能够正确访问到微服务。
spring:
cloud:
gateway:
routes:
- id: service12
uri: http://127.0.0.1:9001
predicates:
- Path=/payment/{segment}
filters:
- RewritePath=/api/(?<segment>.*), /$\{segment}
请求http://localhost:9005/api/payment/123路径,RewritePath过滤器将路径重写为 http://localhost:9005/payment/123,能够正确访问微服务。
SetPath和Rewrite类似,代码如下
spring:
cloud:
gateway:
routes:
- id: service13
uri: http://127.0.0.1:9001
predicates:
- Path=/payment/{segment}
filters:
- SetPath=/payment/{segment}
请求http://localhost:9005/api/payment/123路径,SetPath过滤器将路径设置为 http://localhost:9005/payment/123,能够正确访问微服务。
去掉某个请求头信息。
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: https://example.org
filters:
- RemoveRequestHeader=X-Request-Foo 12345678
去掉请求头X-Request-Foo
去掉某个回执头信息
spring:
cloud:
gateway:
routes:
- id: removerequestparameter_route
uri: https://example.org
filters:
- RemoveRequestParameter=red
设置请求头信息
spring:
cloud:
gateway:
routes:
- id: setrequestheader_route
uri: https://example.org
filters:
- SetRequestHeader=X-Request-Red, Blue
2.2.8 default-filters
对所有的请求添加过滤器
spring:
cloud:
gateway:
routes:
- id: service14
uri: http://127.0.0.1:9001
predicates:
- Path=/9001/{segment}
- id: service15
uri: http://127.0.0.1:9000
predicates:
- Path=/9000/{segment}
default-filters:
- StripPrefix=1
- PrefixPath=/payment
对所有的请求添加过滤器
spring:
cloud:
gateway:
routes:
- id: service14
uri: http://127.0.0.1:9001
predicates:
- Path=/9001/{segment}
- id: service15
uri: http://127.0.0.1:9000
predicates:
- Path=/9000/{segment}
default-filters:
- StripPrefix=1
- PrefixPath=/payment
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
如何匹配未被反斜杠转义的平衡定界符对(其本身未被反斜杠转义)(无需考虑嵌套)?例如对于反引号,我试过了,但是转义的反引号没有像转义那样工作。regex=/(?!$1:"how\\"#expected"how\\`are"上面的正则表达式不考虑由反斜杠转义并位于反引号前面的反斜杠,但我愿意考虑。StackOverflow如何做到这一点?这样做的目的并不复杂。我有文档文本,其中包括内联代码的反引号,就像StackOverflow一样,我想在HTML文件中显示它,内联代码用一些spanMaterial装饰。不会有嵌套,但转义反引号或转义反斜杠可能出现在任何地方。
我有一个在Linux服务器上运行的ruby脚本。它不使用rails或任何东西。它基本上是一个命令行ruby脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg
我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种
question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参