我有一个nginx反向代理,它需要传递它收到的查询字符串。但是它收到的这个查询字符串格式不正确,可以包含不是URL编码的JSON,即它包含大括号,即{},逗号,冒号和双引号!不幸的是,我无法控制这一点,这会导致下游服务器在解析字符串时发生barf。
有没有办法在代理之前对此字符串进行正确的URL编码?
我可以替换花括号,因为我知道使用config只会有一个实例:
if ($args ~* '(.*){"(.*)":"(.*)","(.*)":"(.*)","(.*)":"(.*)","(.*)":"(.*)","(?<group10>.*)":"(?<group11>.*)"}(?<group12>.*)') {
set $args $1%7B%22$2%22%3A%22$3%22%2C%22$4%22%3A%22$5%22%2C%22$6%22%3A%22$7%22%2C%22$8%22%3A%22$9%22%2C%22${group10}%22%3A%22${group11}%22%7D${group12};
rewrite (.*)$ $1;
}
proxy_pass http://127.0.0.1:8080;
但是,我事先并不知道JSON将拥有多少个字段,因此很难对上面的其他对象使用与上面相同的逻辑。
我还应该提一下,我不认为这与nginx url-decoding参数有关,因为我没有在proxy_pass中使用URI。
谢谢!
更新:目前,JSON对象似乎正在发送相同的属性,因此这就是我用作解决方法的方法。它非常可怕,如果属性的数量发生变化,它会破坏,但现在可以完成工作。
const Task = require('data.task')
const {chain, liftM2} = require('control.monads')
import {pipe, length, curry, prop, equals, tap} from 'ramda'
it.only('sign in', done => {
const merge = curry((p, f, g, x) => liftM2(p, f(x), g(x)))
const signIn = pipe(
lift,
chain(merge(equals,
pipe(lift, map(prop('password'))),
pipe(lift, map(prop('userName')), chain(getUserByUserName), map(prop('password')))
))
)
signIn({ userName: 'ron', password: '123' })fork(
(err) => { console.log('error happens'); done(err) },
matched => { expect(matched).to.eql(true); done() }
)
})
const getUserByUserName = (id) => new Task((reject, result) => setTimeout(
userName => userName === 'ron'
? reject('not found')
: result({ userName: 'ron', password: '123' })
, 0
))
请注意,由于这会返回超过9个正则表达式组,因此我必须为组10,11和12命名,否则它们将被解释为$ 1 +数字0,1或2。
有更强大的方法吗?
答案 0 :(得分:0)
就个人而言,我不喜欢使用单个if
语句的解决方案,因为它看起来不太可读,不灵活或易于维护。您可能会看到是否具有location
或rewrite
语句的组合,其中每个语句处理特定的编码情况,可能有效;请参阅http://mdoc.su/,了解内部重定向非常繁重的有趣项目,但我相信nginx可能会对间接总数有所限制。
否则,如果您无法修改后端,另一个选项是自动将行为不当的客户端和/或请求重定向到辅助后端,辅助后端的唯一目的是正确地重新编码字符串,提供X-Accel-Redirect
HTTP响应标头作为其输出(根据http://nginx.org/r/proxy_ignore_headers),nginx将用于对实际后端进行后续内部重定向/请求。