oinume journal

No programming, no life

Mocking a HTTP access with http.Transport in GoLang

I've investegated a way to mock HTTP request and response when writing a code to access to a HTTP API with http.Client. Finally, I found that I can do it by just implementing RoundTrip method of http.RoundTripper.

Here is an example of mocking and proxying HTTP request and response. Running with go run main.go -mock mock, you can get mocked result and with go run main.go -mock proxy, you can get proxied result with httptest.Server.

package main

import (
    "flag"
    "fmt"
    "io/ioutil"
    "net/http"
    "net/http/httptest"
    "net/url"
    "strings"
)

var mock = flag.String("mock", "", "Doesn't perform real access when 'proxy' or 'mock' is specified")

func main() {
    flag.Parse()
    client := http.DefaultClient

    if *mock == "proxy" {
        server := newServer()
        defer server.Close()

        client.Transport = &http.Transport{
            // Proxy to httptest.Server which created above
            Proxy: func(req *http.Request) (*url.URL, error) {
                return url.Parse(server.URL)
            },
        }
    } else if *mock == "mock" {
        client.Transport = newMockTransport()
    }

    resp, err := client.Get("http://ifconfig.co/all.json")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println("GET http://ifconfig.co/all.json")
    fmt.Println(string(body))
}

// Create a HTTP server to return mocked response
func newServer() *httptest.Server {
    return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(200)
        w.Header().Set("Content-Type", "application/json")
        fmt.Fprintln(w,
            `{
    "Accept-Encoding": [
        "proxy"
    ],
    "User-Agent": [
        "proxy"
    ],
    "X-Ip-Country": [
        "Japan(Proxy)"
    ],
    "X-Real-Ip": [
        "192.168.1.1"
    ]
}`)
    }))
}

type mockTransport struct{}

func newMockTransport() http.RoundTripper {
    return &mockTransport{}
}

// Implement http.RoundTripper
func (t *mockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    // Create mocked http.Response
    response := &http.Response{
        Header:     make(http.Header),
        Request:    req,
        StatusCode: http.StatusOK,
    }
    response.Header.Set("Content-Type", "application/json")

    responseBody :=
        `{
    "Accept-Encoding": [
        "mock"
    ],
    "User-Agent": [
        "mock"
    ],
    "X-Ip-Country": [
        "Japan(Mock)"
    ],
    "X-Real-Ip": [
        "192.168.1.1"
    ]
}`
    response.Body = ioutil.NopCloser(strings.NewReader(responseBody))
    return response, nil
}

I think it's very simple to mock a HTTP request in GoLang. net/http package is awesome.

Go Programming Blueprints

Go Programming Blueprints

Changing bower package cache directory

bower caches packages in ~/.cache/bower. How can I change the directory? bower's document says "Add the following in .bowerrc" but it's totally wrong.

"storage": {
  "cache" : "~/.bower/cache",
  "registry" : "~/.bower/registry"
}

I try the configuration and run bower install but nothing changed. I finally found out correct configuration in bower/config repo.

"storage": {
  packages: ".bower/packages",
  registry: ".bower/registry"
}

Why the document of famous software such as bower is wrong?

TypeScript Essentials

TypeScript Essentials

2015年の抱負

一年の計は元旦にあり、という言葉がありますがこのエントリーは1月4日に書いています。どうもこんにちは。あまり一年の目標は立てずにフラフラと生きてきたんだけど、アラフォーに近づいてきてそろそろ自堕落な生き方に危機感を覚えてきたので今年の目標を書いておく。

Dockerを実戦投入する

仕事では余裕なくてDocker使ってないんだけどちゃんと使って運用できるようにしたい。早くEC2 Container Service使えるようにならないかなぁ。

英語でブログエントリーを書く割合を25%にしてみる

英語なりプログラミング言語は使う機会がないとドンドン衰えちゃうんだけど、残念ながら職場ではドキュメントを読む以外ではまったく必要ないので、このブログのエントリーで英語の割合を増やしてみようと思う。というわけで日本人以外にも読めるようにブログタイトルを変えてみた。

フロントエンド(Web)を頑張る

ReactとTypeScriptを習得したい。ネイティブアプリ系はそのうち消え行くと思うのであえてやらない。

Reactive Programmingをちゃんと理解する

Reactive Programmingが今年は来そうな気がするのでちゃんと理解して使えるようにしたい。

アルゴリズムを深く理解する

よく使われるdeflateとかB+Treeとか、実際に自分で実装してみて中身まで理解しないとなぁと思う今日このごろ。普通にWebサービスを作っているだけだと「データベースからデータを取得したものをちょい加工して返す」みたいなプログラムしか書かなくてアルゴリズム回りの知識をアップデートできないので。

2014年振り返り

1/3に2014年の振り返りをしている時点ですでに周回遅れになっているわけですが... 技術的な振り返りは2014年に使ってみた技術に書いたので、仕事やプライベートのことを振り返ってみる。

  • 仕事では7月ぐらいにゲーム系じゃなくてメディア系を立ち上げる部署に異動した。Unityを触ったりしたんだけど、やっぱりゲームを作るのは相当な労力がいるし自分には向いてないんじゃないかなぁと思ってメディア系の部署へ。あと今回は第一線でバリバリ開発する立ち位置なので今は産みの苦しみを絶賛味わってます。あとちょっと...
  • プライベートでは、1月ぐらいに車をお義母さんからゆずってもらって15年ぶりぐらいに車を運転してみた。15年間ペーパードライバーだったんだけど、奥さんが妊娠してたので強制的に病院の送り迎えをすることになり、近距離ならなんとか運転できるようになってきた。人だけは轢かないように心がけてる。車種はトヨタのAllionっていうセダン。すでに12万キロ走っているのでそろそろ壊れる気がする。
  • あと人生の一大イベントで4月に息子が生まれててんやわんや。でもとてつもなくかわいくて毎週成長を見るのが楽しい。仕事できる時間が減り、自分の時間もほぼゼロになってしまったけど、息子を育てる方が社会に貢献できている気がするw 出生率があがれば高齢化社会や人口減少問題が緩和されるらしいので、もう一人ぐらい頑張りたいところ。
  • 飼い猫のししまるが2歳に。2014年は年初から誤飲事件が発生して救急病院に通った。おかげでペット保険の必要性を認識して加入。その後ちょいちょい医者にかかっているのでこれは入っておいてよかったなと思う。今はししまる毎日元気に走り回って息子の攻撃からもひらりと身をかわしている。
  • Amazonでモノを買うのを辞めて、yodobashi.comのヘビーユーザーになった
  • ライブは2月にAvril、11月にKnotfestでKORNを見たぐらい。毎年行っていたサマソニも自粛したので今年こそ行きたい。KORNまた今年も来日しないかな。

2014年に使ってみた技術

新年明けましておめでとうございます。2014年内に書き上げるはずの記事がずっと下書きのまま眠ってしまっていた... 2014年は細かいものを含めるといろいろ新しいものを使い始めたのでそのまとめ。

Ansible

Chefがあまり好きではないのでAnsibleを今やっているプロジェクトで入れてみた。

  • DSLを覚えなくてはいけないのはどちらも一緒
  • Ansibleの方が仕組みがシンプルでPlaybookに書いた順に実行されるのでわかりやすい
  • Dynamic Inventory便利
  • AnsibleはYAMLなのでロジックをゴリゴリ書くのには向いていない
    • Chefはその点Rubyのコードなのでなんでもできる

という感じでどっちもどっちだなという印象。個人的にはChefのようにコードが実行される方がフレキシブルでいいと思っているので、Fabric + Cuisineも試してみたい。

Packer

Vagrantで使うイメージファイルを作るのに使った。便利。時雨堂のリポジトリがとても参考になった。

awscli

便利すぎ。AWSのドキュメントは情報量が多すぎて読むのがつらいんだけど、代わりにこのツールのドキュメントを読むとAWSで何ができるのかが大体把握できるので( ・∀・)イイ!!

Go

Cをちょっと今風にした言語。言語仕様としてはJava 1.2ぐらいのレベルのもので正直扱いづらい。ただ、あえて言語仕様をシンプルにしていて、読みやすさを重視しているというのは大規模開発には向いているのでは?と思って導入してみた。今めちゃくちゃ勢いあるし。

導入してよかったなと思う点は、

  • 静的型付け言語なので安心してリファクタリングできる
  • 半年ごとにバージョンアップするしで着実に進化はしている
  • go getなどのツールが充実してる

つらいところは

  • ベストプラクティスがわからないことが多い
  • Webアプリケーションフレームワークやパッケージ管理が乱立し過ぎていて選択が難しい
  • 他の言語で当たり前のようにできることができなかったりする

というところかなぁ。ブログにもちょいちょい小技を書いているのでよかったらどうぞ。

percol, peco

開発環境回りではこれが一番効果があった気がする。サーバーサイドのエンジニアだとターミナルという黒い謎の画面を見て怪しげなコマンドをたくさん打たなくてはいけないんだけど、そのコマンドの履歴の検索とか絞り込みが画期的にやりやすくなる。最初はpercol使ってたんだけど、pecoの方がバイナリもあって楽にインストールできるので乗り換えた。あとはzsh関連のよさ気なヤツを入れてみた。その辺の話はここで。

tmux, tmuxinator

3年前まではscreenを使っていて、その後はMacのiTermで複数タブでしのいでいたんだけどターミナル環境見直しの一環でtmuxを導入してみた。詳しくはターミナル環境を見直す(3) - tmux編を見てもらえればと。

tmuxinatorは

$ mux start sample

ってやるとこんな感じのYAMLの設定ファイルに書いた内容でtmuxのwindowがバババーンと立ち上がるのがすごい便利。

Angular.js

ちょっとした自分向けのツールで使ってみた。あまりJavaScriptが得意ではない自分としてはすごく簡単にdata bindingできるので純粋に便利だなぁと思ったけど、大きめのアプリをAngularで実装しようと思うと覚えることが多くてツラい印象。「こういう時どうするんだっけ?」っていうのをイチイチググらないとAngular way がわからなくてつらい感じ。

Atom

最近はIntelliJで開発することが多いんだけど、ちょっとしたテキストの修正にはGitHub製のAtomを使ってる。

  • Markdownのプレビューがデフォルトでできる
  • CoffeeScriptで拡張できる

のがメリットかなぁ。試しに突然の死ジェネレータのパッケージを作ってみたりしたのと、Qiitaにこんなのを書いたりした。

入門Ansible

入門Ansible