问题描述
我在前端应用程序中使用了mithril.js,后端应用程序在ipv6环境中运行。
使用mithril.js调用将ajax请求发布到后端。
async post(url,body = {}) {
return new Promise((resolve,reject) => {
m.request({method: 'POST',url,body}).then((data) => {
resolve(data);
}).catch((err) => {
reject(err.message);
});
});
}
支持的网址是这样的:http:// [340f:c0e0:1d1:5gc0:g4fs:2 ::]:22923 / backend。
但是在调用后端api时收到此错误Template parameter names *must* be separated
。
解决方法
错误说明
基于the documentation of m.request()
,您可以指定dynamic URLs:
请求URL可能包含插值:
m.request({ method: "GET",url: "/api/v1/users/:id",params: {id: 123},}).then(function(user) { console.log(user.id) // logs 123 })
在上面的代码中,
:id
被来自params
对象的数据填充,请求变为GET /api/v1/users/123
。如果
params
属性中不存在匹配数据,则插值将被忽略。m.request({ method: "GET",url: "/api/v1/users/foo:bar",})
在上面的代码中,请求变为
GET /api/v1/users/foo:bar?id=123
由于您的后端URL包含冒号,因此将其解释为动态URL。
根据the documentation of m.buildPathname()
,m.request()
在内部使用m.buildPathname()
处理动态URL。
m.buildPathname()
的开头包含有关路径模板参数的以下检查(动态URL =填充路径参数的路径模板):
if ((/:([^\/\.-]+)(\.{3})?:/).test(template)) {
throw new SyntaxError("Template parameter names *must* be separated")
}
(来源:https://github.com/MithrilJS/mithril.js/blob/v2.0.4/mithril.js#L1288-L1292)
同样,由于您的后端URL包含冒号,因此这是您收到错误的地方。 (您可以通过尝试运行m.buildPathname('http://[340f:c0e0:1d1:5gc0:g4fs:2::]:22923/backend')
来进行验证-您会收到相同的错误。)
如何修复
由于您无法摆脱m.buildPathname()
开头的正则表达式检查,因此最好的选择是使用动态URL。像这样:
m.buildPathname(':url...',{ url: 'http://[340f:c0e0:1d1:5gc0:g4fs:2::]:22923/backend' })
// => http://[340f:c0e0:1d1:5gc0:g4fs:2::]:22923/backend
或者当应用于您的代码时:
async post(url,body = {}) {
return new Promise((resolve,reject) => {
m.request({method: 'POST',url: ':url...',body,params: {url}}).then((data) => {
resolve(data);
}).catch((err) => {
reject(err.message);
});
});
}
或者,您也可以指定(动态)URL作为m.request()
的第一个参数:
async post(url,reject) => {
m.request(':url...',{method: 'POST',params: {url}}).then((data) => {
resolve(data);
}).catch((err) => {
reject(err.message);
});
});
}
请注意,路径参数:url
之后有三个点。否则,其值将被转义/编码。 the documentation of path handling中提到了这一点。示例:
m.buildPathname(':url',{ url: 'http://[340f:c0e0:1d1:5gc0:g4fs:2::]:22923/backend' })
// => http%3A%2F%2F%5B340f%3Ac0e0%3A1d1%3A5gc0%3Ag4fs%3A2%3A%3A%5D%3A22923%2Fbackend
处理URL参数
如另一个答案中所述,如果URL包含参数,则将复制问号:
m.buildPathname(':url...',{ url: 'https://example.com/foo?bar=baz' })
// => https://example.com/foo??bar=baz
// ^^
一种解决方法是在路径模板中包含参数:
const url = 'https://example.com/foo?bar=baz'
const [baseUrl,params] = url.split('?')
const template = ':baseUrl...' + (params ? `?${params}` : '')
m.buildPathname(template,{ baseUrl })
// => https://example.com/foo?bar=baz
但是,如果URL参数中包含冒号,则可能会出现与原始错误相同的错误(“模板参数名称*必须*必须分开”)。
也许可以解决这个问题,但是对于这个相对简单的用例,以前的代码示例已经相当复杂。这导致我们:
替代解决方案:不要使用m.request()
m.request()
只是“ XMLHttpRequest
周围的薄包装”。它“返回承诺并在其承诺链完成后触发重新提款。”
如果m.request()
由于使用IPv6 URL(或由于其他原因)而难以使用,则使用其他方法进行XHR请求会更容易。例如,您可以使用fetch()
–仅记得在最后调用m.redraw()
(m.request()
会自动执行此操作)。
当然,m.request()
除了结束时m.redraw()
(see the docs)之外,还可以做更多的事情,但是也可以使用其他东西。
感谢/var/log/nginx/access.log
的回复。我们已经实现了您的解决方案,但是我们面临以下问题。
问号在api的http url中传递了两次。请在下面的屏幕截图中找到附件。
为了解决此问题,请在下面找到更新的代码
mts knn
如果有的话,您也可以提供有效的解决方案。