Skip to content

Commit

Permalink
Merge pull request #8 from Landerstraeten/add-additional-problems
Browse files Browse the repository at this point in the history
Add additional problems
  • Loading branch information
veewee authored Jun 12, 2020
2 parents daf27c6 + 000370c commit 10bcce6
Show file tree
Hide file tree
Showing 15 changed files with 632 additions and 56 deletions.
241 changes: 185 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
[![Installs](https://img.shields.io/packagist/dt/phpro/api-problem.svg)](https://packagist.org/packages/phpro/api-problem/stats)
[![Packagist](https://img.shields.io/packagist/v/phpro/api-problem.svg)](https://packagist.org/packages/phpro/api-problem)


# Api Problem

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

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


## Installation

```sh
Expand All @@ -34,14 +32,26 @@ throw new ApiProblemException(

### Built-in problems

- [ExceptionApiProblem](#exceptionapiproblem)
- [ForbiddenProblem](#forbiddenproblem)
- [HttpApiProblem](#httpapiproblem)
- [NotFoundProblem](#notfoundproblem)
- [UnauthorizedProblem](#unauthorizedproblem)
- [ValidationApiProblem](#validationapiproblem)
- [BadRequestProblem](#badrequestproblem)
- [ConflictProblem](#conflictproblem)
- General problems
- [ExceptionApiProblem](#exceptionapiproblem)
- [HttpApiProblem](#httpapiproblem)

- Symfony integration problems
- [ValidationApiProblem](#validationapiproblem)

- Http problems
- 400 [BadRequestProblem](#badrequestproblem)
- 401 [UnauthorizedProblem](#unauthorizedproblem)
- 403 [ForbiddenProblem](#forbiddenproblem)
- 404 [NotFoundProblem](#notfoundproblem)
- 405 [MethodNotAllowedProblem](#methodnotallowedproblem)
- 409 [ConflictProblem](#conflictproblem)
- 412 [PreconditionFailedProblem](#preconditionfailedproblem)
- 415 [UnsupportedMediaTypeProblem](#unsupportedmediatypeproblem)
- 418 [IAmATeapotProblem](#iamateapotproblem)
- 422 [UnprocessableEntityProblem](#unprocessableentityproblem)
- 423 [LockedProblem](#lockedproblem)
- 428 [PreconditionRequiredProblem](#preconditionrequiredproblem)

#### ExceptionApiProblem

Expand Down Expand Up @@ -90,54 +100,69 @@ new ExceptionApiProblem(new \Exception('message', 500));
}
````

#### ForbiddenProblem
#### HttpApiProblem

```php
use Phpro\ApiProblem\Http\ForbiddenProblem;
use Phpro\ApiProblem\Http\HttpApiProblem;

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

```json
{
"status": 403,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Forbidden",
"detail": "Not authorized to access gold."
"status": 404,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Not found",
"detail": "The book could not be found."
}
````

#### HttpApiProblem
#### ValidationApiProblem

```sh
composer require symfony/validator:^4.1
```

```php
use Phpro\ApiProblem\Http\HttpApiProblem;
use Phpro\ApiProblem\Http\ValidationApiProblem;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;

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

```json
{
"status": 404,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Not found",
"detail": "The book could not be found."
"status": 400,
"type": "https:\/\/symfony.com\/errors\/validation",
"title": "Validation Failed",
"detail": "email: Invalid Email",
"violations": [
{
"propertyPath": "email",
"title": "Invalid email",
"type": "urn:uuid:8615ecd9-afcb-479a-9c78-8bcfe260cf2a"
}
]
}
````

#### NotFoundProblem
#### BadRequestProblem

```php
use Phpro\ApiProblem\Http\NotFoundProblem;
use Phpro\ApiProblem\Http\BadRequestProblem;

new NotFoundProblem('The book with ID 20 could not be found.');
new BadRequestProblem('Bad request. Bad!.');
```

```json
{
"status": 404,
"status": 400,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Not found",
"detail": "The book with ID 20 could not be found."
"title": "Bad Request",
"detail": "Bad request. Bad!"
}
````

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

#### ValidationApiProblem
#### ForbiddenProblem

```sh
composer require symfony/validator:^4.1
```php
use Phpro\ApiProblem\Http\ForbiddenProblem;

new ForbiddenProblem('Not authorized to access gold.');
```

```json
{
"status": 403,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Forbidden",
"detail": "Not authorized to access gold."
}
````

#### NotFoundProblem

```php
use Phpro\ApiProblem\Http\ValidationApiProblem;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Phpro\ApiProblem\Http\NotFoundProblem;

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

```json
{
"status": 400,
"type": "https:\/\/symfony.com\/errors\/validation",
"title": "Validation Failed",
"detail": "email: Invalid Email",
"violations": [
{
"propertyPath": "email",
"title": "Invalid email",
"type": "urn:uuid:8615ecd9-afcb-479a-9c78-8bcfe260cf2a"
}
]
"status": 404,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Not found",
"detail": "The book with ID 20 could not be found."
}
````

#### BadRequestProblem
#### MethodNotAllowedProblem

```php
use Phpro\ApiProblem\Http\BadRequestProblem;
use Phpro\ApiProblem\Http\MethodNotAllowedProblem;

new BadRequestProblem('Bad request. Bad!.');
new MethodNotAllowedProblem('Only POST and GET allowed.');
```

```json
{
"status": 400,
"status": 405,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Bad Request",
"detail": "Bad request. Bad!"
"title": "Method Not Allowed",
"detail": "Only POST and GET allowed."
}
````

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

#### PreconditionFailedProblem

```php
use Phpro\ApiProblem\Http\PreconditionFailedProblem;

new PreconditionFailedProblem('Incorrect entity tag provided.');
```

```json
{
"status": 412,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Precondition Failed",
"detail": "Incorrect entity tag provided."
}
````

#### UnsupportedMediaTypeProblem

```php
use Phpro\ApiProblem\Http\UnsupportedMediaTypeProblem;

new UnsupportedMediaTypeProblem('Please provide valid JSON.');
```

```json
{
"status": 415,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Unsupported Media Type",
"detail": "Please provide valid JSON."
}
````

#### IAmATeapotProblem

```php
use Phpro\ApiProblem\Http\IAmATeapotProblem;

new IAmATeapotProblem('More tea please.');
```

```json
{
"status": 418,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "I'm a teapot",
"detail": "More tea please."
}
````

#### UnprocessableEntityProblem

```php
use Phpro\ApiProblem\Http\UnprocessableEntityProblem;

new UnprocessableEntityProblem('Unable to process the contained instructions.');
```

```json
{
"status": 422,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Unprocessable Entity",
"detail": "Unable to process the contained instructions."
}
````

#### LockedProblem

```php
use Phpro\ApiProblem\Http\LockedProblem;

new LockedProblem('This door is locked.');
```

```json
{
"status": 423,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Locked",
"detail": "This door is locked."
}
````

#### PreconditionRequiredProblem

```php
use Phpro\ApiProblem\Http\PreconditionRequiredProblem;

new PreconditionRequiredProblem('If-match header is required.');
```

```json
{
"status": 428,
"type": "http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html",
"title": "Precondition Required",
"detail": "If-match header is required."
}
````

### Creating your own problem

Creating problem sounds scary right!?
Expand Down
37 changes: 37 additions & 0 deletions spec/Http/IAmATeapotProblemSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace spec\Phpro\ApiProblem\Http;

use Phpro\ApiProblem\Http\HttpApiProblem;
use Phpro\ApiProblem\Http\IAmATeapotProblem;
use PhpSpec\ObjectBehavior;

class IAmATeapotProblemSpec extends ObjectBehavior
{
public function let(): void
{
$this->beConstructedWith('i am a teapot');
}

public function it_is_initializable(): void
{
$this->shouldHaveType(IAmATeapotProblem::class);
}

public function it_is_an_http_api_problem(): void
{
$this->shouldHaveType(HttpApiProblem::class);
}

public function it_can_parse_to_array(): void
{
$this->toArray()->shouldBe([
'status' => 418,
'type' => HttpApiProblem::TYPE_HTTP_RFC,
'title' => HttpApiProblem::getTitleForStatusCode(418),
'detail' => 'i am a teapot',
]);
}
}
Loading

0 comments on commit 10bcce6

Please sign in to comment.