REST: JSON schema definitions for additional response bodies

Bug: T376603
Depends-On: I4193b9be4516717c7ce423131370a7d0b6ea8962
Change-Id: Ic2d9471ad446eb5f9d5e7072f1ef93f7196a20f8
This commit is contained in:
Wendy Quarshie 2024-10-30 04:25:25 +00:00 committed by Reedy
parent c192133daf
commit 87b34ec850
17 changed files with 763 additions and 30 deletions

View file

@ -190,4 +190,7 @@ class LanguageLinksHandler extends SimpleHandler {
return (bool)$this->getPage();
}
public function getResponseBodySchemaFileName( string $method ): ?string {
return 'includes/Rest/Handler/Schema/PageLanguageLinks.json';
}
}

View file

@ -171,4 +171,8 @@ class MediaFileHandler extends SimpleHandler {
$file = $this->getFile();
return $file && $file->exists();
}
public function getResponseBodySchemaFileName( string $method ): ?string {
return 'includes/Rest/Handler/Schema/MediaFile.json';
}
}

View file

@ -192,4 +192,8 @@ class MediaLinksHandler extends SimpleHandler {
protected function getMaxNumLinks(): int {
return self::MAX_NUM_LINKS;
}
public function getResponseBodySchemaFileName( string $method ): ?string {
return 'includes/Rest/Handler/Schema/MediaLinks.json';
}
}

View file

@ -181,4 +181,23 @@ class PageHTMLHandler extends SimpleHandler {
HtmlOutputRendererHelper::getParamSettings()
);
}
protected function generateResponseSpec( string $method ): array {
$spec = parent::generateResponseSpec( $method );
// TODO: Consider if we prefer something like:
// text/html; charset=utf-8; profile="https://www.mediawiki.org/wiki/Specs/HTML/2.8.0"
// That would be more specific, but fragile when the profile version changes. It could
// also be inaccurate if the page content was not in fact produced by Parsoid.
if ( $this->getOutputMode() == 'html' ) {
unset( $spec['200']['content']['application/json'] );
$spec['200']['content']['text/html']['schema']['type'] = 'string';
}
return $spec;
}
public function getResponseBodySchemaFileName( string $method ): ?string {
return 'includes/Rest/Handler/Schema/ExistingPageHtml.json';
}
}

View file

@ -484,4 +484,8 @@ class PageHistoryHandler extends SimpleHandler {
protected function hasRepresentation() {
return (bool)$this->getPage();
}
public function getResponseBodySchemaFileName( string $method ): ?string {
return 'includes/Rest/Handler/Schema/PageHistory.json';
}
}

View file

@ -167,12 +167,21 @@ class PageSourceHandler extends SimpleHandler {
return $this->contentHelper->hasContent();
}
/**
* This method specifies the JSON schema file for the response body
*
* @return ?string The file path to the ExistingPage JSON schema.
*/
public function getResponseBodySchemaFileName( string $method ): ?string {
return 'includes/Rest/Handler/Schema/ExistingPage.json';
// This does not include restbase compatibility mode, which is triggered by request
// headers. Presumably, such callers will look at the RESTBase spec instead.
switch ( $this->getConfig()['format'] ) {
case 'bare':
$schema = 'includes/Rest/Handler/Schema/ExistingPageBare.json';
break;
case 'source':
$schema = 'includes/Rest/Handler/Schema/ExistingPageSource.json';
break;
default:
$schema = null;
break;
}
return $schema;
}
}

View file

@ -0,0 +1,62 @@
{
"description": "Page without content",
"required": [
"id",
"key",
"title",
"latest",
"content_model",
"license",
"html_url"
],
"properties": {
"id": {
"type": "integer",
"description": "Page identifier"
},
"key": {
"type": "string",
"description": "Page title in URL-friendly format"
},
"title": {
"type": "string",
"description": "Page title"
},
"latest": {
"type": "object",
"description": "Information about the latest revision",
"properties": {
"id": {
"type": "integer",
"description": "Revision identifier for the latest revision"
},
"timestamp": {
"type": "string",
"description": " Timestamp of the latest revision"
}
}
},
"content_model": {
"type": "string",
"description": "Page content type"
},
"license": {
"type": "object",
"description": "Information about the wiki's license",
"properties": {
"url": {
"type": "string",
"description": "URL of the applicable license"
},
"title": {
"type": "string",
"description": "Name of the applicable license"
}
}
},
"html_url": {
"type": "string",
"description": "API route to fetch the content of the page in HTML"
}
}
}

View file

@ -0,0 +1,62 @@
{
"description": "Page with HTML content",
"required": [
"id",
"key",
"title",
"latest",
"content_model",
"license",
"html"
],
"properties": {
"id": {
"type": "integer",
"description": "Page identifier"
},
"key": {
"type": "string",
"description": "Page title in URL-friendly format"
},
"title": {
"type": "string",
"description": "Page title in reading-friendly format"
},
"latest": {
"type": "object",
"description": "Information about the latest revision",
"properties": {
"id": {
"type": "integer",
"description": "Revision identifier for the latest revision"
},
"timestamp": {
"type": "string",
"description": " Timestamp of the latest revision in ISO 8601 format"
}
}
},
"content_model": {
"type": "string",
"description": "Type of content on the page"
},
"license": {
"type": "object",
"description": "Information about the wiki's license",
"properties": {
"url": {
"type": "string",
"description": "URL of the applicable license based on the $wgRightsUrl setting"
},
"title": {
"type": "string",
"description": "Name of the applicable license based on the $wgRightsText setting"
}
}
},
"html": {
"type": "string",
"description": "Latest page content in HTML, following the HTML specification"
}
}
}

View file

@ -1,17 +1,18 @@
{
"description": "Schema for wiki pages.",
"description": "Page with source (usually wikitext)",
"required": [
"id",
"key",
"title",
"latest",
"content_model",
"license"
"license",
"source"
],
"properties": {
"id": {
"type": "integer",
"description": "Page identifier."
"description": "Page identifier"
},
"key": {
"type": "string",
@ -40,7 +41,7 @@
"description": "Page content type"
},
"license": {
"type": "string",
"type": "object",
"description": "Information about the wiki's license",
"properties": {
"url": {

View file

@ -0,0 +1,165 @@
{
"description": "Information about the file",
"required": [
"title",
"file_description_url",
"latest",
"preferred",
"original",
"thumbnail"
],
"properties": {
"title": {
"type": "string",
"description": "File title"
},
"file_description_url": {
"type": "string",
"description": "URL for the page describing the file, including license information and other metadata"
},
"latest": {
"type": "object",
"nullable": true,
"description": "Information about the latest revision to the file",
"properties": {
"timestamp": {
"type": "string",
"format": "date-time",
"description": "Last modified timestamp in ISO 8601 format"
},
"user": {
"type": "object",
"description": "Information about the user who uploaded the file",
"properties": {
"id": {
"type": "integer",
"nullable": true,
"description": "User identifier"
},
"name": {
"type": "string",
"nullable": true,
"description": "Username"
}
},
"required": [ "id", "name" ]
}
},
"required": [ "timestamp", "user" ]
},
"preferred": {
"type": "object",
"nullable": true,
"description": "Information about the file's preferred preview format, original format, and thumbnail format",
"properties": {
"mediatype": {
"type": "string",
"enum": [ "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "UNKNOWN", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ],
"description": "The file type"
},
"size": {
"type": "integer",
"nullable": true,
"description": "File size in bytes or null if not available"
},
"width": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image width in pixels or null if not available"
},
"height": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image height in pixels or null if not available"
},
"duration": {
"type": "number",
"nullable": true,
"description": "The length of the video, audio, or multimedia file or null for other media types"
},
"url": {
"type": "string",
"format": "uri",
"description": "URL to download the file"
}
},
"required": [ "mediatype", "size", "width", "height", "duration", "url" ]
},
"original": {
"type": "object",
"nullable": true,
"description": "Original file details",
"properties": {
"mediatype": {
"type": "string",
"enum": [ "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "UNKNOWN", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ],
"description": "The file type"
},
"size": {
"type": "integer",
"nullable": true,
"description": "File size in bytes or null if not available"
},
"width": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image width in pixels or null if not available"
},
"height": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image height in pixels or null if not available"
},
"duration": {
"type": "number",
"nullable": true,
"description": "The length of the video, audio, or multimedia file or null for other media types"
},
"url": {
"type": "string",
"format": "url",
"description": "URL to download the file"
}
},
"required": [ "mediatype", "size", "width", "height", "duration", "url" ]
},
"thumbnail": {
"type": "object",
"nullable": true,
"description": "Thumbnail information",
"properties": {
"mediatype": {
"type": "string",
"enum": [ "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "UNKNOWN", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D" ],
"description": "The file type"
},
"size": {
"type": "integer",
"nullable": true,
"description": "File size in bytes or null if not available"
},
"width": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image width in pixels or null if not available"
},
"height": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image height in pixels or null if not available"
},
"duration": {
"type": "number",
"nullable": true,
"description": "The length of the video, audio, or multimedia file or null for other media types"
},
"url": {
"type": "string",
"format": "uri",
"description": "URL to download the file"
}
},
"required": [ "mediatype", "size", "width", "height", "duration", "url" ]
}
}
}

View file

@ -0,0 +1,182 @@
{
"description": "Media links for the page",
"required": [
"files"
],
"properties": {
"files": {
"type": "array",
"description": "Array of media used on the page",
"items": {
"type": "object",
"required": [
"title",
"file_description_url",
"latest",
"preferred",
"original"
],
"properties": {
"title": {
"type": "string",
"description": "File title"
},
"file_description_url": {
"type": "string",
"description": "URL for the page describing the file, including license information and other metadata"
},
"latest": {
"type": "object",
"nullable": true,
"description": "Information about the latest revision to the file",
"properties": {
"timestamp": {
"type": "string",
"format": "date-time",
"description": "Last modified timestamp in ISO 8601 format"
},
"user": {
"type": "object",
"description": "Information about the user who uploaded the file",
"properties": {
"id": {
"type": "integer",
"nullable": true,
"description": "User identifier"
},
"name": {
"type": "string",
"nullable": true,
"description": "Username"
}
},
"required": [
"id",
"name"
]
}
},
"required": [
"timestamp",
"user"
]
},
"preferred": {
"type": "object",
"nullable": true,
"description": "Information about the file's preferred preview format, original format, and thumbnail format",
"properties": {
"mediatype": {
"type": "string",
"enum": [
"BITMAP",
"DRAWING",
"AUDIO",
"VIDEO",
"MULTIMEDIA",
"UNKNOWN",
"OFFICE",
"TEXT",
"EXECUTABLE",
"ARCHIVE",
"3D"
],
"description": "The file type"
},
"size": {
"type": "integer",
"nullable": true,
"description": "File size in bytes or null if not available"
},
"width": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image width in pixels or null if not available"
},
"height": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image height in pixels or null if not available"
},
"duration": {
"type": "number",
"nullable": true,
"description": "The length of the video, audio, or multimedia file or null for other media types"
},
"url": {
"type": "string",
"format": "uri",
"description": "URL to download the file"
}
},
"required": [
"mediatype",
"size",
"width",
"height",
"duration",
"url"
]
},
"original": {
"type": "object",
"nullable": true,
"description": "Original file details",
"properties": {
"mediatype": {
"type": "string",
"enum": [
"BITMAP",
"DRAWING",
"AUDIO",
"VIDEO",
"MULTIMEDIA",
"UNKNOWN",
"OFFICE",
"TEXT",
"EXECUTABLE",
"ARCHIVE",
"3D"
],
"description": "The file type"
},
"size": {
"type": "integer",
"nullable": true,
"description": "File size in bytes or null if not available"
},
"width": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image width in pixels or null if not available"
},
"height": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image height in pixels or null if not available"
},
"duration": {
"type": "number",
"nullable": true,
"description": "The length of the video, audio, or multimedia file or null for other media types"
},
"url": {
"type": "string",
"format": "uri",
"description": "URL to download the file"
}
},
"required": [
"mediatype",
"size",
"width",
"height",
"duration",
"url"
]
}
}
}
}
}
}

View file

@ -1,34 +1,62 @@
{
"description": "Schema for wiki pages.",
"description": "The new page, including source (usually wikitext)",
"required": [
"source",
"id",
"title",
"comment",
"key",
"latest",
"license",
"content_model",
"token"
"source"
],
"properties": {
"source": {
"type": "string",
"description": "Page content in the format specified by the content_model property"
"id": {
"type": "integer",
"description": "Page identifier"
},
"title": {
"type": "string",
"description": "Page title"
},
"comment": {
"key": {
"type": "string",
"description": "Reason for creating the page."
"description": "Page title in URL-friendly format"
},
"latest": {
"type": "object",
"description": "Information about the latest revision",
"properties": {
"id": {
"type": "integer",
"description": "Revision identifier for the latest revision"
},
"timestamp": {
"type": "string",
"description": " Timestamp of the latest revision"
}
}
},
"license": {
"type": "object",
"description": "Information about the wiki's license",
"properties": {
"url": {
"type": "string",
"description": "URL of the applicable license"
},
"title": {
"type": "string",
"description": "Name of the applicable license"
}
}
},
"content_model": {
"type": "string",
"nullable": true,
"description": "Page content type"
},
"token": {
"source": {
"type": "string",
"nullable": true,
"description": "CSRF token required when using cookie-based authentication."
"description": "Page content in the format specified by the content_model property"
}
}
}

View file

@ -0,0 +1,78 @@
{
"description": "Page revision history",
"required": [
"revisions",
"latest"
],
"properties": {
"revisions": {
"type": "array",
"description": "List of revisions of the page",
"items": {
"type": "object",
"required": [
"id",
"timestamp",
"minor",
"size",
"comment",
"user",
"delta"
],
"properties": {
"id": {
"type": "integer",
"description": "Unique revision identifier"
},
"timestamp": {
"type": "string",
"format": "date-time"
},
"minor": {
"type": "boolean",
"description": "True if the edit is marked as minor"
},
"size": {
"type": "integer",
"description": "Size of the revision in bytes"
},
"comment": {
"type": "string",
"nullable": true,
"description": "The comment the author associated with the revision"
},
"user": {
"type": "object",
"nullable": true,
"description": "Information about the user who made the revision",
"properties": {
"id": {
"type": "integer",
"nullable": true,
"description": "Unique identifier for the user; null for anonymous users"
},
"name": {
"type": "string",
"description": "Username of the editor, or IP address if the user is anonymous"
}
},
"required": [
"id",
"name"
]
},
"delta": {
"type": "integer",
"nullable": true,
"description": "Change in size between this revision and the preceding one; null if not available"
}
}
}
},
"latest": {
"type": "string",
"format": "uri",
"description": "URL to the latest revision of the page"
}
}
}

View file

@ -0,0 +1,30 @@
{
"description": "Interlanguage links for the page",
"type": "array",
"items": {
"required": [
"code",
"name",
"key",
"title"
],
"properties": {
"code": {
"type": "string",
"description": "Language code"
},
"name": {
"type": "string",
"description": "Translated language name"
},
"key": {
"type": "string",
"description": "Translated page title in URL-friendly format"
},
"title": {
"type": "string",
"description": "Translated page title in reading-friendly format"
}
}
}
}

View file

@ -0,0 +1,84 @@
{
"description": "Search results",
"required": [
"pages"
],
"properties": {
"pages": {
"type": "array",
"description": "List of search result pages",
"items": {
"type": "object",
"required": [
"id",
"key",
"title",
"excerpt",
"matched_title",
"description",
"thumbnail"
],
"properties": {
"id": {
"type": "integer",
"description": "Page identifier"
},
"key": {
"type": "string",
"description": "Page title in URL-friendly format"
},
"title": {
"type": "string",
"description": "Page title in reading-friendly format"
},
"excerpt": {
"type": "string",
"description": "Excerpt of the page content matching the search query"
},
"matched_title": {
"type": "string",
"nullable": true,
"description": "The title of a page redirection from, if applicable, or null"
},
"description": {
"type": "string",
"nullable": true,
"description": "Short summary of the page topic or null if no summary exists."
},
"thumbnail": {
"type": "object",
"nullable": true,
"description": "Information about the thumbnail image for the page, or null if no thumbnail exists.",
"properties": {
"mimetype": {
"type": "string",
"description": "The file type"
},
"width": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image width in pixels or null if not available"
},
"height": {
"type": "integer",
"nullable": true,
"description": "Maximum recommended image height in pixels or null if not available"
},
"duration": {
"type": "number",
"nullable": true,
"description": "The length of the video, audio, or multimedia file or null for other media types"
},
"url": {
"type": "string",
"format": "uri",
"description": "URL to download the file"
}
},
"required": [ "mimetype", "width", "height", "duration", "url" ]
}
}
}
}
}
}

View file

@ -414,4 +414,8 @@ class SearchHandler extends Handler {
],
];
}
public function getResponseBodySchemaFileName( string $method ): ?string {
return 'includes/Rest/Handler/Schema/SearchResults.json';
}
}

View file

@ -254,13 +254,7 @@ class UpdateHandler extends EditHandler {
return FormatJson::decode( $json, true );
}
/**
* This method specifies the JSON schema file for the response
* body when updating an existing page.
*
* @return ?string The file path to the ExistingPage JSON schema.
*/
public function getResponseBodySchemaFileName( string $method ): ?string {
return 'includes/Rest/Handler/Schema/ExistingPage.json';
return 'includes/Rest/Handler/Schema/ExistingPageSource.json';
}
}