2016-11-03 74 views
0

我想重新写一个使用HAProxy的如写的URL路径参数的查询字符串HAProxy的

http://ourdomain.com/hotels/vegas?cf=0 

http://ourdomain.com?d=vegas&cf=0 

URL。

我们使用使用

RewriteRule ^hotels/([^/]+)/?\??(.*)$ ?d=$1&$2 [QSA] 

我已经试过

reqrep ^([^\ :]*)\ /hotels/(.*)  \1\ /?d=\2 

与Apache做,而是说给我http://ourdomain.com?d=vegas?cf=0

而且

reqrep ^([^\ :]*)\ /hotels/([^/]+)/?\??(.*)  \1\ /?d=\2&\3 

只是给了我一个400错误。

这将是很好的做与acl的,但我不明白这是如何工作。

回答

1
reqrep ^([^\ :]*)\ /hotels/([^/]+)/?\??(.*)  \1\ /?d=\2&\3 

只给了我一个400错误。

([^/]+)如果后面的所有内容/?\??(.*)都是可选的,那么就太贪婪了。它的重整要求的最后部分,导致400

记住,你正在使用什么样的数据:

GET /path?query HTTP/1.(0|1) 

更换([^/]+)([^/\ ]+)所以之后任何东西,包括空间将是由\3捕获,而不是\2


更新:看来,上面是不是相当完美,因为?的定位仍然不工作了。这个 - 和原始的400错误 - 用req[i]rep突出显示了一些陷阱 - 这是非常低的请求消耗。

HAProxy 1.6引入了一些新的功能,使请求调整更清晰,这实际上是一个很好的例子来说明其中几个。请注意,这些示例还使用匿名ACL,包装在{}中。这些文档似乎有点阻碍了这些 - 但这只是因为当你需要测试同一组条件时(由于多种原因,命名ACL当然可以更容易重用),它们很难维护),但是它们'对于这样的情况来说非常完美。请注意,由于配置解析器限制,大括号必须至少包含1个空格字符。

变量,作用域为请求(一旦选择后端就超出范围),响应(仅在后端响应后才进入作用域),事务(从请求到响应的持久性,这些可以在到达后端之前使用,并且在响应返回时仍然在范围内)或会话(在该连接期间,如果浏览器重新使用该连接,则在该浏览器的多个请求的范围内)可用于隐藏值。

regsub()变换器取的先前值作为它的输入,并返回通过简单的正则表达式替换传递该值。

如果路径以/hotels/启动时,捕捉路径,洗涤出^/hotels/(与下一个逗号后出现的空字符串代替它),以及在名为req.hotel请求变量藏匿它。的最http-request步骤

http-request set-var(req.hotel) path,regsub(^/hotels/,) if { path_beg /hotels/ } 

Processing在配置文件中的顺序进行,所以,在下一条指令,当(且仅当),该变量具有一个值,我们为了使用http-request set-path/参数清空路径。测试变量是必要的,这样我们就不会对每个请求都这样做 - 只有/ hotels /才会这样做。这可能是因为/hotels/本身可能是一个我们应该独自离开的有效路径,所以您实际上可能需要一些更类似if { path_reg /hotels/.+ }的东西。

http-request set-path/if { var(req.hotel) -m found } 

然后,我们使用http-request set-query设置查询字符串通过连接req.hotel变量与&的值和原始查询字符串,我们使用所述query获得创建的值。

http-request set-query d=%[var(req.hotel)]&%[query] if { var(req.hotel) -m found } 

注意,query提取和http-request set-query都有一些神奇的行为 - 他们照顾?的为您服务。提取query不会返回它,并且http-request set-query不指望您提供它。这很有帮助,因为我们可能需要能够正确处理请求,不管?是否存在于原始请求中,而无需自行管理。

通过上述配置,GET /hotels/vegas?&cf=0 HTTP/1.1变为GET /?d=vegas&cf=0 HTTP/1.1

如果初始查询字符串是完全空的,GET /hotels/vegas HTTP/1.1变成GET /?d=vegas& HTTP/1.1。这看起来有点奇怪,但它应该是完全有效的。一个稍微复杂的配置来测试初始查询字符串的存在可能会阻止,但我不认为这是一个问题。因此,我们已经将1行配置变成了3,但我认为这三行对于他们正在完成的事情更加直观,并且它的确比精简整个请求的起始行与正则表达式。在这里,他们是一起有一些可选的空白:

http-request set-var(req.hotel) path,regsub(^/hotels/,) if { path_beg /hotels/ } 
http-request set-path/        if { var(req.hotel) -m found } 
http-request set-query d=%[var(req.hotel)]&%[query]  if { var(req.hotel) -m found } 
+0

谢谢。这给了我'd = vegas?cf = 0&'(从php中的$ _SERVER ['QUERY_STRING']'读取)。 –

+0

啊,它确实如此。道歉,我发现了一个问题,并忽略了第二个问题。这正是我用眼球解析正则表达式所得到的结果。顺便说一下,这是HAProxy> = 1.6?如果是这样的话,有一些更干净的操作方法。 –

+1

是的,我们在HAProxy 1.6 :) - 清洁方法听起来不错。我设法找到了一些工作。我会发布我的正则表达式解决方案,但是会在任何一天将它换成更干净的方法! (我相信一个更清洁的解决方案对任何回来的人都有用)。无论如何,从我+1。 –

0

这是使用reqrep

acl is_destination path_beg /hotels/ 
reqrep ^([^\ :]*)\ /hotels/([^/\ \?]+)/?\??([^\ ]*)(.*)$  \1\ /?d=\2&\3\4 if is_destination 

我希望的是,ACL将删除需要的一切运行正则表达式(因此一个可行的解决方案减轻负荷),但我不确定是这种情况。

+1

感谢@迈克尔 - sqlbot让我99%的方式。 –

相关问题