DEV Community

Weerasak Chongnguluam
Weerasak Chongnguluam

Posted on

แงะ ex_aws_s3 ไลบรารี่สำหรับใช้งาน AWS S3 ผ่าน Elixir ว่ามันได้ response แบบไหนกันแน่

งานที่ทำต้องการ upload file ขึ้น service ที่ compatible กับ AWS S3 เลยเลือกใช้ library ex_aws ช่วยในการเรียกใช้ S3 API ในการอัพโหลดไฟล์ ซึ่งต้องใช้งานร่วมกับ library ex_aws_s3

สิ่งที่ทำให้ต้องมาเขียนโพสต์นี้ก็เพราะว่า document ของ library นี้มันไม่เคลียร์ว่า response ที่มันตอบกลับมานั้นจะอยู่ในรูปแบบไหนกันแน่ เช่นต้องการอัพโหลดไฟล์ในตัวอย่างเขียนไว้แค่นี้

"path/to/big/file"
|> ExAws.S3.Upload.stream_file
|> ExAws.S3.upload("my-bucket", "path/on/s3")
|> ExAws.request #=> {:ok, :done}
Enter fullscreen mode Exit fullscreen mode

กับ get_object เขียนไว้แค่นี้

ExAws.S3.get_object("my-bucket", "image.png") |> ExAws.request
Enter fullscreen mode Exit fullscreen mode

แต่จริงๆแล้วตอน upload จะได้ reponse แบบนี้

{:ok,
 %{
   body: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CompleteMultipartUploadResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Location>http://localhost:9000/my-bucket/mix.exs</Location><Bucket>my-bucket</Bucket><Key>mix.exs</Key><ETag>&#34;5ca9425fced3f0bc1670a8f1fccbe29d-1&#34;</ETag></CompleteMultipartUploadResult>",
   headers: [
     {"Accept-Ranges", "bytes"},
     {"Cache-Control", "no-cache"},
     {"Content-Length", "311"},
     {"Content-Security-Policy", "block-all-mixed-content"},
     {"Content-Type", "application/xml"},
     {"ETag", "\"5ca9425fced3f0bc1670a8f1fccbe29d-1\""},
     {"Server", "MinIO"},
     {"Vary", "Origin"},
     {"X-Accel-Buffering", "no"},
     {"X-Amz-Request-Id", "166840A0DBB74310"},
     {"X-Xss-Protection", "1; mode=block"},
     {"Date", "Mon, 01 Mar 2021 15:12:06 GMT"}
   ],
   status_code: 200
 }}
Enter fullscreen mode Exit fullscreen mode

แต่จริงๆแล้วตอน get_object จะได้ reponse แบบนี้

{:ok,
 %{
   body: "defmodule S3Example.MixProject do\n  use Mix.Project\n\n  def project do\n    [\n      app: :s3_example,\n      version: \"0.1.0\",\n      elixir: \"~> 1.11\",\n      start_permanent: Mix.env() == :prod,\n      deps: deps()\n    ]\n  end\n\n  # Run \"mix help compile.app\" to learn about applications.\n  def application do\n    [\n      extra_applications: [:logger]\n    ]\n  end\n\n  # Run \"mix help deps\" to learn about dependencies.\n  defp deps do\n    [\n      {:ex_aws, \"~> 2.1\"},\n      {:ex_aws_s3, \"~> 2.1\"},\n      {:hackney, \"~> 1.9\"},\n      {:jason, \"~> 1.2\"},\n      {:sweet_xml, \"~> 0.6\"}\n      # {:dep_from_hexpm, \"~> 0.3.0\"},\n      # {:dep_from_git, git: \"https://github.com/elixir-lang/my_dep.git\", tag: \"0.1.0\"}\n    ]\n  end\nend\n",
   headers: [
     {"Accept-Ranges", "bytes"},
     {"Content-Length", "717"},
     {"Content-Security-Policy", "block-all-mixed-content"},
     {"Content-Type", "application/octet-stream"},
     {"ETag", "\"5ca9425fced3f0bc1670a8f1fccbe29d-1\""},
     {"Last-Modified", "Mon, 01 Mar 2021 15:12:06 GMT"},
     {"Server", "MinIO"},
     {"Vary", "Origin"},
     {"X-Amz-Request-Id", "166840A6DA0B6B08"},
     {"X-Xss-Protection", "1; mode=block"},
     {"Date", "Mon, 01 Mar 2021 15:12:31 GMT"}
   ],
   status_code: 200
 }}
Enter fullscreen mode Exit fullscreen mode

จะเห็นว่าก็เป็น pattern {:ok, %{body: , headers: [], status_code: }}

ด้วยความสงสัยเลยไปแงะโค้ดดูพบว่า concept ของมันคือให้สร้าง Operation struct เพื่อเก็บขอมูลของ Request แล้วให้ implement protocol ExAws.Operation ที่มี function perform กับ stream!

เสร็จแล้วเมื่อเราส่งต่อค่าของ operation ไปให้ฟังก์ชัน ExAws.request มันจะเรียก perform ให้นั่นเอง ซึ่งพอไปดูโค้ดของ ExAws.request จะเห็นโค้ดแบบนี้

ExAws.Operation.perform(op, ExAws.Config.new(op.service, config_overrides))
Enter fullscreen mode Exit fullscreen mode

สรุปว่า จริงๆแล้วเวลาเห็นโค้ดแบบด้านบน เราต้องดูว่ามันสร้างค่าของ Operation struct ตัวไหนก่อนจะเรียกไปหา ExAws.request แล้วก็ไปดู perform ของมันว่าทำอะไรแล้วได้อะไรกลับออกมา เช่น ExAws.S3.upload นั้นได้ operation ExAws.S3.Upload ก็ต้องไปไล่ๆหาในฟังก์ชัน perform ของ operation Upload นั่นเอง

จะเห็นว่าตัว document ของ ex_aws กับ ex_aws_s3 ยังปรับปรุงได้อีกเพื่อให้คนที่ต้องใช้งานเข้าใจได้ง่ายขึ้นว่าจะได้ response แบบไหนออกมา เดี๋ยวว่างๆวันหยุดจะลองไปช่วย contribute ดู

ขอฝาก Buy Me a Coffee

สำหรับท่านใดที่อ่านแล้วชอบโพสต์ต่างๆของผมที่นี่ ต้องการสนับสนุนค่ากาแฟเล็กๆน้อยๆ สามารถสนับสนุนผมได้ผ่านทาง Buy Me a Coffee คลิ๊กที่รูปด้านล่างนี้ได้เลยครับ

Buy Me A Coffee

ส่วนท่านใดไม่สะดวกใช้บัตรเครดิต หรือ Paypal สามารถสนับสนุนผมได้ผ่านทาง PromptPay โดยดู QR Code ได้จากโพสต์ที่พินเอาไว้ได้ที่ Page DevDose ครับ https://web.facebook.com/devdoseth

ขอบคุณครับ 🙏

Latest comments (0)