Skip to content

Commit a5815ce

Browse files
authored
Merge pull request #2904 from codeigniter4/apiformat
Allow bypassing content negotiation during API responses.
2 parents 06dd676 + 2783a75 commit a5815ce

3 files changed

Lines changed: 50 additions & 11 deletions

File tree

system/API/ResponseTrait.php

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
*/
5757
trait ResponseTrait
5858
{
59-
6059
/**
6160
* Allows child classes to override the
6261
* status code that is used in their API.
@@ -95,8 +94,11 @@ trait ResponseTrait
9594
];
9695

9796
/**
97+
* How to format the response data.
98+
* Either 'json' or 'xml'. If blank will be
99+
* determine through content negotiation.
98100
*
99-
* @var string the representation format to return resource data in (json/xml)
101+
* @var string
100102
*/
101103
protected $format = 'json';
102104

@@ -384,17 +386,14 @@ protected function format($data = null)
384386
return $data;
385387
}
386388

387-
// Determine correct response type through content negotiation
388389
$config = new Format();
390+
$format = "application/$this->format";
389391

390-
if (! in_array($this->format, ['json', 'xml']))
392+
// Determine correct response type through content negotiation if not explicitly declared
393+
if (empty($this->format) || ! in_array($this->format, ['json', 'xml']))
391394
{
392395
$format = $this->request->negotiate('media', $config->supportedResponseFormats, false);
393396
}
394-
else
395-
{
396-
$format = "application/$this->format";
397-
}
398397

399398
$this->response->setContentType($format);
400399

@@ -415,4 +414,17 @@ protected function format($data = null)
415414
return $this->formatter->format($data);
416415
}
417416

417+
/**
418+
* Sets the format the response should be in.
419+
*
420+
* @param string $format
421+
*
422+
* @return $this
423+
*/
424+
public function setResponseFormat(string $format = null)
425+
{
426+
$this->format = strtolower($format);
427+
428+
return $this;
429+
}
418430
}

tests/system/API/ResponseTraitTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,4 +502,19 @@ public function __construct(&$request, &$response)
502502
$this->assertStringStartsWith(config('Format')->supportedResponseFormats[0], $response->getHeaderLine('Content-Type'));
503503
}
504504

505+
public function testResponseFormat()
506+
{
507+
$data = ['foo' => 'something'];
508+
509+
$controller = $this->makeController();
510+
$controller->setResponseFormat('json');
511+
$controller->respond($data, 201);
512+
513+
$this->assertStringStartsWith('application/json', $this->response->getHeaderLine('Content-Type'));
514+
515+
$controller->setResponseFormat('xml');
516+
$controller->respond($data, 201);
517+
518+
$this->assertStringStartsWith('application/xml', $this->response->getHeaderLine('Content-Type'));
519+
}
505520
}

user_guide_src/source/outgoing/api_responses.rst

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ When you pass your data in any of these methods, they will determine the data ty
7373
the following criteria:
7474

7575
* If $data is a string, it will be treated as HTML to send back to the client.
76-
* If $data is an array, it will try to negotiate the content type with what the client asked for, defaulting to JSON
76+
* If $data is an array, it will be formatted according to the controller's ``$this->format`` value. If that is empty
77+
it will try to negotiate the content type with what the client asked for, defaulting to JSON
7778
if nothing else has been specified within Config\API.php, the ``$supportedResponseFormats`` property.
7879

7980
To define the formatter that is used, edit **Config/Format.php**. The ``$supportedResponseFormats`` contains a list of
@@ -104,6 +105,17 @@ JSON data will be sent back to the client.
104105

105106
Class Reference
106107
***************
108+
.. php:method:: setResponseFormat($format)
109+
110+
:param string $format The type of response to return, either ``json`` or ``xml``
111+
112+
This defines the format to be used when formatting arrays in responses. If you provide a ``null`` value for
113+
``$format``, it will be automatically determined through content negotiation.
114+
115+
::
116+
117+
return $this->setResponseFormat('json')->respond(['error' => false]);
118+
107119

108120
.. php:method:: respond($data[, $statusCode=200[, $message='']])
109121
@@ -186,13 +198,13 @@ Class Reference
186198
:param string $message: A custom "reason" message to return.
187199
:returns: The value of the Response object's send() method.
188200

189-
Sets the appropriate status code to use when a command was successfully executed by the server but there is no
201+
Sets the appropriate status code to use when a command was successfully executed by the server but there is no
190202
meaningful reply to send back to the client, typically 204.
191203

192204
::
193205

194206
sleep(1);
195-
return $this->respondNoContent();
207+
return $this->respondNoContent();
196208

197209
.. php:method:: failUnauthorized(string $description = 'Unauthorized'[, string $code=null[, string $message = '']])
198210

0 commit comments

Comments
 (0)