hkarlstrom / openapi-validation-middleware Goto Github PK
View Code? Open in Web Editor NEWPSR-7 and PSR-15 OpenAPI Validation Middleware
License: MIT License
PSR-7 and PSR-15 OpenAPI Validation Middleware
License: MIT License
Hi, man.
I've got this parameter declaration within my OpenAPI schema (full schema here):
components:
parameters:
withAudits:
in: query
name: with_audits
schema:
type: boolean
required: false
but, when I use it within my request, e.g. curl http://localhost/annotations/1?with_audits=true
, I get the following validation error:
# Output of print_r($validator->validateRequest($request, $path, $method, $pathParameters))
Array (
[0] => Array (
[name] => with_audits
[code] => error_type
[value] => true
[in] => query
[expected] => boolean
[used] => string
)
)
Thanks in advance.
Francesco
Hi, I'm wondering whether the Respect/Validation version can be updated to a 2.x release.
https://github.com/Respect/Validation/releases
It includes loads of new types like uuid and base64 which are very helpful!
More info: https://swagger.io/docs/specification/describing-parameters/#query-parameters
Currently these are not validated at all.
Argument 1 passed to HKarlstrom\Middleware\OpenApiValidation::isJsonMediaType() must be of the type string, null given, called in /app/vendor/hkarlstrom/openapi-validation-middleware/src/OpenApiValidation.php on line 275
Can be fixed with coalesce operator.
Hi, man.
I've just added additionalProperties: false
to models of my project (https://github.com/francescozanoni/students-api-php/blob/master/public/openapi.yaml.example).
As expected, when I add additional properties to models (within request body, in this case), request validation fails.
But the returned error is not very clear:
curl -X POST "http://localhost/students/1/annotations" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d "{\"title\":\"My title\",\"content\":\"My body\",\"user_id\":123,\"one_more_property\":\"one more value\"}"
# Output of print_r(OpenApiValidation->validateRequest($request, $path, $method, $pathParameters))
Array (
[0] => Array (
[name] => one_more_property
[code] => error_$schema
[value] => one more value
[in] => body
[schema] => false
)
)
Could the error be made a bit more explicit?
Thanks in advance!
Hi again!
I'm testing the lib with some data and it seems to be accepting an empty array as a valid request regardless some fields from the body are required.
I think the problem is here!
true
by empty()
.$request->getParsedBody()
returns null|array|object
. So I think changing that line toelseif (null !== $requestBodyData && $this->isJsonMediaType($mediaType))
will work.
Thanks!
Hi, man.
Here's what I've found: if I send no body (be aware: not an empty string) to an endpoint where body is required, the following exception is raised:
curl -X POST http://localhost/endpoint
Argument 1 passed to HKarlstrom/Middleware/OpenApiValidation::isJsonMediaType() must be of the type string, null given, called in
hkarlstrom/openapi-validation-middleware/src/OpenApiValidation.php on line 274
hkarlstrom/openapi-validation-middleware/src/OpenApiValidation.php on line 585
Of course I'm aware this cURL request has no meaning: it's just a test.
By reading other issues, I see issues #29 and #31 seem related.
Any questions, here I am!
Thanks in advance.
Francesco
Any plans to implement caching with the library? We have an openapi specification that's over 3 thousand lines already and it's getting 3 seconds only to parse the yaml file on every request.
I can submit a PR for that using PSR-6 standard, any recommendations?
anyOf, oneOf and not in schemas are not supported in the validator yet.
https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/#allof
Hi, man.
Since release 0.3.1 path parameters seem not being validated with HTTP methods POST and PUT anymore.
Here's my test:
correct ID with GET:
curl -X GET "http://localhost/students/1/annotations" -H "accept: application/json"
{
"status_code": 200,
"status": "OK",
"message": "Resource(s) found",
"data": [
{
"id": 1,
"title": "First title",
"content": "First content",
"user_id": 123,
"created_at": "2019-01-01 01:00:00",
"updated_at": "2019-01-01 01:00:00"
}
]
}
incorrect ID (letters instead of digits) with GET, expected validation error:
curl -X GET "http://localhost/students/abc/annotations" -H "accept: application/json"
# Output of print_r(json_decode($response->getBody()->__toString(), true)['errors'])
Array (
[0] => Array (
[name] => id
[code] => error_type
[value] => abc
[in] => path
[expected] => integer
[used] => string
)
)
correct ID with POST:
curl -X POST "http://localhost/students/1/annotations" \
-H "accept: application/json"
-H "Content-Type: application/json"
-d "{\"title\":\"Annotation title\",\"content\":\"Annotation body\",\"user_id\":123}"
{
"status_code": 200,
"status": "OK",
"message": "Resource successfully retrieved/created/modified",
"data": {
"id": 4,
"title": "Annotation title",
"content": "Annotation body",
"user_id": 123,
"created_at": "2019-01-31 11:58:11",
"updated_at": "2019-01-31 11:58:11"
}
}
incorrect ID (letters instead of digits) with POST, unexpected empty validation error list:
curl -X POST "http://localhost/students/abc/annotations"
-H "accept: application/json"
-H "Content-Type: application/json"
-d "{\"title\":\"Annotation title\",\"content\":\"Annotation body\",\"user_id\":123}"
# Output of print_r(json_decode($response->getBody()->__toString(), true)['errors'])
Array (
)
If you need, my OpenAPI schema is always here: https://github.com/francescozanoni/students-api-php/blob/master/public/openapi.yaml.example
I'm quite sure it's related to the latest package release, since it's the only thing I've changed within my project.
Thanks in advance!
Installing PHP 8.0 is prohibited, only 7.x are allowed in the composer.json
.
As title, it's good for us to let this repository be reliable and verified.
We can consider accomplishing this issue. I think we can choose one of following CI building services:
@hkarlstrom, do you have any idea about this?
I just stumbled upon this problem. Looks like nullable validation is not performed correctly.
Specification contains this schema:
"before_sale_price": {
"type": "integer",
"minimum": 0,
"nullable": true,
"description": "A price before discounts applied"
}
When I run the validation process, I get this error:
{
"name": "data.data.0.before_sale_price",
"code": "error_type",
"value": null,
"in": "body",
"expected": "integer",
"used": "null"
}
I think this is related to #8 because canonic JSON Schema supports this format:
"before_sale_price": {
"type": ["integer",null]
},
Do you think I should convert the schema to JSON Schema first here?
Hi there!
I'm trying to send a request with an empty array to an endpoint with required bodyRequest
and I got a required-type error. An empty array is a valid, non-empty body, it has information.
I think the problem is here!
true
by empty()
.$request->getParsedBody()
returns null|array|object
. So I think changing that line toif (null === $requestBodyData && $requestBody->required)
will work.
Thanks!
ERROR: mb_strlen(): Passing null to parameter #1 ($string) of type string is deprecated on line 559 in file /usr/share/nginx/html/vendor/hkarlstrom/openapi-validation-middleware/src/OpenApiValidation.php
Hey!
I wonder if you think the method could be public (just like the other ones: validateResponseHeaders
,validateResponseBody
), so the library can be used not as a middleware but rather as a validation library like this:
$validator = new OpenApiValidation(...);
$validator->validateRequest($request);
It feels that middleware is just a single application for the underlying validator.
There could be more. For example, validating of logged requests & responses.
When I try to validate a response like this one:
responses: {
200: {
description: "Program replaced",
content: {
application/json: {
schema: {
type: "boolean"
},
example: true
}
}
}
}
I traced the error and located in /vendor/hkarlstrom/openapi-validation-middleware/src/OpenApiValidation.php:359
private function validateObject(array $schema, array $value) : array
That method expects to always receive an array. It should be mixed because it could be a dimple string or in my case a simple boolean.
This issue is related to #31 and a proposed solution is offered below.
Hello,
I am testing some calls against a schema that are supposed to fail validation, but they validate without errors.
This would be the simplified schema:
SomeAddress:
type: object
required:
- country
properties:
country:
type: string
SomeCommand:
type: object
required:
- from
properties:
from:
$ref: '#/components/schemas/SomeAddress'
...
requestBodies:
...
schema:
$ref: '.../SomeCommand'
Sending this in a POST as body, I correctly get a "missing country" error:
{
"from": {
"": 1
}
}
But sending this, I get no error and the empty request gets to my application with unexpected empty fields:
{
"from": {
}
}
I have been digging a bit and I've found that this behavior is intentional:
I understand that the problem happens because PHP decodes JSON objects as array, so when it is empty there is no way to tell between {} and [] once it is decoded.
However, this is a great drawback because it allows empty objects to be considered valid although the specification says that an object with required properties MUST be received.
I have a suggestion: let the user decide if they want this behaviour or they want to carry on and signal a validation error when receiving empty objects where required properties are expected.
This would be simply providing an additional option, by default with the current library behavior.
This would be the implementation:
if ($this->options['strictEmptyArrayValidation']) {
if ('error_type' == $err['code'] && empty($err['value']) && 'object' == $err['expected'] && 'array' == $err['used']) {
return [];
}
}
With this change the library would be usable for me.
If you like it, I have the code prepared to open a pull request including this, the option initialization and a new test to cover this option.
Thanks for your time.
Given the following parameters
schema:
{
"name": "filter",
"in": "query",
"style": "deepObject",
"explode": false,
"schema": {
"type": "object",
"properties": {
"status": {
"type": "array",
"items": {
"type": "string",
"enum": ["open", "pending", "needs_attention", "done"]
}
}
}
}
}
I should would expect a query string filter[status]=open,pending
to be parsed as:
[
'filter' => [
'status' => [
'open',
'pending',
]
]
However, it seems that this package does not respect the explode: false
configuration and reports that the status
parameter is a string.
In order to extend OpenApiValidationMiddleware
Hi, man.
This is the standard response of one of my endpoints (a simple GET /students/1
), whereas all fields are required (except phone
, which is not the matter here):
{
"status_code": 200,
"status": "OK",
"message": "Resource successfully retrieved/created/modified",
"data": {
"id": 1,
"first_name": "John",
"last_name": "Doe",
"e_mail": "[email protected]",
"phone": "1234-567890",
"nationality": "UK"
}
}
I've added response validation to my app, via OpenApiValidation->validateResponseBody()
method.
To test the functionality, I've removed "first_name": "John",
from response, but I'm getting this validation error:
{
"name": "data",
"code": "error_allOf",
"value": {
"id": 1,
"last_name": "Doe",
"e_mail": "[email protected]",
"phone": "1234-567890",
"nationality": "UK"
}
}
I expected an error related to first_name
property mandatority, instead.
Was maybe allOf
support added to request validation only?
Thanks once more.
(I suspect you could start hating me...)
Is it possible to support also php7.0?
This issue is for discussion.
Currently, if validation fails we get a general \Exception
instance with a text message. I think it would be beneficial to have multiple exceptions. For example, PathMissedException
is thrown when we make a request to an undocumented path. Along with the type, we can attach the path itself:
throw new PathMissedException($method, $path);
This typed exceptions allows a consumer to write highly customizable logic on top of the package.
For instance
PATCH /event/13/metadata
{"metadata": {}}
And I have:
{
"metadata": {
"type": "object"
}
}
The "is it an object check" should pass for empty arrays just like it does for associative arrays.
Opis/Json-Schema has moved to v2 from v1. In our system when we implemented custom validation it starts failing due to filter_var PHP function. Latest opis/json has made changes that makes it compatible.
When I make a POST to my route using form-data encoding instead of JSON, and I am using the nullable
attribute, and I have set a format, I receive a TypeError.
Argument 1 passed to HKarlstrom\Middleware\OpenApiValidation::checkFormat() must be of the type string, array given, called in /var/www/vendor/hkarlstrom/openapi-validation-middleware/src/OpenApiValidation.php on line 343
#0 /var/www/vendor/hkarlstrom/openapi-validation-middleware/src/OpenApiValidation.php(343): HKarlstrom\Middleware\OpenApiValidation->checkFormat(Array, 'date-time')
MyObject:
required:
- amount
- userId
- methodId
- date
amount:
type: number
userId:
type: integer
methodId:
description: 'Payment Method ID. Set to null to use existing method. Set to ''DD'' for direct debit'
type: string
nullable: true
date:
description: 'Date in ISO 8601 format. Set to null for immediate processing'
type: string
format: date-time
nullable: true
Note this field still could be provided, but allowed to be null. It works fine when submitting a raw json request. https://swagger.io/docs/specification/data-models/data-types/#null
The problem appears to be here:
private function validateProperties(array $properties) : ?array
{
$errors = [];
foreach ($properties as $property) {
if (isset($property->schema->type, $property->schema->format)) {
$this->checkFormat($property->schema->type, $property->schema->format);
object(HKarlstrom\Middleware\OpenApiValidation\Property)[527]
public 'name' => string 'date (length=11)
public 'in' => string 'form-data' (length=9)
public 'required' => boolean false
public 'schema' =>
object(stdClass)[528]
public 'description' => string 'Date in ISO 8601 format. Set to null for immediate processing' (length=66)
public 'type' =>
array (size=2)
0 => string 'string' (length=6)
1 => string 'null' (length=4)
public 'format' => string 'date-time' (length=9)
public 'value' => null```
Hi, I'm wondering if is there any possibility to introduce support for reading multiple files of a split OpenAPI file as the specification supports:
https://swagger.io/docs/specification/using-ref/#allowed-places
Now the validator throws an error:
"Invalid ref: paths\/endpoint.yaml"
The expected behaviour would be to read all files based on the $ref
field where the file path is specified.
Thank you in advance!
I use this repository to verifiy incomming and outgoing json requests and responses.
I want to rework the error output to another json format.
Currently it is, as example:
Error 400:
{
"message": "Request validation failed",
"errors": [
{
"name": "catalogus",
"code": "error_format",
"value": "",
"in": "query",
"type": "string",
"format": "uri"
}
]
}
I tried to catch this error so i can modify the repsonse like this:
$mw = new HKarlstrom\Middleware\OpenApiValidation(__DIR__.'/catalog_openapi.json');
$mw->addFormat('string','duration',new myDurationFormat());
$options = [
'validateRequest'=> false,
'exampleResponse' => true,
'beforeHandler' => function (\Psr\Http\Message\ServerRequestInterface $request, array $errors) : \Psr\Http\Message\ServerRequestInterface {
// Alter request modifiy the json reponse here !!!
echo "tadaaaa"; <- never outputted
return $request;
}
];
And finally in my route:
$app->get('/v1/zaaktypen[/{params:.*}]',\App\Action\ZTCZaaktypenAction::class)->add($mw,$options);
But it never touches the before- or errorHandler.
Any ideas how to get this working?
I have already loaded schema from a file. Now I want to run validator. For that I have to load schema from a file again.
It will be excelent:
/**
* Class HKarlstrom\Middleware\OpenApiValidation.php
* @param string|array $filename
*/
OpenApiValidation::__construct($filename, array $options = [])
So, I can write somthing like this:
$schema = json_decode(file_get_contents($fileName));
$validator = new OpenApiValidation($schema)
Hi man,
I'm trying to validate my requests, but I'm getting this odd error with a PUT request, whereas the object schema to use is made of a allOf composition:
ERROR: Data validation failed for %s {"exception":"[object] (Respect\Validation\Exceptions\ValidationException(code: 0): [
{
"name": "",
"code": "error_allOf",
"value": {
"id": 2,
"first_name": "Jane",
"last_name": "Doe",
"e_mail": "[email protected]",
"phone": "3333-11111111",
"nationality": "IE"
}
}
This is the object schema:
schemas:
NewStudent:
type: object
properties:
first_name:
type: string
minLength: 2
last_name:
type: string
minLength: 2
e_mail:
type: string
phone:
type: string
nationality:
type: string
pattern: '^[A-Z]{2}$'
required:
- first_name
- last_name
- e_mail
- nationality
Student:
allOf:
- $ref: '#/components/schemas/NewStudent'
- type: object
properties:
id:
type: integer
required:
- id
And this is the modified version (no allOf) that works:
schemas:
NewStudent:
type: object
properties:
first_name:
type: string
minLength: 2
last_name:
type: string
minLength: 2
e_mail:
type: string
phone:
type: string
nationality:
type: string
pattern: '^[A-Z]{2}$'
required:
- first_name
- last_name
- e_mail
- nationality
Student:
type: object
properties:
id:
type: integer
first_name:
type: string
minLength: 2
last_name:
type: string
minLength: 2
e_mail:
type: string
phone:
type: string
nationality:
type: string
pattern: '^[A-Z]{2}$'
required:
- id
- first_name
- last_name
- e_mail
- nationality
I am trying to use the lib to validate some headers in the request using Slim 3.12.
This is how the parameter looks like in my openapi
:
components:
parameters:
X-Location-Code:
in: header
name: X-Location-Code
schema:
type: string
pattern: '^[A-Z]{3}$'
required: true
This is my request:
GET /references/en/SIPStatus HTTP/1.1
Host: localhost:8000
X-Location-Code: DIL
And still, I'm getting an error saying that the header X-Location-Code
was not found. I know that Slim converts the header to lowecase and allow to fetch them regardless.
When checking the code, at the OpenApiValidation.php
line 236
, we can see:
$properties[] = Property::fromParameter($p, $values[$p->in][$p->name] ?? null);
But that $values variable doesn't seem to host the headers values.
As it turned out, I am not able to use this package to validate any other media types except JSON (xml, text/plain, binary string are all good media types these days).
Hi man,
the two following requests have exactly the same output, although the incorrect {id} parameter is respectively a body and a path parameter:
PUT http://localhost/students/1
{
"id": "abc",
"first_name": "Jane",
"last_name": "Doe",
"e_mail": "[email protected]",
"phone": "3333-11111111",
"nationality": "IE"
}
PUT http://localhost/students/abc
{
"id": 2,
"first_name": "Jane",
"last_name": "Doe",
"e_mail": "[email protected]",
"phone": "3333-11111111",
"nationality": "IE"
}
Here is the common output, where I think a context flag is missing:
Array (
[message] => Request validation failed
[errors] => Array (
[0] => Array (
[name] => id
[code] => error_type
[value] => abc
[expected] => integer
[used] => string
)
)
)
Thanks in advance once more!
Implemented this middleware and got the following error:
HKarlstrom\Middleware\OpenApiValidation\Exception\MissingFormatException
Message: Missing validator for type=string, format=duration
File:C:\inetpub\wwwroot\zocommongroundapidevelopment\vendor\hkarlstrom\openapi-validation-middleware\src\OpenApiValidation.php
Does the format: duration needs to be inlemented?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.