5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SlackWebAPIでJSONが利用できなかった話

Last updated at Posted at 2021-08-12

SlackのWebAPIを使ってメッセージを投稿しようとしたときに、JSONで送るとなぜかエラーで送れないという話を聞いたので調査しました。

状況確認

リファレンスを見ると、確かに、JSONで送れると書いてあります。
そして下記に従う必要があるそうです。

There are some ground rules:

  • You must explicitly set the Content-type HTTP header to application/json. We won't interpret your POST body as such without it.
  • You must transmit your token as a bearer token in the Authorization HTTP header.
  • You cannot send your token as part of the query string or as an attribute in your posted JSON.
  • Do not mix arguments between query string, URL-encoded POST body, and JSON attributes. Choose one approach per request.
  • Providing an explicitly null value for an attribute will result in whichever default behavior is assigned to it.

これに合うメッセージ送信処理をJavaScriptで書いてみます。

JSONでメッセージ送信
const request = new XMLHttpRequest();
request.open('POST', 'https://slack.com/api/chat.postMessage', true);
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('Authorization', `Bearer ${token}`);

let data = {};
data['channel'] = '投稿先のチャンネルID';
data['text'] = '送信メッセージ';
request.send(JSON.stringify(data));

ボタンをクリックしたら上記処理が実行されるようなWebページを作って試してみたところ、こんなエラーが表示されました。

クロスオリジン要求をブロックしました:
同一生成元ポリシーにより、https://slack.com/api/chat.postMessage にあるリモートソースの読み込みは拒否されます
(理由: CORS プリフライト応答からのヘッダー 'Access-Control-Allow-Headers' によりヘッダー 'authorization' が許可されていない)。

CORSのプリフライトでエラーとなっていますね。
CORSについては こちらを参考にして下さい。

Authorization ヘッダーが許可されていないということですが、上記のSlackのマニュアルにはTokenはAuthorization ヘッダーに書けって書いてあるしどうしろと。。。

ではどんなヘッダーなら許可されているのか、プリフライトのレスポンスの内容を見てみました。
スクリーンショット 2021-07-17 18.21.19.png

うーん、なんだかこれ、外部からアクセスされることを想定していない設定のような…。

と、ここで一つの疑惑が。

application/json に対応しました(ブラウザからの実行に対応したとは言っていない)

ということなのではないかと。

検証

ではブラウザを使わずに実行してみましょう。

Node.jsを使ってターミナルから同じ処理を実行しました。
送れた!

ということで黒です。

対処法

ブラウザから送る場合はJSONは諦めて、 Content-Type には application/x-www-form-urlencoded を設定することになります。

URLエンコードでメッセージ送信
const request = new XMLHttpRequest();
request.open('POST', 'https://slack.com/api/chat.postMessage', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

const channelID = '投稿先のチャンネルID';
const message = '送信メッセージ';
request.send(`token=${token}&channel=${channelID}&text=${message}`);

この仕様、Slack WebAPIのマニュアルには全く見当たりません。
フロントエンドから直接呼ばれるような使い方はあまり想定していないなのでしょうか。

5
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?