在 Spring Boot 应用程序中使用 API 网关时,HATEOAS 路径无效
Posted
技术标签:
【中文标题】在 Spring Boot 应用程序中使用 API 网关时,HATEOAS 路径无效【英文标题】:HATEOAS paths are invalid when using an API Gateway in a Spring Boot app 【发布时间】:2015-08-15 13:07:22 【问题描述】:我有两个 Spring Boot 应用程序,其中一个用作 API 网关(如在此处讨论的 Spring Example)。连接到第一个的另一个是使用 spring-data-rest (spring-data-neo4j-rest) 公开配置文件服务。
第一个应用程序在端口 8080 上启动,并使用 zuul 将请求路由到第二个应用程序,如下所示:
zuul:
routes:
profiles:
path: /profiles/**
url: http://localhost:8083/profiles/
这一切都很好,第二个应用程序正在处理对http://localhost:8080/profiles 的请求。但问题是响应中的 HATEOAS 链接不正确。调用第二个服务的响应是正确的:
"_links":
"self":
"href": "http://localhost:8083/profiles?page,size,sort",
"templated": true
,
"search":
"href": "http://localhost:8083/profiles/search"
,
"_embedded":
"profiles": [
"name": "Andrew Rutter",
"_links":
"self":
"href": "http://localhost:8083/profiles/0"
,
"name": "Andrew Rutter",
"_links":
"self":
"href": "http://localhost:8083/profiles/1"
]
,
"page":
"size": 20,
"totalElements": 2,
"totalPages": 1,
"number": 0
但是当这回到我的 API 网关时,链接正在被重写为
"name": "Andrew Rutter",
"_links":
"self":
"href": "http://localhost:8080/profiles/profiles/0"
网关路径别名加上实际的服务基 Uri。我是否错过了一个 zuul 选项来禁用该行为,只需将 hatoas uri 留在适当的位置并进行主机调整。或者有没有办法让网关后面的服务连接到 / 而不是 /profiles 的默认资源端点(在这种情况下),这样可以避免添加不需要的路径。
谢谢!
【问题讨论】:
【参考方案1】:Zuul 或 Spring-Cloud 将“X-Forwarded-Host”标头添加到所有转发的请求中,Spring-hateoas 尊重并适当地修改链接。引用 Spring-Cloud 文档:
添加到转发请求的 X-Forwarded-Host 标头由 默认。要关闭它,请设置 zuul.addProxyHeaders = false。前缀 默认情况下会剥离路径,并且对后端的请求会拾取一个 标头“X-Forwarded-Prefix”(上面示例中的“/myusers”)。
您可以尝试推荐的修复方法,即设置zuul.addProxyHeaders=false
【讨论】:
感谢您的建议。将其设置为 false 的结果是返回的链接是指向后端服务的直接链接,这是不受欢迎的。我注意到引入的 spring-hateoas 版本是 0.16.0,因此尝试将依赖项更改为当前版本,但没有任何乐趣。我确实在网关中将 api 路径更改为 /xyz 以使事情更清楚。当我将特定配置文件请求为 /xzy/0 时,它会在内部发送到 /profiles/0,但响应中的 hateoas 链接最终会变成 /xyz/profiles/0/profiles/0【参考方案2】:我遇到了完全相同的问题。改变你的配置如下:
zuul:
routes:
profiles:
path: /profiles/**
url: http://localhost:8083
stripPrefix: false
这会将发送到与“/profiles/**”匹配的网关的所有请求路由到您的后端服务器“http://localhost:8083”并保留前缀(在您的情况下为“/profiles”,因为它与路由匹配)。
【讨论】:
【参考方案3】:Zuul 转发到 /profiles contextPath。
尝试将此设置为配置:
zuul:
routes:
profiles:
path: /profiles/**
url: http://localhost:8083/
【讨论】:
谢谢,我已经尝试过了,原始请求的上下文路径没有传递给服务。在上面的示例中,我得到一个 404,表明 / 上没有任何可用的内容,因为 Spring Data Rest 公开了基于模型的端点,该模型是 /profiles/*,但网关不会自动传递它 你试过zuul: routes: profiles: path: /** url: localhost:8083/profiles 吗?【参考方案4】:在同样的问题上挣扎了一段时间后,我终于尝试了zuul.addProxyHeaders = true
,它成功了!
链接不再断开。
【讨论】:
【参考方案5】:在我在关于 Spring Data REST 的演讲中用于 SpringOne 的演示应用程序中,我有以下配置来处理 URI 重写以及正确调整前缀标头设置。
zuul:
routes:
api:
path: /api/**
serviceId: spring-a-gram-backend
stripPrefix: false
files:
path: /files/**
serviceId: spring-a-gram-mongodb-fileservice
stripPrefix: false
在https://github.com/gregturn/spring-a-gram/blob/master/spring-a-gram-frontend/src/main/resources/application.yml#L23-L32查看全文
【讨论】:
以上是关于在 Spring Boot 应用程序中使用 API 网关时,HATEOAS 路径无效的主要内容,如果未能解决你的问题,请参考以下文章
在Spring Boot Data JPA Rest API中使用PostgreSql时,表未找到错误
在 Spring Boot 中自动生成 API 文档 [关闭]
如何在 Spring Boot 应用程序中从 Api 网关(Zuul)调用外部服务(非 MSA)
使用 RESTful 登录 API 验证我的 Spring Boot 应用程序