やられた。ここにきて苦戦の予感。

ブツ

インストール&実行

NAME='Electron.net.request.20220811143154'
git clone https://github.com/ytyaru/$NAME
cd $NAME
npm install
npm start

WebAPIを実行するとき以下エラーが出て失敗する。

Uncaught (in promise) Error: An object could not be cloned.

なんぞこれ?

コード抜粋

main.js

const { app, BrowserWindow, ipcMain, dialog, net } = require('electron')
...
ipcMain.handle('request', async(event, params)=>{
    const request = net.request(params.params)
    if (params.hasOwnProperty('body')) { request.write(body) }
    console.log(request)
    // レスポンス受信時の処理
    request.on('response', (response) => {
        console.debug(`STATUS: ${response.statusCode}`)
        console.debug(`HEADERS: ${JSON.stringify(response.headers)}`)
        response.on('data', (chunk) => {
            console.debug(`BODY: ${chunk}`)
            params.onData(JSON.parse(chunk), response)
        })
        response.on('end', () => {
            console.debug('No more data in response.')
            params.onEnd(response)
        })
    })
    // リクエストの送信
    request.end()
})

ElectronのAPI net.request を使ってWebAPIを実行する。

コードがめちゃくちゃ汚い。async/awaitパターンが使えない古い形式のAPIだから。こんなコード書きたくないのだが、APIの仕様なので仕方ない。

引数の中に、WebAPIに渡すものと、リクエスト後の処理を含めている。このrequest.on形式のせいでコールバック形式による実装を強いられる。コールバック地獄いやだ苦しい助けて。

preload.js

const {remote,contextBridge,ipcRenderer} =  require('electron');
contextBridge.exposeInMainWorld('myApi', {
    request:async(params)=>await ipcRenderer.invoke('request', params),
})

renderer.js

window.addEventListener('DOMContentLoaded', async(event) => {
    await window.myApi.loadDb(`src/db/mylog.db`)
    const db = new MyLogDb()
    const setting = await Setting.load()
    const params = {
        params: {
            method: 'GET',
            url: `https://api.github.com/users/${setting.github.username}`,
            headers: {
                'Content-Type': 'application/json',
                Authorization: "Bearer " + setting.github.token,
            },
        },
        onData:async(json, res)=>{
            console.debug(res)
            console.debug(json)
        },
        onEnd:async(res)=>{
            console.debug(res)
        },
    }
    console.log(params)
    await window.myApi.request(params) // Uncaught (in promise) Error: An object could not be cloned.
})

GitHub APIのうちusersを使ってみた。引数も不要なので簡単に使えるはずだと思って適当に選出した。

usersのページにはAcceptヘッダがあるけど、これをつけてcurlしたらエラーになった。

curl \
  -H "Accept: application/vnd.github+json" \ 
  -H "Authorization: token <TOKEN>" \
  https://api.github.com/user
curl: (3) URL using bad/illegal format or missing URL

Acceptヘッダをとると成功した。

{
  "login": "ytyaru",
  "id": 19922005,
...

公式ドキュメントで嘘を書くのはやめてほしい。Microsoft社のドキュメントは昔から信用できないことで定評あるけど。改悪するなら買収前のままにしてほしかった。おかげでハメられたorz