yuzurss

Feed aggregator microservice based on Spring
git clone https://git.neuralcrash.com/yuzurss.git
Log | Files | Refs | README | LICENSE

commit af832aab4120e1f039f89fc92f9e277beb639b8e
parent 9472837f9a8925555d98228de068b6c8b353d0e4
Author: Kebigon <git@kebigon.xyz>
Date:   Sun, 20 Jan 2019 21:31:29 +0900

Handle empty feeds
Diffstat:
Msrc/main/java/fr/lrgn/yuzurss/parser/AtomFeedParser.java | 18+++++++++++-------
Msrc/main/java/fr/lrgn/yuzurss/parser/RDFFeedParser.java | 22+++++++++++++---------
Msrc/main/java/fr/lrgn/yuzurss/parser/RSSFeedParser.java | 19+++++++++++--------
Msrc/test/java/fr/lrgn/yuzurss/YuzuRssApplicationTests.java | 46++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 81 insertions(+), 24 deletions(-)

diff --git a/src/main/java/fr/lrgn/yuzurss/parser/AtomFeedParser.java b/src/main/java/fr/lrgn/yuzurss/parser/AtomFeedParser.java @@ -33,17 +33,21 @@ public class AtomFeedParser extends FeedParser public Flux<FeedEntry> parseFeed(JSONObject root) { Flux<FeedEntry> entries = Flux.empty(); + final JSONObject feed = root.optJSONObject("feed"); - for (final Object entry : root.getJSONObject("feed").getJSONArray("entry")) + if (feed != null) { - log.debug("Parsing entry {}", entry); + for (final Object entry : feed.getJSONArray("entry")) + { + log.debug("Parsing entry {}", entry); - final String author = ((JSONObject) entry).getJSONObject("author").getString("name"); - final String link = ((JSONObject) entry).getJSONObject("link").getString("href"); - final String title = ((JSONObject) entry).getString("title"); - final Date published = parseDate(((JSONObject) entry).getString("published")); + final String author = ((JSONObject) entry).getJSONObject("author").getString("name"); + final String link = ((JSONObject) entry).getJSONObject("link").getString("href"); + final String title = ((JSONObject) entry).getString("title"); + final Date published = parseDate(((JSONObject) entry).getString("published")); - entries = entries.mergeWith(Flux.just(new FeedEntry(title, link, published, author))); + entries = entries.mergeWith(Flux.just(new FeedEntry(title, link, published, author))); + } } return entries; diff --git a/src/main/java/fr/lrgn/yuzurss/parser/RDFFeedParser.java b/src/main/java/fr/lrgn/yuzurss/parser/RDFFeedParser.java @@ -33,19 +33,23 @@ public class RDFFeedParser extends FeedParser public Flux<FeedEntry> parseFeed(JSONObject root) { Flux<FeedEntry> entries = Flux.empty(); + final JSONObject document = root.getJSONObject("rdf:RDF"); - final JSONObject channel = root.getJSONObject("rdf:RDF").getJSONObject("channel"); - final String author = channel.getString("title"); - - for (final Object entry : root.getJSONObject("rdf:RDF").getJSONArray("item")) + if (document.has("item")) { - log.debug("Parsing entry {}", entry); + final JSONObject channel = document.getJSONObject("channel"); + final String author = channel.getString("title"); + + for (final Object entry : document.getJSONArray("item")) + { + log.debug("Parsing entry {}", entry); - final String link = ((JSONObject) entry).getString("link"); - final String title = ((JSONObject) entry).getString("title"); - final Date published = parseDate(((JSONObject) entry).getString("dc:date")); + final String link = ((JSONObject) entry).getString("link"); + final String title = ((JSONObject) entry).getString("title"); + final Date published = parseDate(((JSONObject) entry).getString("dc:date")); - entries = entries.mergeWith(Flux.just(new FeedEntry(title, link, published, author))); + entries = entries.mergeWith(Flux.just(new FeedEntry(title, link, published, author))); + } } return entries; diff --git a/src/main/java/fr/lrgn/yuzurss/parser/RSSFeedParser.java b/src/main/java/fr/lrgn/yuzurss/parser/RSSFeedParser.java @@ -34,19 +34,22 @@ public class RSSFeedParser extends FeedParser public Flux<FeedEntry> parseFeed(JSONObject root) { Flux<FeedEntry> entries = Flux.empty(); - final JSONObject channel = root.getJSONObject("rss").getJSONObject("channel"); - final String author = channel.getString("title"); - for (final Object entry : channel.getJSONArray("item")) + if (channel.has("item")) { - log.debug("Parsing entry {}", entry); + final String author = channel.getString("title"); + + for (final Object entry : channel.getJSONArray("item")) + { + log.debug("Parsing entry {}", entry); - final String link = ((JSONObject) entry).getString("link"); - final String title = ((JSONObject) entry).getString("title"); - final Date published = parseDate(((JSONObject) entry).getString("pubDate")); + final String link = ((JSONObject) entry).getString("link"); + final String title = ((JSONObject) entry).getString("title"); + final Date published = parseDate(((JSONObject) entry).getString("pubDate")); - entries = entries.mergeWith(Flux.just(new FeedEntry(title, link, published, author))); + entries = entries.mergeWith(Flux.just(new FeedEntry(title, link, published, author))); + } } return entries; diff --git a/src/test/java/fr/lrgn/yuzurss/YuzuRssApplicationTests.java b/src/test/java/fr/lrgn/yuzurss/YuzuRssApplicationTests.java @@ -29,11 +29,18 @@ public class YuzuRssApplicationTests private static final String RDF_RESPONSE = "<rdf:RDF><channel><title>rdf_feed</title></channel><item><link>rdf_link1</link><title>rdf_title1</title><dc:date>2019-01-06T14:18:00+09:00</dc:date></item><item><link>rdf_link2</link><title>rdf_title2</title><dc:date>2019-01-06T16:51:00+09:00</dc:date></item></rdf:RDF>"; private static final String ATOM_PATH = "/atom.xml"; private static final String ATOM_RESPONSE = "<feed><entry><author><name>atom_feed</name></author><link><href>atom_link1</href></link><title>atom_title1</title><published>2018-11-03T18:12:15+00:00</published></entry><entry><author><name>atom_feed</name></author><link><href>atom_link2</href></link><title>atom_title2</title><published>2018-10-30T18:12:15+00:00</published></entry></feed>"; + private static final String EMPTY_ATOM_PATH = "/empty_atom.xml"; + private static final String EMPTY_ATOM_RESPONSE = "<feed></feed>"; + private static final String EMPTY_RSS_PATH = "/empty_rss.xml"; + private static final String EMPTY_RSS_RESPONSE = "<rss><channel><title>rss_feed</title></channel></rss>"; + private static final String EMPTY_RDF_PATH = "/empty_rdf.xml"; + private static final String EMPTY_RDF_RESPONSE = "<rdf:RDF><channel><title>rdf_feed</title></channel></rdf:RDF>"; private static final String ATOM_RESULT = "[{\"title\":\"atom_title1\",\"link\":\"atom_link1\",\"published\":\"2018-11-03T18:12:15.000+0000\",\"author\":\"atom_feed\"},{\"title\":\"atom_title2\",\"link\":\"atom_link2\",\"published\":\"2018-10-30T18:12:15.000+0000\",\"author\":\"atom_feed\"}]"; private static final String RSS_RESULT = "[{\"title\":\"rss_title1\",\"link\":\"rss_link1\",\"published\":\"2018-12-09T09:22:00.000+0000\",\"author\":\"rss_feed\"},{\"title\":\"rss_title2\",\"link\":\"rss_link2\",\"published\":\"2018-10-19T21:49:54.000+0000\",\"author\":\"rss_feed\"}]"; private static final String RDF_RESULT = "[{\"title\":\"rdf_title2\",\"link\":\"rdf_link2\",\"published\":\"2019-01-06T07:51:00.000+0000\",\"author\":\"rdf_feed\"},{\"title\":\"rdf_title1\",\"link\":\"rdf_link1\",\"published\":\"2019-01-06T05:18:00.000+0000\",\"author\":\"rdf_feed\"}]"; private static final String ATOM_RSS_RESULT = "[{\"title\":\"rss_title1\",\"link\":\"rss_link1\",\"published\":\"2018-12-09T09:22:00.000+0000\",\"author\":\"rss_feed\"},{\"title\":\"atom_title1\",\"link\":\"atom_link1\",\"published\":\"2018-11-03T18:12:15.000+0000\",\"author\":\"atom_feed\"},{\"title\":\"atom_title2\",\"link\":\"atom_link2\",\"published\":\"2018-10-30T18:12:15.000+0000\",\"author\":\"atom_feed\"},{\"title\":\"rss_title2\",\"link\":\"rss_link2\",\"published\":\"2018-10-19T21:49:54.000+0000\",\"author\":\"rss_feed\"}]"; + private static final String EMPTY_FEED_RESULT = "[]"; @Autowired private WebTestClient webClient; @@ -57,6 +64,12 @@ public class YuzuRssApplicationTests return new MockResponse().setBody(RDF_RESPONSE); case ATOM_PATH: return new MockResponse().setBody(ATOM_RESPONSE); + case EMPTY_ATOM_PATH: + return new MockResponse().setBody(EMPTY_ATOM_RESPONSE); + case EMPTY_RSS_PATH: + return new MockResponse().setBody(EMPTY_RSS_RESPONSE); + case EMPTY_RDF_PATH: + return new MockResponse().setBody(EMPTY_RDF_RESPONSE); } return null; } @@ -119,4 +132,37 @@ public class YuzuRssApplicationTests webClient.post().uri("/feed").body(BodyInserters.fromObject(body)).exchange().expectStatus().isOk().expectBody(String.class) .isEqualTo(ATOM_RSS_RESULT); } + + @Test + public void testEmptyAtomFeed() throws UnsupportedEncodingException + { + final ArrayList<String> urls = new ArrayList<String>(); + urls.add("http://127.0.0.1:" + server.getPort() + EMPTY_ATOM_PATH); + final FeedRequestBody body = new FeedRequestBody(urls, 10); + + webClient.post().uri("/feed").body(BodyInserters.fromObject(body)).exchange().expectStatus().isOk().expectBody(String.class) + .isEqualTo(EMPTY_FEED_RESULT); + } + + @Test + public void testEmptyRSSFeed() throws UnsupportedEncodingException + { + final ArrayList<String> urls = new ArrayList<String>(); + urls.add("http://127.0.0.1:" + server.getPort() + EMPTY_RSS_PATH); + final FeedRequestBody body = new FeedRequestBody(urls, 10); + + webClient.post().uri("/feed").body(BodyInserters.fromObject(body)).exchange().expectStatus().isOk().expectBody(String.class) + .isEqualTo(EMPTY_FEED_RESULT); + } + + @Test + public void testEmptyRDFFeed() throws UnsupportedEncodingException + { + final ArrayList<String> urls = new ArrayList<String>(); + urls.add("http://127.0.0.1:" + server.getPort() + EMPTY_RDF_PATH); + final FeedRequestBody body = new FeedRequestBody(urls, 10); + + webClient.post().uri("/feed").body(BodyInserters.fromObject(body)).exchange().expectStatus().isOk().expectBody(String.class) + .isEqualTo(EMPTY_FEED_RESULT); + } }