English | Japanese SourceForge.JP
Copyright (c) 2011-2012 Yutaka Saito

HTTP アクセス

HTTP 経由でファイルをダウンロード

汎用のストリームコピー関数 copy を使って、HTTP 経由のファイルダウンロードができます。

import(net.http)
copy('http://sourceforge.jp/', 'sf.html')

プロキシを通す場合は、以下のように net.http.addproxy() を使ってプロキシサーバの設定をしてください。

import(net.http)
net.http.addproxy('xx.xx.xx.xx', 8080, 'username', 'password')
copy('http://sourceforge.jp/', 'sf.html')

HTTP 経由で CSV ファイルを読み込んでデータ処理

SVN のレポジトリに格納されている CSV ファイルを HTTP プロトコル経由で読み込んで表示します。

import(csv)
import(net.http)
uri = 'http://sourceforge.jp/projects/gura/svn/view/trunk/' \
      'test/50records-en.csv?view=co&root=gura'
Person = struct(name:string, email:string, gender:string, age:number, rest*)
people = Person * csv.reader(uri):iter
println(people)

CSV ファイルを読み込む関数 csv#read() そのものは、HTTP に関して何も知りません。言語本体が、パス名から適切なモジュール (上記の場合 net.http) のオープン関数を呼び出し、ストリームにして関数に渡しています。関数がストリームを引数として受け取るようにしておけば、HTTP などの通信プロトコルや、さまざまなデータ構造にアクセスできるようになります。

データベースアクセスと HTTP プロトコル

HTTP サーバとして動作します。日付と 3 個所の温度を記録した SQLite3 データベースファイル temperature.sqlite3 を読み込んでグラフ描画した結果を、クライアントに返します。

スクリプトを実行すると、HTTP のリクエスト待ちになります。ブラウザから http://localhost/?site=0,1 のようにアクセスしてください。 Linux で動作させる場合は、ルート権限でスクリプトを実行するか、ポート番号を 1024 以上に書き直してください。

import(re)
import(cairo)
import(net.http)
import(png)
import(sqlite3)

makeGraph(iSites[]:number) = {
    tbl = struct(day:number, temps*:number) * \
        sqlite3.db('temperature.sqlite3').query('select * from sites')
    img = image(`rgba, 320, 320, `white)
    [wdAxis, htAxis] = [img.width * 0.9, img.height * 0.9]
    [xAxis, yAxis] = [(img.width - wdAxis) / 2, (img.height - htAxis) / 2]
    [dayMax, dayMin] = [tbl:*day.max(), tbl:*day.min()]
    dayRange = dayMax - dayMin
    [tempMax, tempMin] = [tbl:*temps:*max().max(), tbl:*temps:*min().min()]
    tempRange = tempMax - tempMin
    calcX(day) = xAxis + (day - dayMin) * wdAxis / dayRange
    calcY(temp) = yAxis + htAxis - (temp - tempMin) * htAxis / tempRange
    img.cairo {|cr|
        cr.set_line_width(img.height / 300)
        cr.rectangle(xAxis, yAxis, wdAxis, htAxis).stroke()
        cr.save {
            cr.set_dash([img.height / 200, img.height / 200], 0)
            cr.move_to(xAxis, calcY(0)).line_to(xAxis + wdAxis, calcY(0))
            cr.stroke()
        }
        for (iSite in iSites) {
            func = cr.move_to
            for (item in tbl) {
                func(calcX(item.day), calcY(item.temps[iSite]))
                func = cr.line_to
            }
            cr.stroke()
        }
    }
    img
}
net.http.server(port => 80).wait {|req|
    iSites = [0]
	query = net.http.parsequery(req.query)
    if (query.haskey('site')) {
        iSites = tonumber(query['site'].split(','):list)
    }
    buff = binary()
    makeGraph(iSites).pngwrite(buff)
    req.response('200', nil, buff,
        'Server' => 'Gura_HTTP_Server' 'Connection' => 'close')
}