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
16
2025-09-22 Iceberg, Trinoでのログ基盤構築と パフォーマンス最適化
kamijin_fanta
1
890
2025-04-14 Data & Analytics 井戸端会議 Multi tenant log platform with Iceberg
kamijin_fanta
1
830
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.8k
Unicodeと符号化形式
kamijin_fanta
0
1.2k
Reactとフォームとスキーマバリデーション / React forms with Schema Validation
kamijin_fanta
0
2.8k
2020/05/25 さくらのクラウド向けツールを使いこなす
kamijin_fanta
3
390
2019-01-24 業務でのOSSとの関わり方
kamijin_fanta
7
5.1k
Other Decks in Technology
See All in Technology
プロダクト価値を、 チームが使える判断軸に変える
vivion
0
110
2026-10-01_MagicPod_QAハーネスエンジニアリングとQA組織の未来像
ynisqa1988
1
530
[2026-09-30]ロックンロールは鳴り止まないっ - 信頼性かまってちゃん - 「データ駆動を投げ捨ててまで。」追いかける信頼性改善に向けた取り組みの話
tosite
0
200
Codex概要
ymiya55
0
410
AIは爆速なのに、私が詰まっていた話 ― 音声入力と鳴くマスコットでボトルネックを削る
yama3133
0
520
FinTech 1-2 : Overview of FinTech
ks91
PRO
0
150
AIに攻撃される前に、AIに攻撃させる
tsuchikazu
0
150
転んだ話が背中を預ける理由になる / A_story_about_falling_down_gives_you_a_reason_to_watch_each_other_s_backs.pdf
pauli
3
230
SREでアラート疲れを 解決しよう!
kairim0
1
200
サーバーフルコンピューティング?AWS Lambda
iwatatomoya
1
250
AI 時代の Azure エンジニアリング ~ 私たちは何を磨き、何を任せるのか ~
chack411
1
470
組み立てて楽しむ AWS Blocks 入門
kmiya84377
0
210
Featured
See All Featured
The Language of Interfaces
destraynor
162
27k
Why Our Code Smells
bkeepers
PRO
340
58k
The Spectacular Lies of Maps
axbom
PRO
1
1.1k
Building Adaptive Systems
keathley
44
3.2k
Technical Leadership for Architectural Decision Making
baasie
3
590
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
440
What does AI have to do with Human Rights?
axbom
PRO
1
2.4k
Context Engineering - Making Every Token Count
addyosmani
9
1.2k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
920
Music & Morning Musume
bryan
48
7.4k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
530
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
360
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