Skip to content

Commit 10bcce6

Browse files
authored
Merge pull request #8 from Landerstraeten/add-additional-problems
Add additional problems
2 parents daf27c6 + 000370c commit 10bcce6

15 files changed

+632
-56
lines changed

README.md

Lines changed: 185 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
[![Installs](https://img.shields.io/packagist/dt/phpro/api-problem.svg)](https://packagist.org/packages/phpro/api-problem/stats)
33
[![Packagist](https://img.shields.io/packagist/v/phpro/api-problem.svg)](https://packagist.org/packages/phpro/api-problem)
44

5-
65
# Api Problem
76

87
This package provides a [RFC7807](https://tools.ietf.org/html/rfc7807) Problem details implementation.
@@ -13,7 +12,6 @@ Since handling the exceptions is up to the framework, here is a list of known fr
1312

1413
- **Symfony** `^4.1`: [ApiProblemBundle](https://www.github.com/phpro/api-problem-bundle)
1514

16-
1715
## Installation
1816

1917
```sh
@@ -34,14 +32,26 @@ throw new ApiProblemException(
3432

3533
### Built-in problems
3634

37-
- [ExceptionApiProblem](#exceptionapiproblem)
38-
- [ForbiddenProblem](#forbiddenproblem)
39-
- [HttpApiProblem](#httpapiproblem)
40-
- [NotFoundProblem](#notfoundproblem)
41-
- [UnauthorizedProblem](#unauthorizedproblem)
42-
- [ValidationApiProblem](#validationapiproblem)
43-
- [BadRequestProblem](#badrequestproblem)
44-
- [ConflictProblem](#conflictproblem)
35+
- General problems
36+
- [ExceptionApiProblem](#exceptionapiproblem)
37+
- [HttpApiProblem](#httpapiproblem)
38+
39+
- Symfony integration problems
40+
- [ValidationApiProblem](#validationapiproblem)
41+
42+
- Http problems
43+
- 400 [BadRequestProblem](#badrequestproblem)
44+
- 401 [UnauthorizedProblem](#unauthorizedproblem)
45+
- 403 [ForbiddenProblem](#forbiddenproblem)
46+
- 404 [NotFoundProblem](#notfoundproblem)
47+
- 405 [MethodNotAllowedProblem](#methodnotallowedproblem)
48+
- 409 [ConflictProblem](#conflictproblem)
49+
- 412 [PreconditionFailedProblem](#preconditionfailedproblem)
50+
- 415 [UnsupportedMediaTypeProblem](#unsupportedmediatypeproblem)
51+
- 418 [IAmATeapotProblem](#iamateapotproblem)
52+
- 422 [UnprocessableEntityProblem](#unprocessableentityproblem)
53+
- 423 [LockedProblem](#lockedproblem)
54+
- 428 [PreconditionRequiredProblem](#preconditionrequiredproblem)
4555

4656
#### ExceptionApiProblem
4757

@@ -90,54 +100,69 @@ new ExceptionApiProblem(new \Exception('message', 500));
90100
}
91101
````
92102

93-
#### ForbiddenProblem
103+
#### HttpApiProblem
94104

95105
```php
96-
use Phpro\ApiProblem\Http\ForbiddenProblem;
106+
use Phpro\ApiProblem\Http\HttpApiProblem;
97107

98-
new ForbiddenProblem('Not authorized to access gold.');
108+
new HttpApiProblem(404, ['detail' => 'The book could not be found.']);
99109
```
100110

101111
```json
102112
{
103-
"status": 403,
104-
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
105-
"title": "Forbidden",
106-
"detail": "Not authorized to access gold."
113+
"status": 404,
114+
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
115+
"title": "Not found",
116+
"detail": "The book could not be found."
107117
}
108118
````
109119

110-
#### HttpApiProblem
120+
#### ValidationApiProblem
121+
122+
```sh
123+
composer require symfony/validator:^4.1
124+
```
111125

112126
```php
113-
use Phpro\ApiProblem\Http\HttpApiProblem;
127+
use Phpro\ApiProblem\Http\ValidationApiProblem;
128+
use Symfony\Component\Validator\ConstraintViolation;
129+
use Symfony\Component\Validator\ConstraintViolationList;
114130

115-
new HttpApiProblem(404, ['detail' => 'The book could not be found.']);
131+
new ValidationApiProblem(new ConstraintViolationList([
132+
new ConstraintViolation('Invalid email', '', [], '', 'email', '', null, '8615ecd9-afcb-479a-9c78-8bcfe260cf2a'),
133+
]));
116134
```
117135

118136
```json
119137
{
120-
"status": 404,
121-
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
122-
"title": "Not found",
123-
"detail": "The book could not be found."
138+
"status": 400,
139+
"type": "https:\/\/symfony.com\/errors\/validation",
140+
"title": "Validation Failed",
141+
"detail": "email: Invalid Email",
142+
"violations": [
143+
{
144+
"propertyPath": "email",
145+
"title": "Invalid email",
146+
"type": "urn:uuid:8615ecd9-afcb-479a-9c78-8bcfe260cf2a"
147+
}
148+
]
124149
}
125150
````
126151

127-
#### NotFoundProblem
152+
#### BadRequestProblem
128153

129154
```php
130-
use Phpro\ApiProblem\Http\NotFoundProblem;
155+
use Phpro\ApiProblem\Http\BadRequestProblem;
131156

132-
new NotFoundProblem('The book with ID 20 could not be found.');
157+
new BadRequestProblem('Bad request. Bad!.');
133158
```
134159

135160
```json
136161
{
137-
"status": 404,
162+
"status": 400,
138163
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
139-
"title": "Not found",
140-
"detail": "The book with ID 20 could not be found."
164+
"title": "Bad Request",
165+
"detail": "Bad request. Bad!"
141166
}
142167
````
143168

@@ -158,52 +183,54 @@ new UnauthorizedProblem('You are not authorized to access X.');
158183
}
159184
````
160185

161-
#### ValidationApiProblem
186+
#### ForbiddenProblem
162187

163-
```sh
164-
composer require symfony/validator:^4.1
188+
```php
189+
use Phpro\ApiProblem\Http\ForbiddenProblem;
190+
191+
new ForbiddenProblem('Not authorized to access gold.');
165192
```
166193

194+
```json
195+
{
196+
"status": 403,
197+
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
198+
"title": "Forbidden",
199+
"detail": "Not authorized to access gold."
200+
}
201+
````
202+
203+
#### NotFoundProblem
204+
167205
```php
168-
use Phpro\ApiProblem\Http\ValidationApiProblem;
169-
use Symfony\Component\Validator\ConstraintViolation;
170-
use Symfony\Component\Validator\ConstraintViolationList;
206+
use Phpro\ApiProblem\Http\NotFoundProblem;
171207

172-
new ValidationApiProblem(new ConstraintViolationList([
173-
new ConstraintViolation('Invalid email', '', [], '', 'email', '', null, '8615ecd9-afcb-479a-9c78-8bcfe260cf2a'),
174-
]));
208+
new NotFoundProblem('The book with ID 20 could not be found.');
175209
```
176210

177211
```json
178212
{
179-
"status": 400,
180-
"type": "https:\/\/symfony.com\/errors\/validation",
181-
"title": "Validation Failed",
182-
"detail": "email: Invalid Email",
183-
"violations": [
184-
{
185-
"propertyPath": "email",
186-
"title": "Invalid email",
187-
"type": "urn:uuid:8615ecd9-afcb-479a-9c78-8bcfe260cf2a"
188-
}
189-
]
213+
"status": 404,
214+
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
215+
"title": "Not found",
216+
"detail": "The book with ID 20 could not be found."
190217
}
191218
````
192219

193-
#### BadRequestProblem
220+
#### MethodNotAllowedProblem
194221

195222
```php
196-
use Phpro\ApiProblem\Http\BadRequestProblem;
223+
use Phpro\ApiProblem\Http\MethodNotAllowedProblem;
197224

198-
new BadRequestProblem('Bad request. Bad!.');
225+
new MethodNotAllowedProblem('Only POST and GET allowed.');
199226
```
200227

201228
```json
202229
{
203-
"status": 400,
230+
"status": 405,
204231
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
205-
"title": "Bad Request",
206-
"detail": "Bad request. Bad!"
232+
"title": "Method Not Allowed",
233+
"detail": "Only POST and GET allowed."
207234
}
208235
````
209236

@@ -223,6 +250,108 @@ new ConflictProblem('Duplicated key for book with ID 20.');
223250
}
224251
````
225252

253+
#### PreconditionFailedProblem
254+
255+
```php
256+
use Phpro\ApiProblem\Http\PreconditionFailedProblem;
257+
258+
new PreconditionFailedProblem('Incorrect entity tag provided.');
259+
```
260+
261+
```json
262+
{
263+
"status": 412,
264+
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
265+
"title": "Precondition Failed",
266+
"detail": "Incorrect entity tag provided."
267+
}
268+
````
269+
270+
#### UnsupportedMediaTypeProblem
271+
272+
```php
273+
use Phpro\ApiProblem\Http\UnsupportedMediaTypeProblem;
274+
275+
new UnsupportedMediaTypeProblem('Please provide valid JSON.');
276+
```
277+
278+
```json
279+
{
280+
"status": 415,
281+
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
282+
"title": "Unsupported Media Type",
283+
"detail": "Please provide valid JSON."
284+
}
285+
````
286+
287+
#### IAmATeapotProblem
288+
289+
```php
290+
use Phpro\ApiProblem\Http\IAmATeapotProblem;
291+
292+
new IAmATeapotProblem('More tea please.');
293+
```
294+
295+
```json
296+
{
297+
"status": 418,
298+
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
299+
"title": "I'm a teapot",
300+
"detail": "More tea please."
301+
}
302+
````
303+
304+
#### UnprocessableEntityProblem
305+
306+
```php
307+
use Phpro\ApiProblem\Http\UnprocessableEntityProblem;
308+
309+
new UnprocessableEntityProblem('Unable to process the contained instructions.');
310+
```
311+
312+
```json
313+
{
314+
"status": 422,
315+
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
316+
"title": "Unprocessable Entity",
317+
"detail": "Unable to process the contained instructions."
318+
}
319+
````
320+
321+
#### LockedProblem
322+
323+
```php
324+
use Phpro\ApiProblem\Http\LockedProblem;
325+
326+
new LockedProblem('This door is locked.');
327+
```
328+
329+
```json
330+
{
331+
"status": 423,
332+
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
333+
"title": "Locked",
334+
"detail": "This door is locked."
335+
}
336+
````
337+
338+
#### PreconditionRequiredProblem
339+
340+
```php
341+
use Phpro\ApiProblem\Http\PreconditionRequiredProblem;
342+
343+
new PreconditionRequiredProblem('If-match header is required.');
344+
```
345+
346+
```json
347+
{
348+
"status": 428,
349+
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
350+
"title": "Precondition Required",
351+
"detail": "If-match header is required."
352+
}
353+
````
354+
226355
### Creating your own problem
227356

228357
Creating problem sounds scary right!?

spec/Http/IAmATeapotProblemSpec.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace spec\Phpro\ApiProblem\Http;
6+
7+
use Phpro\ApiProblem\Http\HttpApiProblem;
8+
use Phpro\ApiProblem\Http\IAmATeapotProblem;
9+
use PhpSpec\ObjectBehavior;
10+
11+
class IAmATeapotProblemSpec extends ObjectBehavior
12+
{
13+
public function let(): void
14+
{
15+
$this->beConstructedWith('i am a teapot');
16+
}
17+
18+
public function it_is_initializable(): void
19+
{
20+
$this->shouldHaveType(IAmATeapotProblem::class);
21+
}
22+
23+
public function it_is_an_http_api_problem(): void
24+
{
25+
$this->shouldHaveType(HttpApiProblem::class);
26+
}
27+
28+
public function it_can_parse_to_array(): void
29+
{
30+
$this->toArray()->shouldBe([
31+
'status' => 418,
32+
'type' => HttpApiProblem::TYPE_HTTP_RFC,
33+
'title' => HttpApiProblem::getTitleForStatusCode(418),
34+
'detail' => 'i am a teapot',
35+
]);
36+
}
37+
}

0 commit comments

Comments
 (0)