Julia言語で奏でる詩

80億分の1のあなたへ
 

Socketsを使用してRequestを受け取る

カテゴリー: API, julia言語


まだまだ道のりは長いですが,Julia言語でWebサービスを作成してみたく今回はSocketsを使用してみたいと思います.
Socketsを使えるようになることで,外部からのRequestをJulia言語で受け取ることができます.
Requestを受け取ることができれば,Julia言語でRequest内容を処理ができ,Request内容で処理を変えてResponseを返すことができます.具体的にはBotの返信ができるようになるのかなと思います.
取り急ぎの目的としては,LINE Botを作ってみたいと思っています.

私自身のWebの仕組みが詳しくないので少しふわっとした内容になってしまっています.
公開はしていますが,随時更新できたらなと思います.

実際の内容

Webの仕組みに関しては以下の内容を参考にしていただくのが良いかもしれません.
2021年のエンジニア新人研修の講義資料を公開しました
「HTTPリクエスト」と「HTTPレスポンス」

Julia言語,Webの仕組みともに理解が浅いため簡単な処理ですが,かなり苦労しました.
(ただ、これでHTTP通信の基本がわかったかな?)
また,私のようにあまり知識のない方のために極力全部記述しており,少し冗長になっています.
ご了承ください.
# 以下,サーバー側 Julia言語の環境はJyupter notebookになります.

GET通信

まずはGET通信からやりたいと思います.
サーバー側はJulia言語,クライアント側はcurlとJulia言語の2パターンで実装したいと思います.

# サーバー側 Julia言語

using Sockets
using JSON

# リクエストの受付
server = Sockets.listen(8080)

while true
    # リクエストを確立
    sock = Sockets.accept(server)
    # 非同期処理
    @async begin
        # sockにRequestの内容が入っているので1行ずつ読み込み
        data = readline(sock)
        # 最後は空文字になっている空文字になるまで読み込み
        # 何行読み込まれるかはRequestによる
        while data !== ""
            print("Debug:", data, "\n")
            data = readline(sock)
        end

        # クライアントにResponseを返す
        # クライアントによってはResponseの形式を正しくしないとクライアント側でエラーになる(後述)
        println(sock, "HTTP/1.1 200 OK\nContent-Type: text/html\n")
        println(sock, string("<html><body>", "TEST", "</body></html>"))

        close(sock)
    end
end

次にクライアント側になります.
はじめにcurlでRequestをしてみます.

# クライアント側 curl
$ curl -i -s 'localhost:8080/api?'

# 以下,Response(正しくできていれば)
> HTTP/1.1 200 OK
> Content-Type: text/html

# ちなみにサーバー側は以下のように表示されている方と思います(正しくできていれば)
> Debug:GET /api? HTTP/1.1
> Debug:Host: localhost:8080
> Debug:User-Agent: curl/7.52.1
> Debug:Accept: */*

次にJulia言語でRequestをしてみたいと思います.

# クライアント側 Julia言語
using HTTP

# リクエストはHTTPモジュールを使用して1文でできる
HTTP.request("GET",  "http://localhost:8080/api/")

# クライアント側,サーバー側ともに正しくできている以下のように表示される
> HTTP.Messages.Response:
> """
> HTTP/1.1 200 OK
> Content-Type: text/html
> 
> <html><body>TEST</body></html>
> """
# サーバー側はCurlと同様

<注意>
Curlでは大丈夫だったのですが,Julia言語でRequestをした場合,Responseが正しい形式になっていない場合,クライアント側でエラーになります.

POST通信

次にPOST通信に関してです.基本はGET通信とほとんど変わりません.

# サーバー側 Julia言語

using Sockets
using JSON

# リクエストの受付
server = Sockets.listen(8080)

while true
    # リクエストを確立
    sock = Sockets.accept(server)
    # 非同期処理
    @async begin
        # sockにRequestの内容が入っているので1行ずつ読み込み
        data = readline(sock)
        # 最後は空文字になっている空文字になるまで読み込み
        # 何行読み込まれるかはRequestによる
        while data !== ""
            print("Debug:", data, "\n")
            data = readline(sock)
        end
        # === GET通信と異なる ===
        # POST通信は空文字の後にbodyの値がくる(今回はJSON形式)
        data = JSON.parse(sock) 
        print("Debug:", typeof(data), "-", data, "\n")

        # クライアントにResponseを返す
        # クライアントによってはResponseの形式を正しくしないとクライアント側でエラーになる(後述)
        println(sock, "HTTP/1.1 200 OK\nContent-Type: text/html\n")
        println(sock, string("<html><body>", data["Name"], "</body></html>"))

        close(sock)
    end
end

次にクライアント側になります.
こちらもはじめにcurlになります.

# クライアント側 curl
$ curl -X POST -H "Content-Type: application/json" -d '{"Name":"piyo", "Age":"100"}' localhost:8080/api/v1/users

# 以下,Response(正しくできていれば)
> <html><body>piyo</body></html>
> Content-Type: text/html

# ちなみにサーバー側は以下のように表示されている方と思います(正しくできていれば)
> Debug:POST /api/v1/users HTTP/1.1
> Debug:Host: localhost:8080
> Debug:User-Agent: curl/7.52.1
> Debug:Accept: */*
> Debug:Content-Type: application/json
> Debug:Content-Length: 28
> Debug:Dict{String, Any}-Dict{String, Any}("Age" => "100", "Name" => "piyo")

次にJulia言語でRequestをしてみたいと思います.

# ヘッダーの作成 
header = Dict("Content-Type" => "application/json;charset=UTF-8") 
# bodyの作成
body = Dict("Name" => "piyo", "Age" => "100") 
# POST 
HTTP.request("POST", "http://localhost:8080/api/v1/users", header  , body )

# クライアント側,サーバー側ともに正しくできている以下のように表示される
> HTTP.Messages.Response:
> """
> HTTP/1.1 200 OK
> Content-Type: text/html
> 
> <html><body>piyo</body></html>
> """

終わりに

Julia言語,HTTPの知識がなさすぎたり,エラーが出なかったりでかなり苦労しました.
ただ,これでJulia言語でのRequest,Responseはだいぶ詳しくなったかなと思います.

【募集中】僕と同じレベル感で勉強している方 or 僕にJulia言語を優しく教えてくれる方