Play with Dockerを使って、色んなプログラム言語でhttp通信してみる

以前、
[UserAgentからOS/ブラウザなどの調べかたのまとめ](https://qiita.com/nightyknite/items/b2590a69f2e0135756dc)
で色んなプログラミング言語から、HttpRequestを試す際、環境の準備にPlay with Dockerを使うのが便利だったので、使いかたを乗せておく。


# Play with Dockerとは

<img width="772" alt="playwithdocker.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34699/2ec7f14b-5f57-ba01-df8f-90ae0d3b0acc.jpeg">


[Play with Docker](https://labs.play-with-docker.com/)は使い捨てで使用できる、dockerの実行環境。
ブラウザさえあれば使用できて、自分のローカルPCの環境は何も変える必要は無い。
ローカルPCへのダウンロードが無いので、モバイル回線でも快適に使用することができる。
使用するには、dockerhubのアカウントが必要になる。

単に複数のプログラミング言語でHelloWorldやFizzbuzzをしたいという場合は[ideone](https://ideone.com)というサイトを使う手もあるが、追加モジュールを入れたりまでは出来ないので出来ることは限られてくる。

* [Play with Docker](https://labs.play-with-docker.com/)
* [Docker 入門にはインストールなしで使える「Play with Docker」がいいと思う](https://qiita.com/tag1216/items/ec7228440f6eaf849cd6)
* [Play with DockerでDocker学習環境を整えよう！
](https://www.slideshare.net/HoriTasuku/play-with-dockerdocker)

# 各言語でHttpRequestをしてみる

色んなプログラミング言語で、docker環境を作って、httprequestを実行を試してみる。
接続先は[ifconfig.io/ua](https://ifconfig.io/ua)につないで、UserAgentを取得する。

初期状態のインスタンスはAlpine Linuxが入っている。そこからDocker In Dockerでdockerコンテナを起動することができる。
環境構築の難易度が楽で時間がかからないものは起動時のAlpine Linuxに環境を作って、
難易度が高いものや時間がかかるものはdockerコンテナをさらに立ち上げて作ることになるか。

## Python

PythonはAlpine Linuxの初期インスタンスにインストール済みなので、Pythonコマンドでreplを起動

```
Python
```

```
>>> import requests
>>> requests.get("http://ifconfig.io/ua")
<Response [200]>
>>> requests.get("http://ifconfig.io/ua").text
u'python-requests/2.20.1\n'
```

## Ruby

apkコマンドでruby-irbをインストール。irbでreplを起動

```
apk add ruby-irb
irb
```

http://ifconfig.io/uaに接続する。

```
irb(main):001:0> require 'net/http'
=> true
irb(main):002:0> Net::HTTP.get_print 'ifconfig.io', '/ua'
Ruby
=> nil
```



## C# 


monoが入ったDebianコンテナイメージを立ち上げる。

```
docker run -i -t mono /bin/bash
```

エディタとしてvimをインストール

```
apt-get update
apt-get install vim
```

エディタを開く

``` 
vim DownloadPageWebClient.cs
```

下記の内容を保存する。

```csharp:DownloadPageWebClient.cs

using System;
using System.Net;

class DownloadPageWebClient
{
    static void Main()
    {
        using (WebClient client = new WebClient()) {
        
            string url = "https://ifconfig.io/ua";
            string content = client.DownloadString(url);
            Console.WriteLine(content);
        }
    }
}
```

ビルドして実行する。

```
mcs DownloadPageWebClient.cs

mono ./DownloadPageWebClient.exe
```

参考サイト

* [monoが動くDockerイメージを作る記事を書いたら非常につまらなかったので、C#アプリをDockerで動かしてみた](https://qiita.com/wilfrem/items/8bbeaad0880041497512)
* [Reading a web page in C#](http://zetcode.com/articles/csharpreadwebpage/)
* [Mono で C# を使う](https://qiita.com/ekzemplaro/items/12df8b9b608fc599e1b6)




## D言語

D言語のコンテナイメージを立ち上げる。

```
docker pull dlanguage/dmd
```

viを立ち上げる。

```
vi getua.d
```

以下の内容をviで作成してファイルを保存する。

```dlang:getua.d
import std.stdio,std.net.curl;
void main() {
    auto content = get("http://ifconfig.io/ua");
    writeln(content);
}
```

実行してみる。

```
$ docker run --rm -ti -v $(pwd):/src dlanguage/dmd dmd -run getua.d
Phobos-std.net.curl/2.080 (libcurl/7.47.0)
```

参考URL

* [DockerとD言語のイメージ](https://kubo39.hatenablog.com/entry/2017/11/30/Docker%E3%81%A8D%E8%A8%80%E8%AA%9E%E3%81%AE%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8)
* [std.net.curl](https://dlang.org/phobos/std_net_curl.html#.get)

## Perl

perl-libwwwをインストールする。

```
apk add perl-libwww
```

client.plファイルを作成

```
cat <<'EOS' > client.pl
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
my $response = $ua->get('http://ifconfig.io/ua');
print $response->decoded_content;
EOS
```

client.plを実行する。

```
perl client.pl
```

httpsの場合

## Perl6


Perl 6のコンテナイメージを立ち上げる。

```
docker run -it rakudo-star
```

以下のコマンドを実行。

```
> use v6;
> use LWP::Simple;
> my $html = LWP::Simple.new.get("http://ifconfig.io/ua");
LWP::Simple/0.105 Perl6/rakudo
```

参考URL

* [Getting started with Rakudo Perl 6 in a Docker container
](http://perl6maven.com/rakudo-perl6-with-docker)
* [Install LWP::Simple](http://perl6maven.com/simple-web-client)

## Groovy

groovyのコンテナイメージを立ち上げる。

```
docker run -it --rm groovy:latest
```

```
groovy:000> new URL("https://ifconfig.io/ua").getText()
===> Java/1.8.0_212
```

* [groovy/docker-groovy](https://github.com/groovy/docker-groovy)
* [Groovy built-in REST/HTTP client?](https://stackoverflow.com/questions/25692515/groovy-built-in-rest-http-client)

## Common Lisp

Common Lispのコンテナイメージを立ち上げる。

```
docker run -it lambdasakura/ubuntu-sbcl
```

HTTPクライアントのDrakmaを入れる。

```
(ql:quickload :drakma)
```


```
(drakma:http-request "http://ifconfig.io/ua")
```

結果

```
"Drakma/1.3.11 (SBCL 1.2.6; Linux; 4.4.0-148-generic; http://weitz.de/drakma/)
```



* [CommonLispの実行環境をDockerで構築してみた](https://light-of-moe.ddo.jp/~sakura/diary/?p=138)
* [Common Lisp入門してwebスクレイピングやろうとしてる](https://qiita.com/hasewogamer/items/3cbb9e7da522af4a7c4d)


## PHP

apkコマンドでphp7をインストール。

```
apk add php7
```

対話シェルを立ち上げる。

```
 php -a
```

file_get_contentsを実行。UserAgentは返ってこない。

```
echo(file_get_contents("http://ifconfig.io/ua"));
```

* [How to install PHP 7 fpm on Alpine Linux](https://www.cyberciti.biz/faq/how-to-install-php-7-fpm-on-alpine-linux/)
* [対話シェル](https://www.php.net/manual/ja/features.commandline.interactive.php)
* [file_get_contents](https://www.php.net/manual/ja/function.file-get-contents.php)

## golang

dockerのイメージを立ち上げる。

```
docker pull golang
docker run -it golang
```

vimをインストールする。

```
apt update && apt upgrade
apt install vim
```

vimを立ち上げる。

```
vim client.go
```

以下の通りvimで保存する。

```golang:client.go
package main

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

func main() {
  url := "https://ifconfig/ua"
  resp, _ := http.Get(url)
  defer resp.Body.Close()
  byteArray, _ := ioutil.ReadAll(resp.Body)
  fmt.Println(string(byteArray))
}

```

実行してみる。

```
go run client.go
```

結果

```
Go-http-client/2.0
```

* [golangでdockerをはじめる ~ goのwebサーバーをdockerでたててみた ~](https://qiita.com/vankobe/items/f4c09e8e4b580651b568)
* [Goでhttpリクエストを送信する方法
](https://qiita.com/taizo/items/c397dbfed7215969b0a5)
* [Package http](https://golang.org/pkg/net/http/)

## Rust

rustのdockerコンテナを起動。
cargoを使用する時に、環境変数USERの指定を求められるので、起動時にUSERを指定しておく。

```
docker pull rust
docker run --rm -e USER=$USER -it rust
```

vimをインストール

```
apt update
apt install vim
```

cargoを使ってプロジェクトを作る。

```
#適当なディレクトリに移動
cd ~
# 新規プロジェクトをhelloで作る。binは起動可能なファイルのオプション
cargo new hello --bin
# hello ディレクトリに移動
cd hello
```

srcディレクトリにmain.rsが出来てるのでこれを編集する。

```
vim src/main.rs
```

```rust:main.rs
extern crate reqwest;
use std::io;
fn main() {
    let mut res = reqwest::get("https://ifconfig.io/ua").unwrap();
    res.copy_to(&mut io::stdout()).unwrap();
}
```

Cargo.tomlを開いて、``reqwest="*"``を追加

```
vim Cargo.toml
```

```toml:Cargo.toml
[dependencies]
reqwest="*"
```

実行する。

```
cargo run
```

結果

```
reqwest/0.9.17
```

* [rust - Docker Hub](https://hub.docker.com/_/rust)
* [docker run(コンテナ作成)する時のオプションあれこれ](https://qiita.com/shimo_yama/items/d0c42394689132fcb4b6)
* [Rustのお勉強 - Cargoを使ってみる](https://qiita.com/toully/items/d394407daede97ebfc37)
* [Rust で素朴に HTTP リクエストを投げる](https://rohki.hatenablog.com/entry/2017/02/11/222838)
* [Crate reqwest](https://docs.rs/reqwest/0.9.17/reqwest/)
* [古い記事に騙されないで！hyperじゃなくreqwestを使ってください](https://qiita.com/harvath/items/f400080758f7d4732708)


## Elixir

dockerでElixirをたちあげる。

```
docker run -it elixir bash
```

対話モードを起動する。

```
iex
```

```
# start `inets` application.
Application.ensure_all_started(:inets)
# start `ssl` application also
Application.ensure_all_started(:ssl)
 :httpc.request(:get, {'https://ifconfig.io/ua', []}, [], [])
```


* [最速で知る！ ElixirプログラミングとErlang/OTPの始め方【第二言語としてのElixir】](https://employment.en-japan.com/engineerhub/entry/2017/06/12/110000)
* [Why Elixir ships without HTTP client?](https://virviil.github.io/2018/04/06/elixir-do-you-have-http-requests-you-are-doing-them-wrong/)

## Erlang

dockerでErlang対話モードでたちあげる。

```
docker run -it --rm erlang
```

アプリケーションを起動

```
1> application:start(inets).
```

GETリクエストを実行

```
2> httpc:request("http://ifconfig.io/ua").
```

* [erlang - Docker Hub](https://hub.docker.com/_/erlang)
* [単純なHTTPリクエストにはhttpcを使おう](https://qiita.com/melpon/items/e55a67ebd992c3662bbf)

## Nim

コンテナを起動

```
docker pull nimlang/nim
docker run -d -it --name nim_app nimlang/nim /bin/bash
docker exec -it nim_app /bin/bash
```

vimをインストール

```
apt-get install vim
```

```
cd /var/opt
vim client.nim
```


```nim:client.nim
import httpclient
const url = "https://ifconfig.io/ua"
var client = newHttpClient()
var response = client.get(url)
echo response.body
```

```
nim c -d:ssl -r client.nim
```

結果

```
Nim httpclient/0.20.0
```

参考サイト

* [Nimをインストールしてみる](https://qiita.com/nemui-fujiu/items/8b541fb9b1f4654938f7)
* [Nim 言語で画像収集クローラーを作ってみた](https://enomotodev.hatenablog.com/entry/2017/10/12/002255)



## Julia

dockerを使って対話モードで起動する

```
docker run -it --rm julia
```


```
julia> using Pkg
julia> Pkg.add("HTTP")
julia> using HTTP
julia> r = HTTP.get("http://ifconfig.io/ua")
julia> println(String(r.body))

```



参考サイト

* [julia Docker Official Images](https://hub.docker.com/_/julia)
* [How To Make REST API Calls In Julia](https://codehandbook.org/make-rest-api-calls-julia/)
* [HTTP.jl Documentation](https://juliaweb.github.io/HTTP.jl/dev/)

## Java(JShell)

Javaを試そうと思ったけど、gradleとかmavenとかビルド環境を整えるのは面倒くさそうなので、Java9以降から使えるJShellを使ってみる。

dockerを使って、JShellの対話環境を準備する。

```
docker run -it openjdk:11 jshell
```

以下のコマンドをそれぞれ実行する。

```
jshell>import java.net.http.*
jshell>var client = HttpClient.newHttpClient();
jshell>var request = HttpRequest.newBuilder().uri(URI.create("https://ifconfig.io/ua")).build();
jshell>HttpResponse<String> res = client.send(request,HttpResponse.BodyHandlers.ofString());
jshell>System.out.println(res.body());
```

結果

```
Java-http-client/11.0.3
```

参考サイト

* [Jshellでゆるーく遊んでみた](https://qiita.com/yut_arrows/items/25283a346780c93acc7d)
* [Learn JDK11 with JShell (2018/12/15 JJUG CCC 2018 Fall)](https://qiita.com/nowokay/items/80e8ccd50f6749846dd6)


## Crystal

dockerを使って対話モードで起動する

```
docker run -i -t crystallang/crystal /bin/bash
```


```
cat << EOS > client.cr
require "http/client"
response = HTTP::Client.get "https://ifconfig.io/ua"
puts(response.body.lines.first)
EOS
```

```
crystal client.cr
```


## Racket

dockerを使って対話モードで起動する

```
docker run -it jackfirth/racket
```


```
(require net/url)

(define ua (port->string (get-pure-port (string->url "https://ifconfig.io/ua"))))
(printf "My ua is: ~a" ua)
```


* [Racket](https://ja.wikipedia.org/wiki/Racket)
* [jackfirth/racket](https://hub.docker.com/r/jackfirth/racket)
* [ipify.org](https://www.ipify.org/)



## PowerShell

dockerを使って対話モードで起動する

```
docker run -it mcr.microsoft.com/powershell:latest
```


```
Invoke-WebRequest https://ifconfig.io/ua
```

```
StatusCode        : 200                                                                                  
StatusDescription : OK                                                                                   
Content           : Mozilla/5.0 (Linux; Linux 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017; en-US) PowerShell/6.2.3
```

* [PowerShell - Docker Hub](https://hub.docker.com/_/microsoft-powershell)

## NodeJS

nodejsをインストール

```
apk add nodejs
```

実行ファイルを作成

```
cat << EOS > client.js
require('http').get('http://ifconfig.io/ua', function(res) {
  res.setEncoding('utf8');
  res.on('data', function(body) {
    console.log(body);
  });
});
EOS
```

ファイルを実行

```
node client.js
```

* [最小のNode.jsのDockerイメージを目指すスレ](https://qiita.com/shibukawa/items/f7076cf4b181ee141bcd)
* [標準HTTPモジュールを使ったGETとPOSTリクエストの簡単なサンプルコード](http://or1ko.hatenablog.com/entry/2014/06/29/185012)


## V言語(VLang)

VLangのdockerイメージを立ち上げる。

```
git clone https://github.com/vlang/v
cd v
docker build -t vlang .
docker run --rm -it vlang:latest
```

docker上でOpenSSLのライブラリをインストールする

```
apt-get install libssl-dev
```

VLangを対話モードで起動する

```
v
```

対話モードで実行

```
>>> import http
>>> resp := http.get('http://ifconfig.io/all.json') or { panic(err) }
>>> println(resp.text)
```

* [The V Programming Language](https://vlang.io/)
* [V プログラミング言語](https://qiita.com/RkEclair/items/be3d4d9198cab32aed64)
* [V言語コトハジメ](https://qiita.com/nekijak/items/ded6977d6a42f0cc7384)



他の言語もそのうち書く。