chore: add a PhpStorm HTTP client suite for the chatbot content feed

This commit is contained in:
fromme committed 2026-10-08 09:41:27 +02:00
1 parent 416ac5c13d
commit 7839b97e63
4 files changed
+150 -16

No files matched your search

+1
View File
@@ -20,3 +20,4 @@ public/typo3conf/l10n
public/typo3temp
public/uploads
var
http-client.private.env.json
-16
View File
@@ -10,19 +10,3 @@ GET https://ep-reisen.ddev.site/api/hotel
&key=abcabc123
###
### GET chatbot content manifest (cmsApiKey in extension configuration)
GET https://ep-reisen.ddev.site/api/content/manifest
X-Api-Key: abcabc123
### GET chatbot content records (type: product, hotel, region, country, city, concept, news; at most 100 uids)
GET https://ep-reisen.ddev.site/api/content/records
?type=product
&uids=1,2,3
X-Api-Key: abcabc123
### GET the content-only render of one page (use a contentUrl from the manifest)
GET https://ep-reisen.ddev.site/skireisen/infos/skiurlaub-infos/schneepchen/liegestuhl?type=1730
X-Api-Key: abcabc123
###
+141
View File
@@ -0,0 +1,141 @@
# Chatbot content feed (see .ddev/plans/CHATBOT-MCP-01-TYPO3-CONTENT-FEED.md)
#
# Pick the "local" environment in PhpStorm and run the whole file top to bottom: the manifest
# request stores uids and a content URL that the later requests use.
#
# Needs, locally:
# - http-client.private.env.json with {"local": {"cmsApiKey": "<your key>"}} (gitignored)
# - the same key in TYPO3, e.g.
# ddev exec vendor/bin/typo3cms configuration:set EXTENSIONS/ep_products/cmsApiKey <your key>
# plus contentFeedSites etc. - or open and save the ep_products extension configuration once
# in the backend, which writes all the defaults.
#
# The kill switch (contentFeedEnabled = 0) cannot be toggled from here; with it off, every keyed
# request below answers 503.
### Manifest without a key is refused
GET {{host}}/api/content/manifest
> {%
client.test("403 without key", function () {
client.assert(response.status === 403, "expected 403, got " + response.status);
});
%}
### Manifest
GET {{host}}/api/content/manifest
X-Api-Key: {{cmsApiKey}}
> {%
client.test("manifest is complete and well-formed", function () {
client.assert(response.status === 200, "expected 200, got " + response.status);
client.assert(response.body.items.length > 0, "manifest is empty");
client.assert(response.body.sites.length > 0, "no sites");
client.assert(
response.body.items.every(function (item) { return item.type && item.uid && item.modified; }),
"an item lacks type, uid or modified"
);
});
var uidsOf = function (type, limit) {
return response.body.items
.filter(function (item) { return item.type === type; })
.slice(0, limit)
.map(function (item) { return item.uid; })
.join(",");
};
client.global.set("productUids", uidsOf("product", 5));
client.global.set("hotelUids", uidsOf("hotel", 5));
client.global.set("regionUids", uidsOf("region", 5));
client.global.set("newsUids", uidsOf("news", 3));
var page = response.body.items.filter(function (item) { return item.type === "page" && item.contentUrl; })[0];
client.global.set("contentUrl", page.contentUrl);
var tooMany = [];
for (var i = 1; i <= 101; i++) { tooMany.push(i); }
client.global.set("tooManyUids", tooMany.join(","));
%}
### Products (with FAQs)
GET {{host}}/api/content/records?type=product&uids={{productUids}}
X-Api-Key: {{cmsApiKey}}
> {%
client.test("every requested product comes back, links resolved", function () {
client.assert(response.status === 200, "expected 200, got " + response.status);
client.assert(response.body.items.length === client.global.get("productUids").split(",").length, "products missing");
client.assert(JSON.stringify(response.body).indexOf("t3://") === -1, "unresolved t3:// link");
});
%}
### Hotels (codes include matchcode aliases)
GET {{host}}/api/content/records?type=hotel&uids={{hotelUids}}
X-Api-Key: {{cmsApiKey}}
> {%
client.test("hotels carry their codes", function () {
client.assert(response.status === 200, "expected 200, got " + response.status);
client.assert(response.body.items.every(function (hotel) { return Array.isArray(hotel.codes); }), "hotel without codes");
});
%}
### Regions
GET {{host}}/api/content/records?type=region&uids={{regionUids}}
X-Api-Key: {{cmsApiKey}}
### Blog articles
GET {{host}}/api/content/records?type=news&uids={{newsUids}}
X-Api-Key: {{cmsApiKey}}
### Unknown type is a 400
GET {{host}}/api/content/records?type=page&uids=1
X-Api-Key: {{cmsApiKey}}
> {%
client.test("400 for unknown type", function () {
client.assert(response.status === 400, "expected 400, got " + response.status);
});
%}
### More than 100 uids is a 400
GET {{host}}/api/content/records?type=product&uids={{tooManyUids}}
X-Api-Key: {{cmsApiKey}}
> {%
client.test("400 above 100 uids", function () {
client.assert(response.status === 400, "expected 400, got " + response.status);
});
%}
### Content-only render of the first page in the manifest
GET {{contentUrl}}
X-Api-Key: {{cmsApiKey}}
> {%
client.test("bare article, never cached by proxies", function () {
client.assert(response.status === 200, "expected 200, got " + response.status);
client.assert(response.body.indexOf("<article>") === 0, "not a bare <article> fragment");
client.assert(response.headers.valueOf("Cache-Control") === "private, no-store", "unexpected Cache-Control");
});
%}
### Content-only render without a key is a 404 (the type must not be discoverable)
GET {{contentUrl}}
> {%
client.test("404 without key", function () {
client.assert(response.status === 404, "expected 404, got " + response.status);
});
%}
### Content-only render with a wrong key is a 404
GET {{contentUrl}}
X-Api-Key: definitely-wrong
> {%
client.test("404 with wrong key", function () {
client.assert(response.status === 404, "expected 404, got " + response.status);
});
%}
+8
View File
@@ -0,0 +1,8 @@
{
"local": {
"host": "https://ep-reisen.ddev.site"
},
"staging": {
"host": "https://staging.ep-reisen.de"
}
}