|
|
|
@ -265,8 +265,14 @@ mod tests {
|
|
|
|
use wiremock::{Mock, MockServer, ResponseTemplate};
|
|
|
|
use wiremock::{Mock, MockServer, ResponseTemplate};
|
|
|
|
use wiremock::matchers::method;
|
|
|
|
use wiremock::matchers::method;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Set SKIP_SSRF_CHECK for tests using wiremock (localhost).
|
|
|
|
|
|
|
|
fn skip_ssrf_for_test() {
|
|
|
|
|
|
|
|
unsafe { std::env::set_var("SKIP_SSRF_CHECK", "1"); }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn parse_feed_rss2() {
|
|
|
|
async fn parse_feed_rss2() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let rss_body = r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
let rss_body = r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
<rss version="2.0">
|
|
|
|
<rss version="2.0">
|
|
|
|
@ -307,6 +313,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn parse_feed_atom() {
|
|
|
|
async fn parse_feed_atom() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let atom_body = r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
let atom_body = r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
|
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
|
|
@ -334,6 +341,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn parse_feed_respects_max_links() {
|
|
|
|
async fn parse_feed_respects_max_links() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let rss_body = r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
let rss_body = r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
<rss version="2.0">
|
|
|
|
<rss version="2.0">
|
|
|
|
@ -359,6 +367,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn parse_feed_entries_without_dates_come_last() {
|
|
|
|
async fn parse_feed_entries_without_dates_come_last() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let rss_body = r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
let rss_body = r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
<rss version="2.0">
|
|
|
|
<rss version="2.0">
|
|
|
|
@ -384,6 +393,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn parse_feed_404_returns_empty() {
|
|
|
|
async fn parse_feed_404_returns_empty() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
|
|
|
|
|
|
|
|
Mock::given(method("GET"))
|
|
|
|
Mock::given(method("GET"))
|
|
|
|
@ -398,6 +408,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn parse_feed_invalid_xml_returns_error() {
|
|
|
|
async fn parse_feed_invalid_xml_returns_error() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
|
|
|
|
|
|
|
|
Mock::given(method("GET"))
|
|
|
|
Mock::given(method("GET"))
|
|
|
|
@ -412,6 +423,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn discover_feed_from_link_rss() {
|
|
|
|
async fn discover_feed_from_link_rss() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let html = format!(
|
|
|
|
let html = format!(
|
|
|
|
r#"<html><head>
|
|
|
|
r#"<html><head>
|
|
|
|
@ -434,6 +446,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn discover_feed_from_link_atom() {
|
|
|
|
async fn discover_feed_from_link_atom() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let html = format!(
|
|
|
|
let html = format!(
|
|
|
|
r#"<html><head>
|
|
|
|
r#"<html><head>
|
|
|
|
@ -456,6 +469,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn discover_feed_direct_rss_url() {
|
|
|
|
async fn discover_feed_direct_rss_url() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let rss_body = r#"<?xml version="1.0"?><rss version="2.0"><channel><title>T</title></channel></rss>"#;
|
|
|
|
let rss_body = r#"<?xml version="1.0"?><rss version="2.0"><channel><title>T</title></channel></rss>"#;
|
|
|
|
|
|
|
|
|
|
|
|
@ -476,6 +490,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn discover_feed_no_feed_found() {
|
|
|
|
async fn discover_feed_no_feed_found() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let html = "<html><head><title>No feed</title></head><body></body></html>";
|
|
|
|
let html = "<html><head><title>No feed</title></head><body></body></html>";
|
|
|
|
|
|
|
|
|
|
|
|
@ -492,6 +507,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn discover_feed_resolves_relative_href() {
|
|
|
|
async fn discover_feed_resolves_relative_href() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let html = r#"<html><head>
|
|
|
|
let html = r#"<html><head>
|
|
|
|
<link rel="alternate" type="application/rss+xml" href="/feed.xml">
|
|
|
|
<link rel="alternate" type="application/rss+xml" href="/feed.xml">
|
|
|
|
@ -513,6 +529,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn detect_and_parse_cached_fresh_feed() {
|
|
|
|
async fn detect_and_parse_cached_fresh_feed() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let rss_body = r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
let rss_body = r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
<rss version="2.0"><channel><title>T</title>
|
|
|
|
<rss version="2.0"><channel><title>T</title>
|
|
|
|
@ -543,6 +560,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn detect_and_parse_no_cache_discovers_feed() {
|
|
|
|
async fn detect_and_parse_no_cache_discovers_feed() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
|
|
|
|
|
|
|
|
// First request: HTML page with feed link
|
|
|
|
// First request: HTML page with feed link
|
|
|
|
@ -595,6 +613,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn detect_and_parse_no_feed_returns_not_found() {
|
|
|
|
async fn detect_and_parse_no_feed_returns_not_found() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let html = "<html><head><title>No feed</title></head><body></body></html>";
|
|
|
|
let html = "<html><head><title>No feed</title></head><body></body></html>";
|
|
|
|
|
|
|
|
|
|
|
|
@ -617,6 +636,7 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn detect_and_parse_stale_cache_rediscovers() {
|
|
|
|
async fn detect_and_parse_stale_cache_rediscovers() {
|
|
|
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
let server = MockServer::start().await;
|
|
|
|
|
|
|
|
|
|
|
|
let feed_path = format!("{}/feed.xml", server.uri());
|
|
|
|
let feed_path = format!("{}/feed.xml", server.uri());
|
|
|
|
|