防止 HTTP 503 响应拒绝 Promise
Preventing an HTTP 503 response from rejecting a Promise
这听起来像是对 Promises 的滥用,但这是我的用例。
我正在编写一个基于 NodeJS 的工具来验证存储在 OAS (Swagger) 文件中的 API 定义。此任务的一部分涉及检查通过将 "host" 和 "basepath" 属性与 "paths" 属性.[=11 中列出的每个端点名称连接而构造的端点的有效性=]
我正在使用 NodeJS 库 'promise' 使用此行包装标准 'request' 库
var request = require('request')
var Promise = require('promise')
// Wrap the HTTP HEAD request in a promise
request.head = Promise.denodeify(request.head)
我正在使用 HTTP HEAD 请求,因为我对实际调用 API 不感兴趣 - 我只想确保 OAS 文件中显示的 URL 指向有效目的地。
这意味着除了 404(未找到)和 410(消失)之外,几乎所有响应状态代码都是可接受的。
但是,如果出现 HTTP 503(服务不可用)响应,'request' NodeJS 库将此报告为错误,然后导致 Promise 包装 request.head() 调用被拒绝了。
由于 API 的实现方式有很大差异,如果位于 URL 后面的 API 管理层想要显式阻止 HTTP HEAD请求,那么它可能会通过响应 HTTP 503 而不是更期望的 HTTP 405(方法不允许)来实现。此外,如果 API 已被沙盒化,则 HTTP 503 是预期的状态代码。
无论如何,HTTP 503 证明这个 URL 实际上是有效的,即使我使用可能不允许的 HTTP 方法调用它。
我认为 "unrejecting" Promise 是一种滥用(而且可能也是不可能的),所以我不得不自己处理 HTTP 请求,这样 503 就不会被视为错误。
有人有更好的主意吗?
谢谢
克里斯·W
I think "unrejecting" the Promise is an abuse (and probably also impossible),
"Unrejecting"一个Promise确实是不可能的。改变状态的唯一方法是通过 .then()
或 .catch()
形成一个承诺链,并从回调中进行适当的 returns (或抛出)。
so I'm left with the possibility of having to handle the HTTP requests myself in such a way that 503 is not considered an error.
这可能是最现实的方法,即 request.head()
的定制、手动承诺。
问题表明错误代码列表很短(404 和 410),因此只有遇到这些代码时才更容易拒绝。
function testUrl(url) {
const badCodes = [404, 410];
return new Promise((resolve, reject) => {
request.head(url, (error, response, body) => {
if(error) {
if(response && badCodes.indexOf(+response.statusCode) === -1) {
resolve(response.statusCode);
} else {
reject error;
}
} else {
resolve(response.statusCode);
}
});
});
}
或者,如果您要接受的错误代码列表很短,那么测试逻辑很容易反转。
function testUrl(url) {
const goodCodes = [503];
return new Promise((resolve, reject) => {
request.head(url, (error, response, body) => {
if(error) {
if(response && goodCodes.indexOf(+response.statusCode) > -1) {
resolve(response.statusCode);
} else {
reject(error);
}
} else {
resolve(response.statusCode);
}
});
});
}
你可以玩弄逻辑来得到你想要的。
无论你最终得到什么,请致电:
testUrl('http://path/to/resource').then(function(statusCode) {
// pass
}, function(error) {
// fail
});
这听起来像是对 Promises 的滥用,但这是我的用例。
我正在编写一个基于 NodeJS 的工具来验证存储在 OAS (Swagger) 文件中的 API 定义。此任务的一部分涉及检查通过将 "host" 和 "basepath" 属性与 "paths" 属性.[=11 中列出的每个端点名称连接而构造的端点的有效性=]
我正在使用 NodeJS 库 'promise' 使用此行包装标准 'request' 库
var request = require('request')
var Promise = require('promise')
// Wrap the HTTP HEAD request in a promise
request.head = Promise.denodeify(request.head)
我正在使用 HTTP HEAD 请求,因为我对实际调用 API 不感兴趣 - 我只想确保 OAS 文件中显示的 URL 指向有效目的地。
这意味着除了 404(未找到)和 410(消失)之外,几乎所有响应状态代码都是可接受的。
但是,如果出现 HTTP 503(服务不可用)响应,'request' NodeJS 库将此报告为错误,然后导致 Promise 包装 request.head() 调用被拒绝了。
由于 API 的实现方式有很大差异,如果位于 URL 后面的 API 管理层想要显式阻止 HTTP HEAD请求,那么它可能会通过响应 HTTP 503 而不是更期望的 HTTP 405(方法不允许)来实现。此外,如果 API 已被沙盒化,则 HTTP 503 是预期的状态代码。
无论如何,HTTP 503 证明这个 URL 实际上是有效的,即使我使用可能不允许的 HTTP 方法调用它。
我认为 "unrejecting" Promise 是一种滥用(而且可能也是不可能的),所以我不得不自己处理 HTTP 请求,这样 503 就不会被视为错误。
有人有更好的主意吗?
谢谢
克里斯·W
I think "unrejecting" the Promise is an abuse (and probably also impossible),
"Unrejecting"一个Promise确实是不可能的。改变状态的唯一方法是通过 .then()
或 .catch()
形成一个承诺链,并从回调中进行适当的 returns (或抛出)。
so I'm left with the possibility of having to handle the HTTP requests myself in such a way that 503 is not considered an error.
这可能是最现实的方法,即 request.head()
的定制、手动承诺。
问题表明错误代码列表很短(404 和 410),因此只有遇到这些代码时才更容易拒绝。
function testUrl(url) {
const badCodes = [404, 410];
return new Promise((resolve, reject) => {
request.head(url, (error, response, body) => {
if(error) {
if(response && badCodes.indexOf(+response.statusCode) === -1) {
resolve(response.statusCode);
} else {
reject error;
}
} else {
resolve(response.statusCode);
}
});
});
}
或者,如果您要接受的错误代码列表很短,那么测试逻辑很容易反转。
function testUrl(url) {
const goodCodes = [503];
return new Promise((resolve, reject) => {
request.head(url, (error, response, body) => {
if(error) {
if(response && goodCodes.indexOf(+response.statusCode) > -1) {
resolve(response.statusCode);
} else {
reject(error);
}
} else {
resolve(response.statusCode);
}
});
});
}
你可以玩弄逻辑来得到你想要的。
无论你最终得到什么,请致电:
testUrl('http://path/to/resource').then(function(statusCode) {
// pass
}, function(error) {
// fail
});