javascript - 使用 Axios 在 Microsoft Teams 中发布消息

标签 javascript axios postman microsoft-teams

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/

相关文章:

javascript - 其他集合的 lodash 过滤器集合

reactjs - 使用 catch 在 redux-saga 中处理 Rest API axios 错误

javascript - Vimeo channel 和视频未显示

javascript - 不能将 ctrl + click 与 preventDefault 一起使用并返回 false

javascript - 网页包 + react : Module parse failed: Unexpected token: You may need an appropriate loader

javascript - 来自不同文件夹的 Jquery.load URL

vue.js - vue js axios响应数组列表

javascript - findByIdAndUpdate 不断被捕获在 .catch 中

azure - 为什么 jwt.io 无法解码 google JWT token

java - 授权用户读取 URL 正文内容时出错