post Image
Git.io 短縮 URL を golang コードで取得してみる

Git.io で短縮 URL が取得できるらしい

これを読んでたら後ろの方に Git.io の話が出ていた。このサイトで短縮 URL を生成できるらしい。

API が curl で掲載されていて,例えば私の https://github.com/spiegel-im-spiegel なら

$ curl -i "http://git.io" -F "url=https://github.com/spiegel-im-spiegel"
HTTP/1.1 201 Created
Server: Cowboy
Connection: keep-alive
Date: Sat, 08 Aug 2015 02:42:16 GMT
Status: 201 Created
Content-Type: text/html;charset=utf-8
Location: http://git.io/vOj52
Content-Length: 37
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Runtime: 0.210952
X-Node: 871d903e-a8e0-46ff-a96f-ef424385e5ed
X-Revision: b1d9ce07ccb700fc90398edafd397beb8d3bd772
Via: 1.1 vegur

https://github.com/spiegel-im-spiegel

てな感じで,ヘッダの Location 要素に短縮 URL が返ってくる仕組みらしい。

って,これって curl で書けるんなら golang で表現できるんじゃね?

cURL as DSL

cURL as DSL とは curl の構文を任意のコード(今のところは golang, Python, PHP, JavaScript, Java, Objective-C, Vim Script)に変換してくれるもので,どういうことかというと「Web API は curl で表現すればいいんじゃね?」ということらしい。

さっそく curl を golang に変換してみる

では早速,上述の curl コマンドを golang に変換してみる(ちなみに -i は付けない)。こんな感じ。

gitio0.go
package main

import (
    "bytes"
    "io/ioutil"
    "log"
    "mime/multipart"
    "net/http"
)

func main() {
    var buffer bytes.Buffer
    writer := multipart.NewWriter(&buffer)
    writer.WriteField("url", "https://github.com/spiegel-im-spiegel")

    resp, err := http.Post("http://git.io", "multipart/form-data; boundary="+writer.Boundary(), &buffer)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    log.Print(string(body))
}

まずは何も考えずに動かしてみる。

C:>go run gitio0.go
2015/08/08 12:00:00 Invalid url:

あれ? おかしいなぁ。ん~,じゃあちょっと出力をいじって…

gitio1.go
package main

import (
    "bytes"
    "io/ioutil"
    "log"
    "mime/multipart"
    "net/http"
)

func main() {
    var buffer bytes.Buffer
    writer := multipart.NewWriter(&buffer)
    writer.WriteField("url", "https://github.com/spiegel-im-spiegel")

    resp, err := http.Post("http://git.io", "multipart/form-data; boundary="+writer.Boundary(), &buffer)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    log.Println("  Status: ", resp.Header.Get("Status"))
    log.Println("Location: ", resp.Header.Get("Location"))
    log.Println("    Body: ", string(body))
}
C:>go run gitio1.go
2015/08/08 12:00:00   Status: 422 Unprocessable Entity
2015/08/08 12:00:00 Location:
2015/08/08 12:00:00     Body: Invalid url:

ん? あっそうか。 url がちゃんと渡ってないんだ。ひとしきり悩んだ後,以下のようにすればいいことに気がついた。

gitio2.go
package main

import (
    "bytes"
    "io/ioutil"
    "log"
    "mime/multipart"
    "net/http"
)

func main() {
    var buffer bytes.Buffer
    writer := multipart.NewWriter(&buffer)
    writer.WriteField("url", "https://github.com/spiegel-im-spiegel")
    writer.Close() //writer はちゃんと閉じましょう

    resp, err := http.Post("http://git.io", "multipart/form-data; boundary="+writer.Boundary(), &buffer)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    log.Println("  Status: ", resp.Header.Get("Status"))
    log.Println("Location: ", resp.Header.Get("Location"))
    log.Println("    Body: ", string(body))
}

多分 buffer に flush されてなかったんだね(この問題は修正されたようです)。これで

C:>go run gitio2.go
2015/08/08 12:00:00   Status: 201 Created
2015/08/08 12:00:00 Location: http://git.io/vOj52
2015/08/08 12:00:00     Body: https://github.com/spiegel-im-spiegel

となり,めでたく短縮 URL が取得できた。

ちなみに,これには http.PostForm 関数を使った別解がある。最初の curl の式の -F-d にかえればいいらしい。結果は以下の通り

gitio0b.go
package main

import (
    "io/ioutil"
    "log"
    "net/http"
    "net/url"
)

func main() {
    values := url.Values{
        "url": {"https://github.com/spiegel-im-spiegel"},
    }

    resp, err := http.PostForm("http://git.io", values)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    log.Print(string(body))
}

今回に限れば,こちらのほうがコードがスッキリして分かりやすい。

では,楽しい夏休みを!


『 Go 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。