リポジトリは zaneli-sandbox/rssss。
RSS の URL を入力してその場で内容を表示できるだけのもので、特に面白みもないが練習用という事で。
とりあえず、以下のRSSには対応できていそう。
-
- Qiita: http://qiita.com/tags/rust/feed.atom
はてなブログ: http://staff.hatenablog.com/rss, http://staff.hatenablog.com/feed
GitHub: https://github.com/zaneli-sandbox/rssss/commits/master.atom
medium: https://medium.com/feed/@medium
note: https://note.mu/info/rss
Tumblr: https://staff.tumblr.com/rss
YouTube: https://www.youtube.com/feeds/videos.xml?channel_id=UC4QobU6STFB0P71PMvOGN5A
ニコニコ動画: https://www.nicovideo.jp/newarrival?rss=2.0
私の個人ブログ: https://www.zaneli.com/blog/rss
使ったものは
-
- Rust
actix-web: Rust で Web アプリを書くならデファクトスタンダードかな、と思い。まだデファクトというほどのものが確立していないのかもしれないけれど。
xml-rs: XMLプルパーサ。serde_json のように from_str() とかで struct を作ってくれるようなやつが見つからなかったので面倒だったけど、各サービスによって微妙に要素名や構造が違っていたりしていたので取り回しが効いて良かったかもしれない。
scraper: RSSの の値はHTMLタグを含んでいるので、そこから雑にテキストだけを取り出すために使用。
Elm
Create Elm App: Elm はもとよりフロントエンド・js文化も不慣れだったので雰囲気で使って雰囲気で動かしているが助かっている。
CSS
Bulma: elm-bulmaというものもあり Elm 0.19 にも対応していたが、それは使わず直接 Bulma を使用した。フロントエンド力が低くてもそれなりの見栄えになってありがたい。
以下、作っていてハマった事などをつらつらと。
[Rust] future の型合わせ
レスポンスステータスによって、RSSをパースするか否かを分ける処理をこのように書こうとしていたが、
let status = res.status();
if status.is_success() {
res.body()
.from_err()
.and_then(|b| match rss::parse_rss(b) {
Ok(r) => Ok(HttpResponse::Ok().json(r)),
Err(e) => Ok(e.into()),
})
} else {
future::ok::<HttpResponse, Error>(
HttpResponse::build(res.status()).finish(),
)
}
返す型が futures::AndThen と futures::FutureResult で異なるためコンパイルエラーとなった。
このあたり、 Scala と同じような感覚で書こうとしていてなかなかコンパイルを通すのに苦戦した。
Boxでくるんで何とかコンパイルを通したが、これが正攻法なのかどうかがイマイチよく分かっていない。
Future に対する操作がそれぞれの型を返すのは、コンパイル時にサイズが決まっていないといけないとか、その辺の兼ね合いだろうか?
[Rust] エラーの型合わせ
以下の記事が参考になった。
-
- Rustのエラー処理
- rust のエラーライブラリは failure を使え!
…が、何とも面倒だなー、という印象が拭えない。
この辺は発展途上な部分なのかもしれないが。
[Rust] actix_web::client の使い勝手
30x を返す際にリダイレクトに対応していなかった。
reqwest とかを使えばもう少し楽になったのかもしれないが、今回は練習という事で自分でリダイレクトを解決する処理を書いてみた。
(余談だが、せいぜいリダイレクト1回のみに対応すればええやろと思っていたところ、http://qiita.com/tags/Docker/feed.atom には2回リダイレクトが必要だったため3回まで許容するようにした。)
また、Cargo.toml の dependencies に actix-web = { version=”0.7″, features=[“ssl”] } と指定しておかないと https リクエストが投げられなかったり。
この辺はまぁ、知ってしまえばそれまで系だが。
[Elm] ステータスコードによって Json Decoder を分けたい
200なら通常の型、40x系ならエラーメッセージ用の型、のように分けたかったが、
標準のexpectJsonは20x系しか扱えないようだった。
Twitterでも助言をもらい、Http.expectStringResponse を呼んで Http.BadStatus_, Http.GoodStatus_ を扱う処理を書く事で対処した。
[Elm] バージョン0.19未満の情報がヒットしたり、使えそうなライブラリが0.19対応してなかったり
悲しい。
…と、色々書いてはみたが、普段使わない言語で何か動くものを書いてみるのは凄く楽しかったし、書いてみて初めて躓く事も分かり良かった。
次は、DBアクセスしたり複数画面に渡る何かを作ってみようかな。
今回は Main.elm に全部押し込んだけど、ソースファイルの分け方もまだあまり分かっていない。
Rust や Elm の強い人の目に止まって、何かしら助言などいただけると幸いです。