原因
仕事でOracle B2Cというやつを召喚しまして。
したらまあ、構築してくれた人が Account
を日本語名で作ってくれやがったりしたわけです。
それをAPIでごにょごにょするわけです。
C#で組むのでもよかったのですが、後々の保守だったりの手間を省くためにGASを使う方向で、となった時に問題になるのがアカウントの日本語名ですよ。
Oracle B2Cの仕様
Oracle B2CさんのAPIの認証は簡単で、BASIC認証です。
ざっくり こういう仕様 ですね。
普通のBASIC認証のようです。
base64変換( 名前 + ':' + パスワード )
をやればいいということで。
GASで普通にやれば以下のようになりますね。
const ORACLE_USER = "ほにゃらら";
const ORACLE_PASS = "foobar";
const ORACLE_DOMAIN = "test.example.com";
function myFunction() {
var url = `https://${ORACLE_DOMAIN}/services/rest/connect/v1.4/incidents`;
var authCode = Utilities.base64Encode(ORACLE_USER + ":" + ORACLE_PASS);
var res = UrlFetchApp.fetch(url, {
'method': 'get',
'headers': {
'Authorization': " Basic " + authCode,
'osvc-crest-application-context': '1',
"muteHttpExceptions": true
}}
);
}
試してみると、
Exception: Request failed for https://test.example.com returned code 401. Truncated server response: {"type":"https://test.example.com/services/rest/connect/exceptions/OSC-CREST-00014","title":"このサイトを使用する権限がありません","status":401,"detail":"You are no...
JavaScriptの文字列の内部処理形式はUTF-16です
先のコードが権限異常なのは、「 JavaScriptは文字コードとしてUnicodeを採用し、エンコード方式としてUTF-16を採用しています。 」ということらしい。
UTF-16にbase64かけちゃうので認証コードがおかしくなるんですね。
なので、UTF-8に変換してやらなければいけない。
結局、以下のコードになりました。
const ORACLE_USER = "ほにゃらら";
const ORACLE_PASS = "foobar";
const ORACLE_DOMAIN = "test.example.com";
function myFunction() {
var url = `https://${ORACLE_DOMAIN}/services/rest/connect/v1.4/incidents`;
var blob = Utilities.newBlob(ORACLE_USER + ":" + ORACLE_PASS);
var codeSrc = blob.getBytes();
var authCode = Utilities.base64Encode(codeSrc);
var res = UrlFetchApp.fetch(url, {
'method': 'get',
'headers': {
'Authorization': " Basic " + authCode,
'osvc-crest-application-context': '1',
"muteHttpExceptions": true
}}
);
}
blob作って変換してやるみたいです。
参考元は、ここ とか ここ とか。
ちなみに
ちなみに、C#だと以下。
var code = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{ORACLE_USER}:{ORACLE_PASS}"));
var client = new HttpClient();
client = new HttpClient() { BaseAddress = new Uri($"https://{ORACLE_DOMAIN}"), };
client.DefaultRequestHeaders.Add("osvc-crest-application-context", "1");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", code);
var res = await client.GetAsync($"/services/rest/connect/v1.4/incidents");
よくあるC#のBASIC認証のサンプルコードだと、 Encoding.ASCII.GetBytes
を使ってあるけど、UTF-8を使うようにしておく、と。