Drop RSS/Atom feeds, support JSON feeds only
Removes the RSS and Atom feed routes, controller methods, and views for both the blog and notes feeds, keeping JSON (and JF2) as the only supported feed formats. Also serves the JSON feeds with the spec-required application/feed+json MIME type instead of the generic application/json. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AXyzNvQZPQgBoSZwW7cLG8
This commit is contained in:
parent
6a0bb623fc
commit
714cd95d79
8 changed files with 12 additions and 209 deletions
|
|
@ -7,66 +7,13 @@ namespace App\Http\Controllers;
|
|||
use App\Models\Article;
|
||||
use App\Models\Note;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class FeedsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns the blog RSS feed.
|
||||
*/
|
||||
public function blogRss(): Response
|
||||
{
|
||||
$articles = Article::where('published', '1')->latest('updated_at')->take(20)->get();
|
||||
$buildDate = $articles->first()->updated_at->toRssString();
|
||||
|
||||
return response()
|
||||
->view('articles.rss', compact('articles', 'buildDate'))
|
||||
->header('Content-Type', 'application/rss+xml; charset=utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blog Atom feed.
|
||||
*/
|
||||
public function blogAtom(): Response
|
||||
{
|
||||
$articles = Article::where('published', '1')->latest('updated_at')->take(20)->get();
|
||||
|
||||
return response()
|
||||
->view('articles.atom', compact('articles'))
|
||||
->header('Content-Type', 'application/atom+xml; charset=utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the notes RSS feed.
|
||||
*/
|
||||
public function notesRss(): Response
|
||||
{
|
||||
$notes = Note::latest()->take(20)->get();
|
||||
$buildDate = $notes->first()->updated_at->toRssString();
|
||||
|
||||
return response()
|
||||
->view('notes.rss', compact('notes', 'buildDate'))
|
||||
->header('Content-Type', 'application/rss+xml; charset=utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the notes Atom feed.
|
||||
*/
|
||||
public function notesAtom(): Response
|
||||
{
|
||||
$notes = Note::latest()->take(20)->get();
|
||||
|
||||
return response()
|
||||
->view('notes.atom', compact('notes'))
|
||||
->header('Content-Type', 'application/atom+xml; charset=utf-8');
|
||||
}
|
||||
|
||||
/** @todo sort out return type for json responses */
|
||||
|
||||
/**
|
||||
* Returns the blog JSON feed.
|
||||
*/
|
||||
public function blogJson(): array
|
||||
public function blogJson(): JsonResponse
|
||||
{
|
||||
$articles = Article::where('published', '1')->latest('updated_at')->take(20)->get();
|
||||
$data = [
|
||||
|
|
@ -94,13 +41,15 @@ class FeedsController extends Controller
|
|||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
return response()->json($data, 200, [
|
||||
'Content-Type' => 'application/feed+json',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the notes JSON feed.
|
||||
*/
|
||||
public function notesJson(): array
|
||||
public function notesJson(): JsonResponse
|
||||
{
|
||||
$notes = Note::latest()->with('media', 'place', 'tags')->take(20)->get();
|
||||
$data = [
|
||||
|
|
@ -130,7 +79,9 @@ class FeedsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
return response()->json($data, 200, [
|
||||
'Content-Type' => 'application/feed+json',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>Atom feed for {{ config('user.display_name') }}’s blog</title>
|
||||
<link rel="self" href="{{ config('app.url') }}/blog/feed.atom" />
|
||||
<id>{{ config('app.url')}}/blog</id>
|
||||
<updated>{{ $articles[0]->updated_at->toAtomString() }}</updated>
|
||||
|
||||
@foreach($articles as $article)
|
||||
<entry>
|
||||
<title>{{ $article->title }}</title>
|
||||
<link href="{{ config('app.url') }}{{ $article->link }}" />
|
||||
<id>{{ config('app.url') }}{{ $article->link }}</id>
|
||||
<updated>{{ $article->updated_at->toAtomString() }}</updated>
|
||||
<content>{{ $article->main }}</content>
|
||||
<author>
|
||||
<name>{{ config('user.display_name') }}</name>
|
||||
</author>
|
||||
</entry>
|
||||
@endforeach
|
||||
</feed>
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>{{ config('user.display_name') }}</title>
|
||||
<atom:link href="{{ config('app.url') }}/blog/feed.rss" rel="self" type="application/rss+xml" />
|
||||
<description>An RSS feed of the blog posts found on {{ config('app.url') }}</description>
|
||||
<link>{{ config('app.url') }}/blog</link>
|
||||
<lastBuildDate>{{ $buildDate }}</lastBuildDate>
|
||||
<ttl>1800</ttl>
|
||||
|
||||
@foreach($articles as $article)
|
||||
<item>
|
||||
<title>{{ strip_tags($article->title) }}</title>
|
||||
<description>
|
||||
<![CDATA[
|
||||
{{ $article->main }}
|
||||
@if($article->url)<p><a href="{{ config('app.url') }}{{ $article->link }}">Permalink</a></p>@endif
|
||||
]]>
|
||||
</description>
|
||||
<link>@if($article->url != ''){{ $article->url }}@else{{ config('app.url') }}{{ $article->link }}@endif</link>
|
||||
<guid>{{ config('app.url') }}{{ $article->link }}</guid>
|
||||
<pubDate>{{ $article->pubdate }}</pubDate>
|
||||
</item>
|
||||
@endforeach
|
||||
</channel>
|
||||
</rss>
|
||||
|
|
@ -7,13 +7,9 @@
|
|||
<title>@yield('title'){{ config('app.name') }}</title>
|
||||
<link rel="stylesheet" href="/assets/highlight/nord.css">
|
||||
<link rel="stylesheet" href="/assets/css/app.css">
|
||||
<link rel="alternate" type="application/rss+xml" title="Blog RSS Feed" href="{{ route('feed.blog.rss') }}">
|
||||
<link rel="alternate" type="application/atom+xml" title="Blog Atom Feed" href="{{ route('feed.blog.atom') }}">
|
||||
<link rel="alternate" type="application/json" title="Blog JSON Feed" href="{{ route('feed.blog.json') }}">
|
||||
<link rel="alternate" type="application/feed+json" title="Blog JSON Feed" href="{{ route('feed.blog.json') }}">
|
||||
<link rel="alternate" type="application/jf2feed+json" title="Blog JF2 Feed" href="{{ route('feed.blog.jf2') }}">
|
||||
<link rel="alternate" type="application/rss+xml" title="Notes RSS Feed" href="{{ route('feed.notes.rss') }}">
|
||||
<link rel="alternate" type="application/atom+xml" title="Notes Atom Feed" href="{{ route('feed.notes.atom') }}">
|
||||
<link rel="alternate" type="application/json" title="Notes JSON Feed" href="{{ route('feed.notes.json') }}">
|
||||
<link rel="alternate" type="application/feed+json" title="Notes JSON Feed" href="{{ route('feed.notes.json') }}">
|
||||
<link rel="alternate" type="application/jf2feed+json" title="Notes JF2 Feed" href="{{ route('feed.notes.jf2') }}">
|
||||
<link rel="indieauth-metadata" href="{{ route('indieauth.metadata') }}">
|
||||
<link rel="authorization_endpoint" href="{{ route('indieauth.start') }}">
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>Atom feed for {{ config('user.display_name') }}’s notes</title>
|
||||
<link rel="self" href="{{ config('app.url') }}/notes/feed.atom" />
|
||||
<id>{{ config('app.url')}}/notes</id>
|
||||
<updated>{{ $notes[0]->updated_at->toAtomString() }}</updated>
|
||||
|
||||
@foreach($notes as $note)
|
||||
<entry>
|
||||
<title>{{ strip_tags($note->note) }}</title>
|
||||
<link href="{{ $note->uri }}" />
|
||||
<id>{{ $note->uri }}</id>
|
||||
<updated>{{ $note->updated_at->toAtomString() }}</updated>
|
||||
<content type="html">{{ $note->note }}</content>
|
||||
<author>
|
||||
<name>{{ config('user.display_name') }}</name>
|
||||
</author>
|
||||
</entry>
|
||||
@endforeach
|
||||
</feed>
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>{{ config('user.display_name') }}</title>
|
||||
<atom:link href="{{ config('app.url') }}/notes/feed.rss" rel="self" type="application/rss+xml" />
|
||||
<description>An RSS feed of the notes found on {{ config('app.url') }}</description>
|
||||
<link>{{ config('app.url') }}/notes</link>
|
||||
<lastBuildDate>{{ $buildDate }}</lastBuildDate>
|
||||
<ttl>1800</ttl>
|
||||
|
||||
@foreach($notes as $note)
|
||||
<item>
|
||||
<title>{{ strip_tags($note->note) }}</title>
|
||||
<description>
|
||||
<![CDATA[
|
||||
{!! $note->note !!}
|
||||
]]>
|
||||
</description>
|
||||
<link>{{ $note->uri }}</link>
|
||||
<guid>{{ $note->uri}}</guid>
|
||||
<pubDate>{{ $note->pubdate }}</pubDate>
|
||||
</item>
|
||||
@endforeach
|
||||
|
||||
</channel>
|
||||
</rss>
|
||||
|
|
@ -170,8 +170,6 @@ Route::middleware(MyAuthMiddleware::class)->prefix('admin')->group(function () {
|
|||
|
||||
// Blog pages using ArticlesController
|
||||
Route::prefix('blog')->group(function () {
|
||||
Route::get('/feed.rss', [FeedsController::class, 'blogRss'])->name('feed.blog.rss');
|
||||
Route::get('/feed.atom', [FeedsController::class, 'blogAtom'])->name('feed.blog.atom');
|
||||
Route::get('/feed.json', [FeedsController::class, 'blogJson'])->name('feed.blog.json');
|
||||
Route::get('/feed.jf2', [FeedsController::class, 'blogJf2'])->name('feed.blog.jf2');
|
||||
Route::get('/s/{id}', [ArticlesController::class, 'onlyIdInURL']);
|
||||
|
|
@ -182,8 +180,6 @@ Route::prefix('blog')->group(function () {
|
|||
// Notes pages using NotesController
|
||||
Route::prefix('notes')->group(function () {
|
||||
Route::get('/', [NotesController::class, 'index']);
|
||||
Route::get('/feed.rss', [FeedsController::class, 'notesRss'])->name('feed.notes.rss');
|
||||
Route::get('/feed.atom', [FeedsController::class, 'notesAtom'])->name('feed.notes.atom');
|
||||
Route::get('/feed.json', [FeedsController::class, 'notesJson'])->name('feed.notes.json');
|
||||
Route::get('/feed.jf2', [FeedsController::class, 'notesJf2'])->name('feed.notes.jf2');
|
||||
Route::get('/new', [NotesController::class, 'create']);
|
||||
|
|
|
|||
|
|
@ -15,42 +15,6 @@ class FeedsTest extends TestCase
|
|||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/**
|
||||
* Test the blog RSS feed.
|
||||
*/
|
||||
#[Test]
|
||||
public function blog_rss_feed_is_present(): void
|
||||
{
|
||||
Article::factory()->count(3)->create();
|
||||
$response = $this->get('/blog/feed.rss');
|
||||
$response->assertHeader('Content-Type', 'application/rss+xml; charset=utf-8');
|
||||
$response->assertOk();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the notes RSS feed.
|
||||
*/
|
||||
#[Test]
|
||||
public function notes_rss_feed_is_present(): void
|
||||
{
|
||||
Note::factory()->count(3)->create();
|
||||
$response = $this->get('/notes/feed.rss');
|
||||
$response->assertHeader('Content-Type', 'application/rss+xml; charset=utf-8');
|
||||
$response->assertOk();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the blog RSS feed.
|
||||
*/
|
||||
#[Test]
|
||||
public function blog_atom_feed_is_present(): void
|
||||
{
|
||||
Article::factory()->count(3)->create();
|
||||
$response = $this->get('/blog/feed.atom');
|
||||
$response->assertHeader('Content-Type', 'application/atom+xml; charset=utf-8');
|
||||
$response->assertOk();
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function blog_jf2_feed_is_present(): void
|
||||
{
|
||||
|
|
@ -73,18 +37,6 @@ class FeedsTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the notes RSS feed.
|
||||
*/
|
||||
#[Test]
|
||||
public function notes_atom_feed_is_present(): void
|
||||
{
|
||||
Note::factory()->count(3)->create();
|
||||
$response = $this->get('/notes/feed.atom');
|
||||
$response->assertHeader('Content-Type', 'application/atom+xml; charset=utf-8');
|
||||
$response->assertOk();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the blog JSON feed.
|
||||
*/
|
||||
|
|
@ -93,7 +45,7 @@ class FeedsTest extends TestCase
|
|||
{
|
||||
Article::factory()->count(3)->create();
|
||||
$response = $this->get('/blog/feed.json');
|
||||
$response->assertHeader('Content-Type', 'application/json');
|
||||
$response->assertHeader('Content-Type', 'application/feed+json');
|
||||
$response->assertOk();
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +57,7 @@ class FeedsTest extends TestCase
|
|||
{
|
||||
Note::factory()->count(3)->create();
|
||||
$response = $this->get('/notes/feed.json');
|
||||
$response->assertHeader('Content-Type', 'application/json');
|
||||
$response->assertHeader('Content-Type', 'application/feed+json');
|
||||
$response->assertOk();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue