Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
KtorでおうちAPIをリプレースした話
Search
yagi2
December 18, 2017
Programming
1
990
KtorでおうちAPIをリプレースした話
2017/12/18 CA.kt #5 @大阪 LT
yagi2
December 18, 2017
Tweet
Share
More Decks by yagi2
See All by yagi2
Kotlin DSLを理解してみる / Understanding Kotlin DSL
yagi2
4
2.3k
おうちにAPIを生やすお話.pdf
yagi2
0
440
略解 The Navigation Architecture Component
yagi2
1
200
10分で完全に(雰囲気を)理解するマテリアルデザイン
yagi2
1
400
Other Decks in Programming
See All in Programming
Android 15 でアクションバー表示時にステータスバーが白くなってしまう問題
tonionagauzzi
0
140
macOS でできる リアルタイム動画像処理
biacco42
7
1.9k
カスタムしながら理解するGraphQL Connection
yanagii
1
1.2k
役立つログに取り組もう
irof
26
8.7k
色々なIaCツールを実際に触って比較してみる
iriikeita
0
270
Generative AI Use Cases JP (略称:GenU)奮闘記
hideg
0
160
PLoP 2024: The evolution of the microservice architecture pattern language
cer
PRO
0
1.6k
シールドクラスをはじめよう / Getting Started with Sealed Classes
mackey0225
3
400
のびしろを広げる巻き込まれ力:偶然を活かすキャリアの作り方/oso2024
takahashiikki
1
410
Hotwire or React? ~Reactの録画機能をHotwireに置き換えて得られた知見~ / hotwire_or_react
harunatsujita
9
4.1k
WEBエンジニア向けAI活用入門
sutetotanuki
0
300
外部システム連携先が10を超えるシステムでのアーキテクチャ設計・実装事例
kiwasaki
1
230
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
167
14k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
14
1.9k
The Language of Interfaces
destraynor
154
24k
Visualization
eitanlees
144
15k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
26
1.4k
Adopting Sorbet at Scale
ufuk
73
9k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
126
18k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Designing Experiences People Love
moore
138
23k
How STYLIGHT went responsive
nonsquared
95
5.2k
The World Runs on Bad Software
bkeepers
PRO
65
11k
Keith and Marios Guide to Fast Websites
keithpitt
408
22k
Transcript
torͰ͓͏ͪAPI ɹΛϦϓϨʔεͨ͠ 2017/12/18 CA.kt #5 @େࡕ Itsuki AOYAGI
͍͋ͭ͝͞ - ࣗݾհ - • ໊લ : ੨༄ थ Itsuki
AOYAGIʢ23ʣ a.k.a ͗ʹ͍ • AndroidΞϓϦΤϯδχΞ • Kotlinྺ : • Twitter : @yaginier • GitHub etc… : @yagi2 / @yagi21 • ͓͏͍͖ͪͩ͢
͍͋ͭ͝͞ - ࣗݾհ - • ໊લ : ੨༄ थ Itsuki
AOYAGIʢ23ʣ a.k.a ͗ʹ͍ • AndroidΞϓϦΤϯδχΞ • Kotlinྺ : • Twitter : @yaginier • GitHub etc… : @yagi2 / @yagi21 • ͓͏͍͖ͪͩ͢
͓͏ͪϋοΫͯ͠·͔͢ʁ
͓͏ͪϋοΫ ͓͏ͪΛΑΓշదͳͷʹ͢ΔͨΊʹ ΨδΣοταʔϏεΛΈ߹Θͤͯ ϋοϐʔʹ͢ΔͨΊͷ͋Ε͜Ε ɻ ࠷ۙͩͱεϚʔτεϐʔΧʔ͕͍ͬͺ͍͋ΔͷͰ ͦΕΒܦ༝ͰՈిͱ͔Λૢ࡞Ͱ͖Δɻ
͓͏ͪϋοΫ - զ͕Ո - ɾRaspberry Piʢॳʣ ɹˠ ͓͏ͪAPI͕͍͑ͯΔʢPHPʣ ɹɹˠ ϒϥβ͔ΒHTTPSܦ༝ͯ͠ϖʔδ͔Βୟ͘
ɹɹˠ ࣗ࡞ͷAndroidΞϓϦ͔ΒϦΫΤετ Ұྫ ɾࣗͷσεΫτοϓPCͷిݯΛ֎͔ΒೖΕΔ ɾΤΞίϯɺςϨϏͷ֎ઢͰૢ࡞͢ΔՈిͷૢ࡞ ɾϥδΦʢRasPiΛrtmpετϦʔϛϯάͬͯϥδΦʹ͍ͯͨ͠ʣ
͓͏ͪϋοΫ - զ͕Ո - ɾRaspberry Piʢॳʣ ɹˠ ͓͏ͪAPI͕͍͑ͯΔʢPHPʣ ɹɹˠ ϒϥβ͔ΒHTTPSܦ༝ͯ͠ϖʔδ͔Βୟ͘
ɹɹˠ ࣗ࡞ͷAndroidΞϓϦ͔ΒϦΫΤετ Ұྫ ɾࣗͷσεΫτοϓPCͷిݯΛ֎͔ΒೖΕΔ ɾΤΞίϯɺςϨϏͷ֎ઢͰૢ࡞͢ΔՈిͷૢ࡞ ɾϥδΦʢRasPiΛrtmpετϦʔϛϯάͬͯϥδΦʹ͍ͯͨ͠ʣ
͓͏ͪϋοΫ - զ͕Ո - ɾRaspberry Piʢॳʣ ɹˠ ͓͏ͪAPI͕͍͑ͯΔʢPHPʣ ɹɹˠ ϒϥβ͔ΒHTTPSܦ༝ͯ͠ϖʔδ͔Βୟ͘
ɹɹˠ ࣗ࡞ͷAndroidΞϓϦ͔ΒϦΫΤετ Ұྫ ɾࣗͷσεΫτοϓPCͷిݯΛ֎͔ΒೖΕΔ ɾΤΞίϯɺςϨϏͷ֎ઢͰૢ࡞͢ΔՈిͷૢ࡞ ɾϥδΦʢRasPiΛrtmpετϦʔϛϯάͬͯϥδΦʹ͍ͯͨ͠ʣ ͍ͭ͜ΛKotlinʹॻ͖͑Δ
αʔόʔαΠυ Kotlin
αʔόʔαΠυKotlin ɾSpring Boot ɹҎલKotlin + Spring BootͰJSONΛు͘APIΛ࡞ͬͨ͜ͱ͕͋Δ ɹ ͦͷ࣌ͷϒϩά →
KotlinͱSpring BootΛͬͯαΫοͱୟ͚ΔAPIΛ࡞Δ ɾKotr ɹΊͬͪΌബ͍ ɹ ɹKtor is a framework for quickly creating web applications in Kotlin with minimal effort.
Ktor fun main(args: Array<String>) { embeddedServer(Netty, 8080) { routing {
get("/") { call.respondText("Hello, world!", ContentType.Text.Html) } } }.start(wait = true) } ɾബ͗ͯ͢README͕͍ ɹɹɹɹউखͳΠϝʔδ ɹɹɹɹɹɹɹSpringBoot → Ruby on Rails ɹɹɹɹɹɹɹKtor → Sinatra
Ktor - WoL API - KtorΛͬͯɺࣗPCͷిݯΛ֎͔ΒೖΕΔAPIΛॻ͖͢ ݱࡏͷ༷ ɾΫϥΠΞϯτPOSTͰରͷMacΞυϨεΛ͛Δ ɾαʔόʔड͚औͬͨΒͦͷMacΞυϨεʹରͯ͠WoL͢Δ ɹʢexecͰwakeonlanίϚϯυΛୟ͍͍ͯΔʣ
Ktor - WoL API - KtorΛͬͯɺࣗPCͷిݯΛ֎͔ΒೖΕΔAPIΛॻ͖͢ ৽͍༷͠ ɾΫϥΠΞϯτPOSTͰରͷϗετ໊Λ͛Δ ɹˠ ϗετ໊ͦΕʹ४ͣΔͷʢཧ༝ޙड़ʣΛ͛Δ
ɹˠ DBαʔόʔଆͰϗετ໊ͱMacΞυϨεΛ͓͍࣋ͬͯͯࢀর ɾαʔόʔड͚औͬͨΒରʹରͯ͠WoL͢Δ ɹ͔ͤͬ͘ͳͷͰϚδοΫύέοτૹ৴Λ࣮͢Δ
Ktor - WoL API - install(Routing) { post("/wol") { val
name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔ύϥϝʔλͰ ɹˠ DBʹExposed + MySQLΛ༻
Ktor - WoL API - install(Routing) { post("/wol") { val
name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔ύϥϝʔλͰ ɹˠ DBʹExposed + MySQLΛ༻
Ktor - WoL API - install(Routing) { post("/wol") { val
name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔ύϥϝʔλͰ ɹˠ DBʹExposed + MySQLΛ༻ object Computers : IntIdTable() { val hostName = varchar("hostname", 50).index() val macAddr = varchar("mac_addr", 50) } class Computer(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass<Computer>(Computers) var hostname by Computers.hostName var macAddr by Computers.macAddr } fun findByHostName(hostName: String?): Computer? { return transaction { Computer.find { Computers.hostName eq hostName }.firstOrNull() } }
Ktor - WoL API - install(Routing) { post("/wol") { val
name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔ύϥϝʔλͰ ɹˠ DBʹExposed + MySQLΛ༻
Ktor - WoL API - class WakeOnLan(private val macAddress: String)
{ @Throws(IOException::class) fun sendMagicPacket() { val iNetAddress = InetAddress.getByName("255.255.255.255") val magicPacket = getMagicPacket(macAddress) DatagramSocket().send(DatagramPacket(magicPacket, magicPacket.size, iNetAddress, 8080)) } private fun getMagicPacket(macAddress: String): ByteArray { val packet = ByteArray(102) var index = 0 repeat(6) { packet[index++] = 0xFF.toByte() } val macAddressByte = getMacAddressByte(macAddress) repeat(16) { repeat(6) { packet[index++] = macAddressByte[it] } } return packet } private fun getMacAddressByte(macAddress: String): ByteArray = macAddress.split(":").map { Integer.parseInt(it, 16).toByte() }.toByteArray() }
ʂ ͨ͠ͷͰɺGoogleHome͔Β͑ΔΑ͏ʹ͢Δ
Google Home + IFTTT Google HomeͷԻίϚϯυͰIFTTTͷτϦΨʔΛୟ͍ͯ IFTTTWebHookͰ͓ՈAPIʹPOST͢Δ
Google Home + IFTTT ී௨ʹϓϩάϥϜ͔ΒPOST͢Δͱ͖ $ curl --data-urlencode "name=hoge"
http://api.example.com/wol Google Homeͩͱ”name=hoge”͕ͭΒ͍ ɹˠ ຊޠͰͷΤΠϦΞεΛ͚ͯDBͷΧϥϜʹೖΕ͓ͯ͘ ྫʣʮͶ͐ɺGoogle ͏ͪͷ͜ͱΓΛىͯ͜͠ʯ ɹɹˠ name=͜ͱΓ ɹɹˠ DB͔Βʮ͜ͱΓʯͰҰக͢ΔͷΛݕࡧͯ͠Δ
Google Home + IFTTT object Computers : IntIdTable() { val
hostName = varchar("hostname", 50).index() val macAddr = varchar("mac_addr", 50) } class Computer(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass<Computer>(Computers) var hostname by Computers.hostName var macAddr by Computers.macAddr } fun findByHostName(hostName: String?): Computer? { return transaction { Computer.find { Computers.hostName eq hostName }.firstOrNull() } } object Computers : IntIdTable() { val hostName = varchar("hostname", 50).index() val name = varchar("name", 50) val macAddr = varchar("mac_addr", 50) } class Computer(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass<Computer>(Computers) var hostname by Computers.hostName var name by Computers.name var macAddr by Computers.macAddr } fun findByHostName(hostName: String?): Computer? { return transaction { Computer.find { Computers.hostName eq hostName }.firstOrNull() } } fun findByName(name: String?): Computer? { return transaction { Computer.find { Computers.name eq name }.firstOrNull() } }
Google Home + IFTTT transaction { Computer.new { hostname =
"kotori" name = "͜ͱΓ" macAddr = “FF:FF:FF:FF:FF:FF” } } ͓Ոʹ͋ΔϚγϯΛDBʹೖΕͯ͋͛Δɻ $ curl --data-urlencode "name=kotori" http://api.example.com:/wol ʮͶ͐ɺGoogle ͓͏ͪͷ͜ͱΓΛىͯ͜͠ʯ ✨྆ํڞOK✨
Google Home + IFTTT ҙ ʮͶ͐ɺGoogle ͏ͪͷ͜ͻͳͨΛىͯ͜͠ʯ → ͬͯ͘Δ໊લ͕ʮ͜ ͻͳ
ͨʯ ʮͶ͐ɺGoogle ͏ͪͷͪΌͪΌΛىͯ͜͠ʯ → ͬͯ͘Δ໊લ͕ʮʑʯ ղܾࡦ → 1ճࢼͯ͠Կ͕ͬͯ͘Δͷ͔ΛݟΔ
ຊͷ͓͠ͳ͕͖ ɾAPI ɹˠ https://github.com/yagi2/Kaya ɾKtor ɹˠ https://github.com/ktorio/ktor ɾExposed ɹˠ https://github.com/JetBrains/Exposed
Have a Nice Kotlin!