2020 年 10 月 16 日更新的问题 我简化了代码,因此它不再包含用于运行 postMessageToTeams 函数的 if 语句,并且我添加了在 catch 中收到的错误响应。希望这能让调试变得更容易。
当我从 Visual Studio 终端运行脚本时,它可以工作,但从我的 cmder 运行脚本时,它不起作用。所以我认为这与我的cmder设置有关。
目标
我正在通过 testcafe 运行一些自动化任务,并且希望在某项任务完成时在 Microsoft Teams 中收到通知。为此,我在 channel 中创建了一个 Webhook,并希望向我的 Webhook URL 发送 POST 请求。但是,执行此操作时,我收到 405 错误。在 Postman 中尝试时,它确实可以使用相同的 JSON 数据。
我的代码(为此测试,我稍微更改了 https://gist.github.com/johnsibly/806a7190fbdc4b439ed040f327e6e679 中的代码)
const axios = require('axios'); // axios must be installed via npm i axios
const webhookURL = "https://outlook.office.com/webhook/xxxxx"; // this holds my webhook URL
postMessageToTeams();
async function postMessageToTeams(title, message) {
const card = {
"@type": "MessageCard",
"@context": "http://schema.org/extensions",
"themeColor": "0072C6",
"summary": "Summary description",
"sections": [
{
"activityTitle": "Testcafe",
"text": "Testcafe is talking to you"
}
]
};
try {
const response = await axios.post(webhookURL, card, {
headers: {
'content-type': 'application/vnd.microsoft.teams.card.o365connector',
'content-length': `${card.toString().length}`,
},
});
return `${response.status} - ${response.statusText}`;
} catch (err) {
console.log(err)
return err;
}
}
错误响应
{
status: 405,
statusText: 'Method Not Allowed',
headers: {
'cache-control': 'no-cache',
pragma: 'no-cache',
allow: 'POST',
'content-length': '43',
'content-type': 'text/plain; charset=utf-8',
expires: '-1',
server: 'Microsoft-IIS/10.0',
'request-id': 'b565e1ec-79a2-4fc1-99e1-56e8caa98a48',
'strict-transport-security': 'max-age=31536000; includeSubDomains; preload',
'x-calculatedbetarget': 'AM0PR02MB5570.eurprd02.prod.outlook.com',
'x-backendhttpstatus': '405',
'x-aspnet-version': '4.0.30319',
'x-cafeserver': 'AM3PR07CA0145.EURPRD07.PROD.OUTLOOK.COM',
'x-beserver': 'AM0PR02MB5570',
'x-proxy-routingcorrectness': '1',
'x-proxy-backendserverstatus': '405',
'x-powered-by': 'ASP.NET',
'x-feserver': 'AM3PR07CA0145',
date: 'Fri, 16 Oct 2020 07:58:34 GMT',
connection: 'close'
},
config: {
url: 'https://outlook.office.com/webhook/xxxx',
method: 'post',
data: '{"@type":"MessageCard","@context":"http://schema.org/extensions","themeColor":"0072C6","summary":"Summary description","sections":[{"activityTitle":"Testcafe","text":"Testcafe is talking to you"}]}',
headers: {
Accept: 'application/json, text/plain, */*',
'User-Agent': 'axios/0.20.0'
},
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
validateStatus: [Function: validateStatus]
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype] {
socket: [Function (anonymous)],
abort: [Function (anonymous)],
aborted: [Function (anonymous)],
connect: [Function (anonymous)],
error: [Function (anonymous)],
timeout: [Function (anonymous)],
prefinish: [Function: requestOnPrefinish]
},
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'outlook.office.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 9,
connecting: false,
_hadError: false,
_parent: null,
_host: 'outlook.office.com',
_readableState: [ReadableState],
readable: true,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [TLSWrap],
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular *1],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 15,
[Symbol(kHandle)]: [TLSWrap],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(connect-options)]: [Object]
},
_header: 'GET /webhook/xxxx HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'User-Agent: axios/0.20.0\r\n' +
'Host: outlook.office.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: Agent {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object],
requests: {},
sockets: [Object],
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
maxCachedSessions: 100,
_sessionCache: [Object],
[Symbol(kCapture)]: false
},
socketPath: undefined,
method: 'GET',
maxHeaderSize: undefined,
path: '/webhook/xxxx',
_ended: true,
res: IncomingMessage {
_readableState: [ReadableState],
readable: false,
_events: [Object: null prototype],
_eventsCount: 3,
_maxListeners: undefined,
socket: [TLSSocket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: [Object],
rawHeaders: [Array],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 405,
statusMessage: 'Method Not Allowed',
client: [TLSSocket],
_consuming: false,
_dumped: false,
req: [Circular *1],
responseUrl: 'https://outlook.office.com/webhook/xxxx',
redirects: [],
[Symbol(kCapture)]: false
},
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
_redirectable: Writable {
_writableState: [WritableState],
writable: true,
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
_options: [Object],
_ended: true,
_ending: true,
_redirectCount: 1,
_redirects: [],
_requestBodyLength: 197,
_requestBodyBuffers: [],
_onNativeResponse: [Function (anonymous)],
_currentRequest: [Circular *1],
_currentUrl: 'https://outlook.office.com/webhook/xxxx',
_isRedirect: true,
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype] {
accept: [Array],
'user-agent': [Array],
host: [Array]
}
},
data: 'Invalid webhook request - GET not supported'
}
如果您需要完整的错误消息才能正确调试此问题,请告诉我。
postman
POST 请求的正文(原始)
{
"@type": "MessageCard",
"@context": "http://schema.org/extensions",
"themeColor": "0072C6",
"summary": "Summary description",
"sections": [
{
"activityTitle": "Testcafe",
"text": "Testcafe is talking to you"
}
]
}
回应
1
,该消息发布在我的 Teams channel 中
最佳答案
您应该让 axios
处理有效负载长度的计算,因此删除此行:
'content-length': `${card.toString().length}`
您的帖子生成的脚本如下所示:
const axios = require('axios'); // axios must be installed via npm i axios
const webhookURL = "https://outlook.office.com/webhook/xxxxx"; // this holds my webhook URL
postMessageToTeams();
async function postMessageToTeams(title, message) {
const card = {
"@type": "MessageCard",
"@context": "http://schema.org/extensions",
"themeColor": "0072C6",
"summary": "Summary description",
"sections": [
{
"activityTitle": "Testcafe",
"text": "Testcafe is talking to you"
}
]
};
try {
const response = await axios.post(webhookURL, card, {
headers: {
'content-type': 'application/vnd.microsoft.teams.card.o365connector'
},
});
return `${response.status} - ${response.statusText}`;
} catch (err) {
console.log(err)
return err;
}
}
发现这对我有用。
关于javascript - 使用 Axios 在 Microsoft Teams 中发布消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64339179/