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
18
2025-09-22 Iceberg, Trinoでのログ基盤構築と パフォーマンス最適化
kamijin_fanta
1
900
2025-04-14 Data & Analytics 井戸端会議 Multi tenant log platform with Iceberg
kamijin_fanta
1
840
IoT向けストレージにTiKVを採用したときの話 / 2024-10-25 TiUG Meetup 3 Using TiKV as IoT storage
kamijin_fanta
0
210
TrinoとIcebergで ログ基盤の構築 / 2023-10-05 Trino Presto Meetup
kamijin_fanta
1
2.8k
Unicodeと符号化形式
kamijin_fanta
0
1.3k
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
推論基盤と Scale-Up Interconnect の現状と制約から俯瞰する技術動向
markunet
2
310
DevelopersIO2026 -バックアップは“消されないこと”が9割-
yoshida0129
0
410
VLA-JEPA: Enhancing Vision-Language-Action Models with Latent World Models
takmin
0
330
企画を Software Factory-ready にする——開発が高速になったとき、PdMの仕事はどう変わったか
yachibit
1
280
AIコーディングを実践してきた1年を振り返る / Looking Back on a Year of Practicing AI Coding
takedatakashi
1
140
Claude Code on Bedrock で統制をかける小ネタ集/claude-code-bedrock-governance-tips
emiki
1
13k
野良MCPサーバーを排除せよ!MCPサーバーのガバナンス
yukiogawa
1
240
CSS2026:OWS研究会・招待講演「世界観を、実装する」
atsush1_sada
2
340
AI時代、つくる力を自分たちの手に。 ──電通×KAG、アジャイルとAI駆動開発で挑む開発の変革
yuukiyo
3
390
Maestro MCPとClaude Code Skillsによる自律的なE2Eテスト支援
asmz
0
190
1週間、Opus封印でお願いします
kintotechdev
0
210
顧客価値を追いかけたら、プライシングにたどり着いた
sansantech
PRO
2
1k
Featured
See All Featured
Measuring & Analyzing Core Web Vitals
bluesmoon
9
1k
Producing Creativity
orderedlist
PRO
348
41k
Abbi's Birthday
coloredviolet
4
10k
Building an army of robots
kneath
307
47k
The browser strikes back
jonoalderson
0
1.9k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
860
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
420
ラッコキーワード サービス紹介資料
rakko
4
5.5M
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
Making the Leap to Tech Lead
cromwellryan
135
10k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
47k
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