66টি সোশ্যাল নেটওয়ার্কে RSS: Facebook, Instagram, X, LinkedIn, Telegram এবং আরও অনেক কিছু ব্লগ অ্যাফিলিয়েট যোগাযোগ
সাইন ইন ফ্রি শুরু করুন
Updated: 2026-10-21
Litestar RSS Feed in Python: Build It and Auto-Post Items

Short answer: To serve an RSS feed from a Litestar application, add a GET handler for /feed.xml, read the newest published rows with an async database driver, build the document with xml.etree.ElementTree so every value is escaped, format dates with email.utils.format_datetime in UTC and return a Response with the application/rss+xml media type. Compute an ETag from the newest publication time, answer a matching If-None-Match header with a 304, test the address with curl and a validator, then give the public URL to an auto-poster so every new item reaches your social channels.

Litestar is an ASGI framework for Python that grew out of the FastAPI and Starlette world and adds a layered architecture, strong typing with msgspec, built-in dependency injection and a thorough set of plugins for databases and templating. It is a good fit for APIs and for content sites where the team wants structure without a heavy framework. Sooner or later such an application publishes something that people want to follow: articles, release notes, listings or event dates. A feed is the standard way to let readers, aggregators and auto-posters watch that content without an account or an API key. This guide builds a complete Litestar RSS feed with escaping, stable identifiers, correct dates and conditional requests, explains each decision and ends with the checks that keep the feed dependable once other systems rely on it.

When a Litestar application needs a feed

A feed is worth adding whenever the application publishes things that people outside it want to follow:

  • articles, news or announcements stored in a database and rendered by the application;
  • release notes or a changelog for a product, a library or an internal tool;
  • listings, events, offers or job openings added by staff or by users;
  • any content that should also appear on social networks without being copied by hand.

If your content already lives in a blog or a CMS, use the feed it provides instead; see how to find your WordPress feed link. If you run FastAPI or Flask rather than Litestar, see the FastAPI guide অথবা the Flask guide; the feed logic is the same and only the handler syntax differs. The approach below uses only Litestar, an async SQLite driver and the standard library.

Set up the project

Create a virtual environment and install Litestar with the standard extras, which include the uvicorn server, plus the aiosqlite driver. The example uses SQLite, but the query and the document builder stay the same with PostgreSQL through asyncpg or with SQLAlchemy.

python -m venv .venv && source .venv/bin/activate
pip install "litestar[standard]" aiosqlite

Keep the public address of the site in configuration rather than reading it from the incoming request. Behind a reverse proxy, the request may show an internal host name or a plain http scheme, and a feed full of internal addresses is useless to every reader. The example reads the address from an environment variable with a safe default.

The handler

The handler below queries the published rows, builds an ElementTree document, serialises it and returns the response. The condition on the publication time matters: without it, an item scheduled for tomorrow would appear in the feed today, and an auto-poster would share it before it exists on the website. Publication times are stored as epoch seconds in UTC.

import os
import time
import xml.etree.ElementTree as ET
from datetime import datetime, timezone
from email.utils import format_datetime

import aiosqlite
from litestar import Litestar, Request, Response, get

SITE_URL = os.environ.get("SITE_URL", "https://www.example.com")
DB_PATH = "data/site.db"


@get("/feed.xml", cache=False)
async def feed(request: Request) -> Response:
    async with aiosqlite.connect(DB_PATH) as db:
        db.row_factory = aiosqlite.Row
        cursor = await db.execute(
            "SELECT id, title, slug, summary, published_at FROM posts "
            "WHERE status = 'published' AND published_at <= ? "
            "ORDER BY published_at DESC LIMIT 20",
            (int(time.time()),),
        )
        rows = await cursor.fetchall()

    newest = rows[0]["published_at"] if rows else 0
    etag = f'"{newest}-{len(rows)}"'
    headers = {"ETag": etag, "Cache-Control": "public, max-age=300"}
    if request.headers.get("if-none-match") == etag:
        return Response(content=b"", status_code=304, headers=headers)

    rss = ET.Element("rss", version="2.0")
    rss.set("xmlns:atom", "http://www.w3.org/2005/Atom")
    channel = ET.SubElement(rss, "channel")
    ET.SubElement(channel, "title").text = "Example News"
    ET.SubElement(channel, "link").text = SITE_URL + "/"
    ET.SubElement(channel, "description").text = "The latest posts from Example News"
    ET.SubElement(channel, "language").text = "en"
    ET.SubElement(channel, "atom:link", href=SITE_URL + "/feed.xml", rel="self",
                  type="application/rss+xml")

    for row in rows:
        item = ET.SubElement(channel, "item")
        ET.SubElement(item, "title").text = row["title"]
        ET.SubElement(item, "link").text = f"{SITE_URL}/{row['slug']}/"
        guid = ET.SubElement(item, "guid", isPermaLink="false")
        guid.text = f"post-{row['id']}"
        published = datetime.fromtimestamp(row["published_at"], tz=timezone.utc)
        ET.SubElement(item, "pubDate").text = format_datetime(published, usegmt=True)
        ET.SubElement(item, "description").text = row["summary"]

    body = ET.tostring(rss, encoding="utf-8", xml_declaration=True)
    return Response(content=body, media_type="application/rss+xml; charset=utf-8",
                    headers=headers)


app = Litestar(route_handlers=[feed])

Run it with litestar run during development, or with uvicorn in production, and open the route in a browser or with curl. You should see well-formed XML with at most twenty items, newest first. Because every text value is assigned through ElementTree, the serialiser escapes ampersands and angle brackets for you, which is the main reason to build a tree rather than join strings by hand. The handler disables the framework cache for this route, because the ETag logic handles freshness itself; if you prefer the Litestar response cache, set a short expiry and drop the manual 304.

Where each field comes from

Feed fieldSource in the exampleRule to keep
titleThe title columnPlain text, escaped, no markup
linkSite address plus slugAbsolute address that returns 200 directly
guidThe row id with a prefixNever changes, even if the slug changes
pubDateThe publication timestamp in UTCRFC 822 with GMT, never in the future
descriptionThe summary columnOne or two sentences that make sense alone

The identifier is the most important decision. An auto-poster remembers which items it has already shared by their GUID. If the value changes when someone edits a slug or republishes an article, the same story is shared again. Using the database id with a fixed prefix avoids that. The problem and its fixes are described in why a feed auto-posts the same article twice.

Dates in the English format

RSS dates follow RFC 822, with English abbreviations for days and months. The format_datetime function in email.utils prints exactly that shape, and the usegmt flag writes the zone as GMT, which every parser accepts, provided the datetime is timezone-aware and in UTC. The function never localises month names, so there is no risk of a server locale producing names that readers cannot parse. Avoid strftime with a locale setting, and do not use isoformat here; that format belongs to Atom feeds, and many RSS readers reject it. If a validator complains about dates, read the guide to RSS date format errors.

Conditional requests and caching

Auto-posters, readers and search engines request a feed often, and almost always nothing has changed. The handler above deals with that in two ways. It computes an ETag from the newest publication time and the number of items, sets the header on every response and, when the If-None-Match header of the request matches, finishes with a 304 and no body. The Cache-Control header lets a proxy or a content delivery network keep the response for a few minutes. Together they cut the cost of each check to one query.

If you edit old items and want the feed to change, store an updated time and include it in the ETag. Do not cache for hours, because a long cache delays every new post by the same amount. The background to both techniques is in the guide to ETags and conditional GET এবং the guide to feed caching.

Running behind a proxy in production

In production, run the application with uvicorn or granian under a process manager and put a reverse proxy in front of it that terminates HTTPS. Keep the public address in your own setting rather than trusting forwarded headers, so that links in the feed are always correct. Check that the proxy does not strip the ETag and Cache-Control headers and that it does not add its own long cache that keeps old XML for too long. After every deployment, request the feed once to confirm that it still returns 200 and that the address is exactly the one you gave to the auto-poster. If the feed ever stops updating, this checklist shows what to inspect first.

Images and richer items

An auto-poster is more useful when each item carries a picture. Add an enclosure element with the url, length and type attributes, filled from an image column, and use an absolute https address and a file of reasonable size. Without an image, many networks show a plain text card. How tools read these elements is explained in the guide to enclosure tags. If a summary legitimately contains HTML, keep it escaped as ElementTree does, or wrap it in a CDATA block as described in the CDATA guide; both are valid, and readers handle both.

Test the feed before you connect it

  1. Request the route with curl and look at the headers: the status should be 200, the content type should be application/rss+xml and an ETag should be present.
  2. Repeat the request with the ETag in an If-None-Match header and confirm that a 304 comes back.
  3. Paste the public address into the W3C Feed Validation Service and fix every error.
  4. Insert a test row and check that it appears at the top of the feed.
  5. Set a publication time in the future and check that the item stays hidden until then.

There is a longer checklist in the feed validation guide and a short curl routine in the guide to debugging a feed with curl. The Litestar documentation covers handlers, responses and caching in more depth.

Common mistakes to avoid

  • Building XML with f-strings. Use ElementTree so that every value is escaped.
  • Future items. Filter by publication time so scheduled content stays hidden until its moment.
  • Unstable GUIDs. Use an identifier that never changes.
  • Naive datetimes. Build timezone-aware UTC datetimes before formatting, or the GMT suffix is wrong.
  • Addresses taken from the request. Build links from the configured public address.
  • Changing the feed address. Keep the route, or redirect the old one permanently.

How PostRSS works with a Litestar feed

PostRSS has been publishing RSS and Atom feeds to social networks since 2014. Paste the address of your feed route, connect your accounts and choose how each post is built from the title, the description or the page title. PostRSS checks the feed as often as every minute and shares each new item, with its image and link, to the channels you choose among 66 supported networks, messengers, team chats and blogs, including LinkedIn, X, Bluesky, Mastodon and Telegram. Keyword filters, UTM parameters and posting windows let you tune each channel, and webhooks connect PostRSS to your own systems. See the PostRSS features page and the plan limits on the pricing page. More developer guides are under the Technical Guide tag.

সম্পর্কিত পাঠ্য

The bottom line

Litestar needs only a handler, a query and ElementTree to serve a dependable RSS feed: select published items dated in the past, let the serialiser escape every value, use a stable GUID, format dates in RFC 822 UTC with format_datetime, build links from a configured public address and return the result with the right media type, an ETag and a short cache. Test the route with curl and a validator, keep the address unchanged and connect it to an auto-poster. After that, every item you publish can reach your social channels automatically.

FAQ

Does Litestar have a built-in RSS generator?

No. Litestar has no feed support, but xml.etree.ElementTree from the standard library produces a valid feed from a small tree, and a few lines in the handler add the ETag and cache headers that make the route cheap to poll.

Why use ElementTree instead of an f-string?

The serialiser escapes every text value, so a title with an ampersand or an angle bracket cannot break the XML. A template works too, but you must remember to escape every value yourself.

Can I use a feed library instead?

Yes. The feedgen package produces RSS and Atom from the same model. The handler stays the same; only the document building changes.

How many items should the feed contain?

Between ten and twenty of the newest published items is enough. An auto-poster only needs recent items, and a smaller file is faster to download and parse.

How do I stop old posts from being shared again?

Give every item a stable identifier and use it as the GUID. Avoid editing the publication date of items that are already public, because some tools treat a changed date as a new item.

Can I use this feed with PostRSS?

Yes. PostRSS reads any valid RSS or Atom address that is reachable without a login. Paste the address, connect your channels and new items are shared as soon as they appear.

New guides, once a month

What changed in the networks, what broke, and how to fix it before it costs you reach.

We send a confirmation e-mail first. Unsubscribe any time.

আমাদের টিমের আরও টুল

PostRSS-এর পেছনের টিম Internet Solutions-এর তৈরি। প্রতিটি পণ্য নিজের মতো করে আপনার সময় বাঁচায়।

ওয়েবসাইটের জন্য AI লাইভ চ্যাট Talkmio আপনার ওয়েবসাইট আপনার নিজের কনটেন্ট থেকে, দর্শকের ভাষায়, 24/7 উত্তর দেয়। ফ্রি প্ল্যান · কার্ড লাগবে না AI সহকারী Ask Mio চ্যাট, কোড, ডিজাইন, লেখা ও গবেষণা। প্রতিটি কাজের জন্য Mio সেরা মডেলটি বেছে নেয়। ফ্রি প্ল্যান ব্লগ ও সোশ্যাল মিডিয়ার জন্য AI অটোপাইলট AI Blog Autopilot AI 2,000–3,000 শব্দের SEO আর্টিকেল লেখে এবং প্রতিটি 60 সোশ্যাল নেটওয়ার্কে শেয়ার করে। প্রথম 3টি আর্টিকেল ফ্রি ওয়েবসাইট হেলথ চেক সাইট AI অডিট SEO, গতি, SSL, নিরাপত্তা ও ইমেইল সেটআপ এক রিপোর্টে, কোনটা আগে ঠিক করতে হবে সেই ক্রমে। প্রথম অডিট ফ্রি গভীর SEO ক্রল সাইট SEO AI অডিট AI সার্চে দৃশ্যমানতাসহ 7টি ক্ষেত্রে পূর্ণ SEO ক্রল, প্রভাব অনুযায়ী সাজানো সমাধানসহ। প্রথম অডিট ফ্রি RSS ও পণ্য ফিড RSS ফিড ক্রিয়েটর যেকোনো ওয়েব পেজ থেকে RSS তৈরি করুন, সঙ্গে Google ও Meta-র জন্য পণ্য ফিড যা নিজে থেকেই আপডেট হয়। ফ্রি প্ল্যান ওয়েব ডেভেলপমেন্ট ও SEO ইন্টারনেট সলিউশনস ওয়েবসাইট, ই-শপ ও কাস্টম সিস্টেম — আমাদের টিম ডিজাইন করে, তৈরি করে ও পরিচালনা করে। 2011 থেকে