Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
2018-11-10 Akka-HTTPで作るAPIサーバ
Search
kamijin_fanta
November 10, 2018
Technology
4.2k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
2018-11-10 Akka-HTTPで作るAPIサーバ
https://github.com/kamijin-fanta/slide/tree/master/2018-11-10%20ScalaKansai-AkkaHTTP
kamijin_fanta
November 10, 2018
More Decks by kamijin_fanta
See All by kamijin_fanta
2026-06-11 Iceberg Trinoログ基盤の 設計ポイント - Design Points for an Iceberg + Trino Log Platform
kamijin_fanta
0
15
2025-09-22 Iceberg, Trinoでのログ基盤構築と パフォーマンス最適化
kamijin_fanta
1
890
2025-04-14 Data & Analytics 井戸端会議 Multi tenant log platform with Iceberg
kamijin_fanta
1
810
IoT向けストレージにTiKVを採用したときの話 / 2024-10-25 TiUG Meetup 3 Using TiKV as IoT storage
kamijin_fanta
0
200
TrinoとIcebergで ログ基盤の構築 / 2023-10-05 Trino Presto Meetup
kamijin_fanta
1
2.7k
Unicodeと符号化形式
kamijin_fanta
0
1.2k
Reactとフォームとスキーマバリデーション / React forms with Schema Validation
kamijin_fanta
0
2.8k
2020/05/25 さくらのクラウド向けツールを使いこなす
kamijin_fanta
3
380
2019-01-24 業務でのOSSとの関わり方
kamijin_fanta
7
5.1k
Other Decks in Technology
See All in Technology
The Agent Builder Loop from Daily Work to OSS
minorun365
PRO
3
200
What the customer really needed
kawaguti
PRO
2
180
積み重なった技術負債への挑戦 〜初手としての全社ゴト化〜
techtekt
PRO
0
1.2k
10分で知る最近のOmarchy
komagata
0
340
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
5
25k
データ界隈LT祭 第1回LT登壇
taromatsui_cccmkhd
1
1.4k
20260912_スクフェス三河
kgnkhkr
0
380
LTのテーマ どうきめてる?〜5つの型と私のやり方〜
yama3133
1
110
Claude in Chrome 入門 / Introduction to Claude in Chrome
cielo1985
0
820
株式会社シーエーシー エンジニア向け会社紹介資料
cac
0
57k
生成AIエージェントを用いた、 手動テスト手順書から自動テストへの 変換手法の検討
magicpod
0
160
Railsのように考える: See through the Master
snoozer05
PRO
3
890
Featured
See All Featured
BBQ
matthewcrist
89
10k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
Prompt Engineering for Job Search
mfonobong
0
450
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
200
Build your cross-platform service in a week with App Engine
jlugia
234
19k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.1k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
Designing for Performance
lara
611
70k
Into the Great Unknown - MozCon
thekraken
41
2.7k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
Transcript
Akka‑HTTPで作るAPIサーバ 2018‑11‑10 Scala Kansai Summit ‑ kamijin‑fanta
諸注意 スライド公開します 撮影NG (イベントのレギュレーション) Twitter: #scala̲ks #s1 2
自己紹介 Scala関西Summit運営 Github: kamijin‑fanta Twitter: kamijin̲fanta 3
Akka HTTP HTTP Server HTMLテンプレート・フォーム等を使用したWebサイト クライアント・バックエンドが分離したAPIサーバ HTTP Client スクレイピング マイクロサービスの他のエンドポイントの呼び出し
HTTP Serverについて主に紹介 4
Akka HTTP is... Webフレームワーク 例 Play, Rails, Django, Laravel 機能
ルーティング・テンプレート・データベース・セッション・認証・テスト 5
Akka HTTP is HTTP Library Akka HTTPはWebフレームワークではない 有: ルーティング・テスト 無:
テンプレート・データベース・セッション・認証 6
Why Akka HTTP 何故機能の少ないAkka HTTPを選択するのか Webフレームワークが適切でないユースケースが存在 大きなビジネスロジックが存在し、APIが付加的なものである RDB(MySQL等)ではなくKVS(Dynamo等)を使用する 認証に独自のSSOを使用する 気に入ったライブラリ(twirl,
circe等)を使用したい フレームワークのアップグレードコストが無視できない プログラミングの考え方 他のWebフレームワーク: HTTPのサービスを記述する Akka HTTP: アプリケーションを記述し、HTTPと統合する 7
Beginner friendly Akka HTTPは2つの側面が有る 大規模サービス構築に向く DB・セッション管理なども1から作れる クリーンアーキテクチャ等の設計手法と親和性が高い 単機能なので破壊的変更が少なく、アップグレードコストが低い 単機能で覚える機能が少ない Scalaの習得後のステップで扱うのに適している
8
Recommended for... こんな人におすすめ フレームワークが負担になってきた アップグレード・独自の認証・スケーリング シンプルな機能の組み合わせでHTTPサーバを作りたい 単機能なディレクティブを組み合わせる Scalaの言語をある程度覚え、何を作ろうか迷っている ライブラリ特有の機能等の覚えるべきことが少ない 9
Understand code 10
Install Requirement sbt JDK // build.sbt libraryDependencies ++= Seq( "com.typesafe.akka"
%% "akka‐http" % "10.1.5", "com.typesafe.akka" %% "akka‐stream" % "2.5.12", ) 11
Basic Server object HttpServerUseHttpApp { object WebServer extends HttpApp {
override def routes: Route = path("hello") { get { val entity = HttpEntity( ContentTypes.`text/html(UTF‐8)`, "<h1>hello akka‐http</h1>" ) complete(entity) } } } def main(args: Array[String]): Unit = WebServer.startServer("localhost", 8080) } 12
$ sbt > run $ curl localhost:8080/hello <h1>hello akka‐http</h1> 13
Model, Types リクエスト・レスポンスに対応する型が定義されている Request, Response, Uri, Header(Accept, Cookie) etc... Scalaのパターンマッチングを行うことができる
例:Reqに含まれるAcceptヘッダからUEで許可されているMIMEタイプを抽出 多数の型が定義されているので、一部だけ紹介 14
Methods HttpMethods.CONNECT HttpMethods.DELETE HttpMethods.GET HttpMethods.HEAD HttpMethods.OPTIONS HttpMethods.PATCH HttpMethods.POST HttpMethods.PUT HttpMethods.TRACE
15
Uri / Query assert( Uri("https://akka.io:443/try‐akka/") === Uri.from(scheme = "https", host
= "akka.io", port = 443, path = "/try‐akka/") ) assert(Query("key1=value1&key2=Foo&key2=Bar").get("key1") === Some("value1")) assert(Query("key=Foo&key=Bar").getAll("key") === List("Bar", "Foo")) 16
Headers RawHeader("x‐custom‐header", "value") headers.Host("example.com") headers.`Access‐Control‐Allow‐Origin`(HttpOrigin("https://example.com")) 17
Routing DSL object RoutingBasic extends HttpApp { def main(args: Array[String]):
Unit = startServer("localhost", 8080) override def routes: Route = pathPrefix("hello") { get { complete("get hello") } ~ post { complete("post hello") } } ~ ((get | post) & path("user" / Segment)) { userName => complete(s"UserName: $userName") } } Directive(pathPrefix, get, post, complete, path)を組み合わせてRouteを作る 入れ子にすることや、 ~ & | で連結することが出来る 18
What is Directive? // 1. 内部のルートに委譲または、拒否しフィルタリングを行う filter(args...) { ??? }
// 2. 値を抽出し、内部のルートに渡す extract(args...) { variable => ??? } // 3. コンテンツを返す complate(???) 2つ以上の性質を組み合わせたディレクティブも存在 19
Composing Route override def routes: Route = pathPrefix("hello") { get
{ complete("get hello") } ~ post { complete("post hello") } } ~ ((get | post) & path("user" / Segment)) { userName => complete(s"UserName: $userName") } ~ : ルートで拒否されたときに、次のRouteへ処理を移す & : 両方のディレクティブの条件を満たす必要がある | : どちらかのディレクティブの条件を満たす必要がある 20
val getOrPostUser = (get | post) & path("user" / Segment)
override def routes: Route = pathPrefix("hello") { get { complete("get hello") } ~ post { complete("post hello") } } ~ getOrPostUser { userName => complete(s"UserName: $userName") } 21
Test Kit libraryDependencies ++= Seq( "com.typesafe.akka" %% "akka‐http‐testkit" % "10.1.3"
% Test, "org.scalatest" %% "scalatest" % "3.0.5" % Test ) class SimpleHttpServerSpec extends FunSpec with ScalatestRouteTest { it("basic test") { val route = path("hello") & get { complete(HttpEntity(ContentTypes.`text/html(UTF‐8)`, "<h1>Say hello to akka‐http</h1>")) } Get("/hello") ~> route ~> check { assert(status === StatusCodes.OK) assert(responseAs[String] === "<h1>Say hello to akka‐http</h1>") assert(contentType === ContentTypes.`text/html(UTF‐8)`) } } } 22
Get("/hello") はHttpRequestを作るためのショートハンド Get Post Put Patch Delete Options Head もある
object HttpRequest { def apply( method: HttpMethod = HttpMethods.GET, uri: Uri = Uri./, headers: immutable.Seq[HttpHeader] = Nil, entity: RequestEntity = HttpEntity.Empty, protocol: HttpProtocol = HttpProtocols.`HTTP/1.1`) = new HttpRequest(method, } 23
Easy to test DirectiveはRequestから値の抽出・フィルタリングを行う純粋関数→テストしやすい 任意のHttpRequestをRouteに投げた結果を検証する仕組みがTestKitで用意されている 簡易なテストを楽に書くためのショートハンドも存在 24
Rejection override def routes: Route = path("hello") { get {
complete("get hello") } ~ post { complete("post hello") } } $ curl ‐X DELETE localhost:8080/hello HTTP method not allowed, supported methods: GET, POST 適切なエラーをクライアントに返すための仕組み 25
Provide Rejections override def routes: Route = path("foo") { reject
} ~ path("bar") { reject(MissingQueryParamRejection("rejection reason")) } final case class MissingQueryParamRejection(parameterName: String) extends jserver.MissingQueryParamRejection with Rejection trait Rejection $ curl localhost:8080/bar Request is missing required query parameter 'rejection reason' 26
Handle Rejection 標準ではデフォルトのRejectionHandlerが使用されている 上書きor拡張することで、カスタムのエラーメッセージを返すことが可能 Route.seal でラップし、implicit valを注入する 27
implicit def myRejectionHandler: RejectionHandler = // point 1 RejectionHandler.newBuilder() .handle
{ case reject: MissingQueryParamRejection => complete( StatusCodes.BadRequest, s"required query parameter [${reject.parameterName}]") }.result() override def routes: Route = Route.seal(internalRoutes) // point 2 def internalRoutes: Route = path("bar") { reject(MissingQueryParamRejection("rejection reason")) } final case class MissingQueryParamRejection(parameterName: String) extends jserver.MissingQueryParamRejection with Rejection 28
エラーを型を使って表現することが出来る RejectionHandlerで、エラーメッセージを容易にカスタマイズ可能 JSON/HTML/XMLでのエラー対応等 29
Marshall Marshal オブジェクトをシリアライズする仕組み 文字列・バイト列などに変換するMarshallerを定義する 30
import io.circe.generic.auto._ import io.circe.syntax._ case class User(name: String, age: Int)
implicit val userMarshaller: ToEntityMarshaller[User] = Marshaller.opaque { user => HttpEntity(ContentTypes.`application/json`, user.asJson.noSpaces) } val route: Route = get { complete(User("mika", 20)) } Get("/") ~> route ~> check { assert(contentType === ContentTypes.`application/json`) assert(responseAs[String] === """{"name":"mika","age":20}""") } 31
Examples https://github.com/kamijin‑fanta/akka‑http‑ 2018/tree/master/src/main/scala/examples https://github.com/kamijin‑fanta/akka‑http‑ 2018/tree/master/src/test/scala/examples 32
Summary Route DSL Model Directive Rejection Marshall Test Kit Akka
HTTPはこれらのパーツを組み合わせ、 シンプルなHTTPサーバ構築をサポートするライブラリ 33
https://kinyoubenkyokai.github.io/book/techbook05/ 34
ありがとうございました Akka-HTTP で作るAPI サーバ 2018‑11‑10 Scala Kansai Summit ‑ kamijin‑fanta
35