Xojo で Web アプリ Tips ( Web1.0 )


(2021/01/22追記)
以下の記述は主に Xojo 2019 r3.1/3.2 のもの。 Xojo 2020 以降は Xojo フレームワークとしての Web2.0 に移行していてかなり相違があることに注意。

cgi/スタンドアロン/cloud(?) 共通

複数のWebアプリを同一ホストで動かす

Application Identifier の値を別個にする

サーバに設置する場合、アプリ名が異なっていたとしても標準では config.cfg ファイルが同じ名前のファイルとなるので、競合しないようにしないといけない。アプリごとに別ディレクトリに設置するなど。

cgi として動かすノウハウ

デプロイするには

Help - License Keys でライセンスを通しておく。

Deployボタンは Xojo Cloud 用。自前のサーバで動かす場合はBuildボタンを押す。
Buildボタンが押せない場合は左側の「Build Settings」でターゲットを選ぶ。

今回は、Ubuntu Linux 18.04で動かすのでLinuxを選択する。

Buildすると以下のようなファイルができるので、フォルダごと圧縮してサーバに転送。

Ubuntu 18.04 サーバで cgi として動かす設定

apache2 をあらかじめインストールしておく。
先の圧縮ファイルを例えば /var/www/html/test に展開して、そこで動かしたいとする。

apache の cgi モジュールをインストール


$ sudo a2enmod cgid

今回は、 /var/www 以下全てで CGI が動作するようにしました。


$ sudo vim /etc/apache2/apache2.conf

・・・
<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>
・・・


・・・
<Directory /var/www/>
        Options Indexes FollowSymLinks execCGI
        AddHandler cgi-script .cgi .pl
        AllowOverride None
        Require all granted
</Directory>
・・・

今回は、サーバでcgiだけしか動かさないので /etc/apache2/apache2.conf に記述したが、そうでなければ /etc/apache2/conf-available/cgi-enabled.conf などでディレクトリ指定をするのが望ましい。

ブラウザで、http://(サーバIPアドレス)/test を開けたら index.cgi が動作するように設定します。Ubuntu 18.04では既に設定されていたので確認だけ。


$ sudo vim /etc/apache2/mods-enabled/dir.conf

以下のように設定されていました。


・・・
<IfModule mod_dir.c>
        DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
</IfModule>
・・・

変更の反映


$ sudo service apache2 reload


Ubuntu 18.04 サーバに設置する場合のアプリファイルの設定

/var/www/html/test に展開しました。


$ cd /var/www/html/test

アクセス権限を設定します。


$ sudo chown -R www-data:www-data *
$ sudo chmod 705 mysqlwebtest.cgi
$ sudo chmod 705 MySQLWebTest

http://(サーバIPアドレス)/test で動作するようにします。


$ sudo mv mysqlwebtest.cgi index.cgi

アプリ名の制限

アプリ名は標準ではプロジェクト名が引き継がれる。アプリ名を

Build settings の Linux App Name で指定した名前が cgi ファイル名になる。
ここで日本語を指定したがうまく動かないようだ。

Windowsでビルド、Linuxに転送した場合。

IDEからの実行や、リモート実行時には問題ないが、cgi として動作できない。

また、Linux では Linux app Name が日本語の場合ビルドしても cgi ファイルが生成されない。

プロジェクト名が日本語、Linux app Name が英語の場合は cgi ファイルが生成されるが実行時にエラーとなる。

Raspberry Pi を サーバにして cgi で動かす場合

Raspberry Pi の設定

確認は以下の環境で行っています

  • Raspbian GNU/Linux 10 (buster)
  • Raspberry Pi 3 Model B

「Ubuntu 18.04 サーバで cgi として動かす設定」

アプリのビルド

Build Settings の Linux を選び、 Inspector で Architecture を ARM 32-bit を選びます。

アプリファイルの設定

「Ubuntu 18.04 サーバに設置する場合のアプリファイルの設定」

と同じ設定で動きました。

Raspberry Pi

デプロイをUSBメモリで

Windowsで作ったバイナリをRaspberryPiなどにデプロイする時、USBメモリを使うやり方。
USBメモリに作成したファイルをコピーしてRaspberryPiに刺して電源を入れる。
RaspberryPiではDocumentRootをUSBメモリにしておいて、そのままUSBメモリに入ったcgiが動作する。
している。
まず、USBメモリを起動時に /mnt にマウントする。
Raspberry Pi の /etc/rc.local の最後、


exit 0 

の手前に


mount -o exec,uid=33,gid=33 /dev/sda1 /mnt

exit 0

と記述。vfat に入っているプログラムは通常実行できないが、実行権をつけてマウント、所有者のユーザ・グループをwww-data/www-data とすることで、cgi として動作するようになっている。当然、vfat なのでアクセス権に依存するプログラムは注意。

次に、apache2 の DocumentRootの設定。
/etc/apache2/apache2.confの


<Directory /var/www/>
    Options Indexes FollowSymLinks execCGI
        AddHandler cgi-script .cgi .pl
    AllowOverride None
    Require all granted
</Directory>

を以下のように書き換え


<Directory /mnt/>
    Options Indexes FollowSymLinks execCGI
        AddHandler cgi-script .cgi .pl
    AllowOverride None
    Require all granted
</Directory>

Raspberry Pi の GPIO操作

apache2 で cgi で動作させる場合は www-data となるので、通常では GPIO 操作に制限がある。
いろんなやりかたがあるが、セキュリティを特に気にしなくても良い場合は、sudoer に www-data を登録する。

$ sudo visudo

として、最後に

www-data ALL=(ALL) NOPASSWD: ALL

を追加する。

WebListBox

WebListBox の行全部削除

Desktop の ListBox だと RemoveAllRows ですが、WebだとDeleteAllRows

WebListBox のどの行をセレクトしたかを取得する

SelectionChanged イベントに書く


Var id As String
If Me.ListIndex < 0 Then
  MessageBox("Please select a row.")
Else
  id = Me.Cell(Me.ListIndex, 0)
End If

WebListBox の列数を取得する

Desktop アプリで使う
Listbox.ListCount
の代わりに
Listbox.RowCount
を使う

WebListBox の特定のセルの色を変える

テキストを赤にしたWebStyleを作り、


ListBox1.CellStyle(1,0) = WebStyleTextRed

とすると

となる。
WebStyleの作り方は別掲。

WebListBox に追加した行を取得

Desktop の ListBox だと LastAddedRowIndex ですが、Web だと該当のものが無いので LastIndex で代用

その他UI

WebTextのフォント属性

フォントサイズやテキストカラーなどは、Desktopアプリのようには指定できない。代わりにスタイルを設定して適用する。

WebStyle の設定

Project Items から Style (カラーチップのアイコン)を選び、 Contentsペインにドラッグします


Add Property を押して必要な属性を設定します。

WebImageView

Desktopアプリだと


ImageWell1.Image = thumbnail

となるところが、Webアプリだと


WebImageView1.Picture = thumbnail 

となる。

TextField で エンターを検出

WebTextField, WebTextArea and WebSearchField 共通。


Select Case details.KeyCode
Case details.KeyEnter
  MessageBox("Enter!")
End Select

注:上記で KeyPressed イベントで動かしていたが、 Xojo 2020 R2.1 では KeyPressed は使えなくなった。代わりに TextChanged を使うが details が使えないのでこの方法は使えない。エンター検出には JavaScript が必要かな。

ブラウザの縦スクロールができない

WebPage1のSizeのMinHeightを増やしておく

プロパティetc

WebSession.ClientTime

返ってくるのはWebサーバの時刻

Command.Execute

LinuxでCommand.Executeするときの改行コード


Dim Command As New Shell
Command.Execute("echo "+id+" >> log")
MsgBox(Command.Result)

としたところ、log の改行コードはlfでした。

実行パス

何と、 "/"

トラブルシューティング

RaspberryPiで実行したら、以下のようなエラーが出た


[Sat Apr 25 17:18:16.790080 2020] [cgid:error] [pid 450:tid 1858057248] [client 192.168.162.19:56411] End of script output before headers: mysqlwebcardwrite.cgi, referer: http://192.168.162.77/
Can't use an undefined value as a symbol reference at /mnt/MySQLWebCardWrite/mysqlwebcardwrite.cgi line 118.

はてなーと思っていたら何もしてないのにそのまま動くようになった。
起動に時間がかかっていたようだ。

(2021/05/18追記)

Webアプリをcgiで動かす時に、結構これが発生する。
別インスタンスで XOJO Web アプリが動いている場合にこれが発生しやすいようだ。
スタンドアローン Web アプリだとこのような問題は発生しない。

cf., 「Xojo で スタンドアローン Web アプリを RaspberryPi で動かす」
https://qiita.com/nanbuwks/items/615a929babca8986e634