2014/12/02


通常、golang のデフォルトの HTTP クライアントは環境変数 HTTP_PROXY もしくは HTTPS_PROXY を参照してプロキシに接続し、環境変数 NO_PROXY で指定されたホストが無視される仕組みになっています。しかし一般ユーザにとって環境変数の設定は、難易度の高い作業だったりします。

使用例

たとえばこういうコードに…

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    res, err := http.Get("http://www.google.com")
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
    defer res.Body.Close()
    io.Copy(os.Stdout, res.Body)
}

一行追加すると:

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"

    _ "github.com/mattn/go-ieproxy/global" // ← この行
)

func main() {
    os.Setenv("HTTP_PROXY""")
    os.Setenv("HTTPS_PROXY""")
    res, err := http.Get("http://www.google.com")
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
    defer res.Body.Close()
    io.Copy(os.Stdout, res.Body)
}

たったこれだけで、IE のプロキシ設定が引き継がれます。無ければデフォルトと同じ様に、環境変数で動作します。

仕組み

ieproxy は ieproxy.ProxyFromIE という関数を提供していて、これが http.Transport.Proxy を実装しています。この関数は http クライアントのプロキシ仲介有無を行っているのでつまりは http.Client の Proxy を設定できます。http.Cilent が HTTP リクエストを実行する際にはこの Proxy が呼び出されて判定処理が行われますが、ieproxy.ProxyFromIE はレジストリから IE のプロキシ設定を取得しつつプロキシの判定を行うような実装になっているので、このように HTTP 通信に引っかけてプロキシをすげかえることができるわけです。

さらに github.com/mattn/go-ieproxy/global パッケージでは http.DefaultTransport.Proxy を ieproxy.ProxyFromIE に書き換え(!)しているので、インポートするだけですべての HTTP 通信が(標準の http パッケージを利用していれば)勝手に IE のプロキシ設定になります。

注意: Windows でしかビルド出来ません。

参考資料: ソースに一行追加するだけですべての HTTP 通信をロギングするモジュールを書いた #golang - 詩と創作・思索のひろば

mattn/go-ieproxy - GitHub
https://github.com/mattn/go-ieproxy
Posted at by



2014/11/18


今日、嫁から電話があり...


嫁「送り主の分からない小包が届いてる」

僕「どんなん?誰から?俺に?」

嫁「それが分からんねん。英語ばっかりや」

僕「なんて書いてる?」

嫁「フェーフェー、フェデークス...」

僕「それ、運送会社や」

嫁「英語ばっかりで分からんわ。開けていい?」

僕「いや、間違いかも知れんし」

嫁「宛名は合ってるねんで」

僕「なんやろ覚えが無い」

嫁「カードでなんか買い物したんちゃうん...」

僕「してないわー」

家で見ても、確かに送り主が分からない。おそるおそる開けて見ると















DSC01360

どどーん。なんか真っ黒いの出てきたと思ったら、ブランケット出てきた。しかも「Google」って書いてある。

DSC01362

かっ... かっちょ... かっちょええやん...

DSC01363

おーぷんそーす ぷろぐらむ おふぃす...

Google is sending out blankets to open-source developers | Hacker News

My perspective comes from the corporate world. On the one hand, it's nice to be acknowledged for wor...

https://news.ycombinator.com/item?id=5650075

これやーーーーー!

ありがとうございます!ありがとうございます!

大事にします!

ただ一つだけ...

出来れば送り主、書いて下さい!

Posted at by



2014/10/22


昨日は naoina さんの genmai を使って wiki を書きましたが、今日は同じく naoina さんが開発している kocha を使って簡単な SPA アプリを書いてみたいと思います。

Kocha web application framework for Go

A convenient web application framework for Go

http://naoina.github.io/kocha/

巷の golang の WAF の殆どは、どちらかというと Sinatra 風の、自前でルーティングハンドラ兼コントローラを書いてくタイプの物ですが、kocha はどちらかというと rails 寄りの WAF に位置します。

rails g でコントローラを生成したりモデルを作ったりといった、コマンドラインベースのジェネレータを使ってガシガシと開発していくフローを実現出来ます。以下手順を追って説明します。

アプリケーションひな形を作る

$ kocha new github.com/mattn/kocho
    create directory /home/mattn/dev/godev/github.com/mattn/kocho/app/controller
              create /home/mattn/dev/godev/github.com/mattn/kocho/app/controller/root.go
    create directory /home/mattn/dev/godev/github.com/mattn/kocho/app/view/error
              create /home/mattn/dev/godev/github.com/mattn/kocho/app/view/error/404.html
              create /home/mattn/dev/godev/github.com/mattn/kocho/app/view/error/500.html
    create directory /home/mattn/dev/godev/github.com/mattn/kocho/app/view/layout
              create /home/mattn/dev/godev/github.com/mattn/kocho/app/view/layout/app.html
              create /home/mattn/dev/godev/github.com/mattn/kocho/app/view/root.html
    create directory /home/mattn/dev/godev/github.com/mattn/kocho/config
              create /home/mattn/dev/godev/github.com/mattn/kocho/config/app.go
              create /home/mattn/dev/godev/github.com/mattn/kocho/config/routes.go
              create /home/mattn/dev/godev/github.com/mattn/kocho/main.go
    create directory /home/mattn/dev/godev/github.com/mattn/kocho/public
              create /home/mattn/dev/godev/github.com/mattn/kocho/public/robots.txt

この状態でも kocha run とすれば動作します。この辺は rails に似た動作になっていますね。golang の場合はシングルバイナリがウリですがもちろん kocha でも kocha build とすればシングルバイナリが生成されます。

モデルを作る

このサンプルではユーザ登録画面を作ろうと思います。とは言っても属性は名前(name)だけとなります。

$ kocha g model user
              create app/model/users.go
生成されるコードは以下の通り。 package model

import (
    "github.com/naoina/genmai"
)

type User struct {
    Id int64 `db:"pk" json:"id"`

    genmai.TimeStamp
}

func (m *User) BeforeInsert() error {
    // FIXME: This method is auto-generated by Kocha.
    //        You can remove this method if unneeded.
    return m.TimeStamp.BeforeInsert()
}

func (m *User) AfterInsert() error {
    // FIXME: This method is auto-generated by Kocha.
    //        You can remove this method if unneeded.
    return nil
}

func (m *User) BeforeUpdate() error {
    // FIXME: This method is auto-generated by Kocha.
    //        You can remove this method if unneeded.
    return m.TimeStamp.BeforeUpdate()
}

func (m *User) AfterUpdate() error {
    // FIXME: This method is auto-generated by Kocha.
    //        You can remove this method if unneeded.
    return nil
}

func (m *User) BeforeDelete() error {
    // FIXME: This method is auto-generated by Kocha.
    //        You can remove this method if unneeded.
    return nil
}

func (m *User) AfterDelete() error {
    // FIXME: This method is auto-generated by Kocha.
    //        You can remove this method if unneeded.
    return nil
}

これに Name 属性を足します。

type User struct {
    Id int64 `db:"pk" json:"id"`
    Name string `json:"name"`

    genmai.TimeStamp
}

コントローラを作る

$ kocha g controller users
              create app/controller/users.go
              create app/view/users.html

コントローラのひな形が生成されました。生成されるコードは以下の様になっています。

package controller

import (
    "github.com/naoina/kocha"
)

type Users struct {
    *kocha.DefaultController
}

func (us *Users) GET(c *kocha.Context) kocha.Result {
    // FIXME: auto-generated by kocha
    return kocha.Render(c)
}

func (us *Users) POST(c *kocha.Context) kocha.Result {
    // FIXME: auto-generated by kocha
    return kocha.Render(c)
}
これを、昨日の例を参考に以下の様に修正します。POST は name パラメータを貰ってモデルに登録します。 package controller

import (
    "github.com/mattn/kocho/db"
    "github.com/mattn/kocho/app/model"
    "github.com/naoina/kocha"
)

type Users struct {
    *kocha.DefaultController
}

func (us *Users) GET(c *kocha.Context) kocha.Result {
    var users []model.User
    err := db.Get("default").Select(&users)
    if err != nil {
        return kocha.RenderError(c, 500, err)
    }
    return kocha.RenderJSON(c, users)
}

func (us *Users) POST(c *kocha.Context) kocha.Result {
    name := c.Params.Get("name")
    if name == "" {
        return kocha.RenderError(c, 400"Bad request")
    }
    user := &model.User{Name: name}
    _, err := db.Get("default").Insert(user)
    if err != nil {
        return kocha.RenderError(c, 500, err)
    }
    return kocha.RenderJSON(c, user)
}

ビューを作る

今回作るサンプルアプリケーションは SPA (Single Page Application) なので、ルートのページのみ編集します。

root.html の編集前は以下の様になっています。

{{define "content"}}
<h1>Welcome to Kocha</h1>
{{end}}

これを弄って以下の様にしました。

{{define "content"}}
<script>
$(function() {
    function update() {
        $.getJSON("/users"function(data) {
            var $u = $('#users').empty();
            $.each(data, function(index, user) {
                $('<li/>').text(user.name).appendTo($u)
            });
        })
    }
    $('#send').click(function() {
        $.post("/users"{"name": $('#name').val()}function() {
            $('#name').val('');
            update();
        });
    });
    update();
})
</script>
<h1 class="title">ユーザ一覧</h1>
<label for="name">名前</label>
<input id="name" type="text">
<input id="send" type="submit" value="追加">
<ul id="users"></ul>
{{end}}

jQuery を使うので app/view/layout/app.html も以下の様に修正しました。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
  <link rel="stylesheet" href="style.css" media="all">
  <title>ユーザ一覧</title>
</head>
<body>
  {{template "content" .}}
</body>
</html>

名前欄に入力された文字列を Ajax で POST して、成功すれば一覧を更新する単純なアプリケーションが出来ました。

kocho

まとめ

始めに仕組みを覚えるまでに間違ったルータを作ってしまったりモデルが決まらなかったりしますが、一旦作り方を覚えてしまえば rails 並みの開発効率が生み出せると思います。

実際にこのサンプルアプリケーションを作るのに20分程度でした(僕は kocha はずいぶん前から遊んでいたので使い方は大体知ってはいましたが)。

ちなみに kocha、Windows でも動きます!(ここ大事)

例によって作ったプリケーションを github に置いておきます。

mattn/kocho - GitHub
https://github.com/mattn/kocho
Posted at by