Skip to content

Commit

Permalink
contentType setting + JSON Feed 1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonkelly committed Sep 1, 2021
1 parent 693e533 commit bbb3fee
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 6 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# Release Notes for Element API

### Added
- Added the `contentType` endpoint configuration setting.

### Changed
- Element API now requires Craft 3.6 or later.
- API endpoints now send `X-Robots-Tag: none` headers. ([#124](https://github.com/craftcms/element-api/issues/124))
- `OPTIONS` requests now return an empty response. ([#128](https://github.com/craftcms/element-api/issues/128))
- JSON Feed endpoints now set the `version` to `https://jsonfeed.org/version/1.1`.
- JSON Feed endpoints now use the `application/feed+json` content type by default.

### Fixed
- Fixed a bug where API endpoints were returning cached responses for Live Preview requests. ([#143](https://github.com/craftcms/element-api/issues/143))
Expand Down
23 changes: 20 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ An array of parameters that should be set on the [Element Query](https://docs.cr
],
```

#### `contentType`

The content type the endpoint responses should have.

```php
'contentType' => 'application/foo+json',
```

By default, the content type will be:

- `application/javascript` for endpoints that define a JSONP [callback](#callback)
- `application/feed+json` for endpoints where the [serializer](#serializer) is set to `jsonFeed`
- `application/json` for everything else

#### `transformer`

The [transformer](http://fractal.thephpleague.com/transformers/) that should be used to define the data that should be returned for each element. If you don’t set this, the default transformer will be used, which includes all of the element’s direct attribute values, but no custom field values.
Expand Down Expand Up @@ -237,7 +251,7 @@ Possible values are:
- `'array'` _(default)_ – formats data using the [ArraySerializer](http://fractal.thephpleague.com/serializers/#arrayserializer).
- `'dataArray'` – formats data using the [DataArraySerializer](http://fractal.thephpleague.com/serializers/#dataarrayserializer).
- `'jsonApi'` – formats data using the [JsonApiSerializer](http://fractal.thephpleague.com/serializers/#jsonapiserializer).
- `'jsonFeed'` – formats data based on [JSON Feed V1](https://jsonfeed.org/version/1) (see the [JSON Feed](#json-feed) example below).
- `'jsonFeed'` – formats data based on [JSON Feed V1.1](https://www.jsonfeed.org/version/1.1/) (see the [JSON Feed](#json-feed) example below).
- A custom serializer instance.

#### `includes`
Expand Down Expand Up @@ -478,7 +492,7 @@ Here are a few endpoint examples, and what their response would look like.

### JSON Feed

Here’s how to set up a [JSON Feed](https://jsonfeed.org/) ([Version 1](https://jsonfeed.org/version/1)) for your site with Element API.
Here’s how to set up a [JSON Feed](https://jsonfeed.org/) ([Version 1.1](https://www.jsonfeed.org/version/1.1/)) for your site with Element API.

Note that `photos`, `body`, `summary`, and `tags` are imaginary custom fields.

Expand All @@ -500,7 +514,10 @@ Note that `photos`, `body`, `summary`, and `tags` are imaginary custom fields.
'image' => $image ? $image->url : null,
'date_published' => $entry->postDate->format(\DateTime::ATOM),
'date_modified' => $entry->dateUpdated->format(\DateTime::ATOM),
'author' => ['name' => $entry->author->name],
'authors' => [
['name' => $entry->author->name],
],
'language' => $entry->getSite()->language,
'tags' => array_map('strval', $entry->tags->all()),
];
},
Expand Down
2 changes: 1 addition & 1 deletion src/JsonFeedV1Serializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function collection($resourceKey, array $data)
public function meta(array $meta)
{
return array_merge([
'version' => 'https://jsonfeed.org/version/1',
'version' => 'https://jsonfeed.org/version/1.1',
'title' => \Craft::$app->getSites()->getCurrentSite()->name,
'home_page_url' => UrlHelper::baseSiteUrl(),
'feed_url' => UrlHelper::url(Craft::$app->getRequest()->getPathInfo()),
Expand Down
21 changes: 19 additions & 2 deletions src/controllers/DefaultController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use craft\elementapi\Plugin;
use craft\helpers\ArrayHelper;
use craft\helpers\ConfigHelper;
use craft\helpers\StringHelper;
use craft\web\Controller;
use League\Fractal\Manager;
use League\Fractal\Serializer\ArraySerializer;
Expand Down Expand Up @@ -105,8 +106,14 @@ public function actionIndex(string $pattern): Response
$cacheService = Craft::$app->getCache();

if (($cachedContent = $cacheService->get($cacheKey)) !== false) {
if (StringHelper::startsWith($cachedContent, 'data:')) {
list($contentType, $cachedContent) = explode(',', substr($cachedContent, 5), 2);
}
// Set the JSON headers
(new JsonResponseFormatter())->format($this->response);
$formatter = new JsonResponseFormatter([
'contentType' => $contentType ?? null,
]);
$formatter->format($this->response);

// Set the cached JSON on the response and return
$this->response->format = Response::FORMAT_RAW;
Expand All @@ -125,6 +132,7 @@ public function actionIndex(string $pattern): Response
$pretty = ArrayHelper::remove($config, 'pretty', false);
$includes = ArrayHelper::remove($config, 'includes', []);
$excludes = ArrayHelper::remove($config, 'excludes', []);
$contentType = ArrayHelper::remove($config, 'contentType');

// Generate all transforms immediately
Craft::$app->getConfig()->getGeneral()->generateTransformsBeforePageLoad = true;
Expand All @@ -150,6 +158,9 @@ public function actionIndex(string $pattern): Response
break;
case 'jsonFeed':
$serializer = new JsonFeedV1Serializer();
if ($contentType === null) {
$contentType = 'application/feed+json';
}
break;
default:
$serializer = new ArraySerializer();
Expand Down Expand Up @@ -189,6 +200,7 @@ public function actionIndex(string $pattern): Response

// Create a JSON response formatter with custom options
$formatter = new JsonResponseFormatter([
'contentType' => $contentType ?? null,
'useJsonp' => $callback !== null,
'encodeOptions' => $jsonOptions,
'prettyPrint' => $pretty,
Expand Down Expand Up @@ -222,8 +234,13 @@ public function actionIndex(string $pattern): Response
/** @phpstan-ignore-next-line */
$dep = $elementsService->stopCollectingCacheTags();
$dep->tags[] = 'element-api';

$cachedContent = $this->response->content;
if (isset($contentType)) {
$cachedContent = "data:$contentType,$cachedContent";
}
/** @phpstan-ignore-next-line */
$cacheService->set($cacheKey, $this->response->content, $expire, $dep);
$cacheService->set($cacheKey, $cachedContent, $expire, $dep);
}

// Don't double-encode the data
Expand Down

0 comments on commit bbb3fee

Please sign in to comment.