Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/parsing openapi #18612

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions w3af/core/data/parsers/doc/open_api/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ def get_uri(self):
continue

if param_def.param_spec['type'] == 'array':
if not parameters[param_name] and not param_def.required:
continue
parameters[param_name] = parameters[param_name][0]

if parameters:
Expand Down
4 changes: 2 additions & 2 deletions w3af/core/data/parsers/doc/open_api/specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

"""
import json
import yaml
import logging

from yaml import load
Expand Down Expand Up @@ -232,7 +231,8 @@ def _load_spec_dict(self):
:return: The dict with the open api data
"""
try:
spec_dict = json.loads(self.http_response.body)
decoded_response = self.http_response.body.decode('ascii', 'ignore')
spec_dict = json.loads(decoded_response)
except ValueError:
# Seems like the OpenAPI was specified using Yaml instead of
# JSON. Let's parse the Yaml data!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"name": "Swagger API Team"
},
"license": {
"name": "MIT"
}
},
"host": "petstore.swagger.io",
"basePath": "/api",
"schemes": [
"http"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/pets": {
"post": {
"description": "Add multiple pets",
"operationId": "addMultiplePets",
"produces": [
"application/json"
],
"parameters": [
{
"name": "pets",
"in": "query",
"description": "array with pets to add",
"required": false,
"type": "array",
"items": {}
}
],
"responses": {
"200": {
"description": "pet response",
"schema": {
"$ref": "#/definitions/Pet"
}
}
}
}
}
},
"definitions": {
"Pet": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore, special chars: ąęćźżó^żć√≤Ķńå",
"description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"name": "Swagger API Team"
},
"license": {
"name": "MIT"
}
},
"host": "petstore.swagger.io",
"basePath": "/api",
"schemes": [
"http"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/pets": {
"get": {
"description": "Returns all pets from the system that the user has access to",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "A list of pets.",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
}
}
}
}
},
"/pets/{ąęćźżó^żć√≤Ķńå}": {
"get": {
"description": "Let's see if I'll return an error"
}
}
},
"definitions": {
"Pet": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
}
}
}
19 changes: 19 additions & 0 deletions w3af/core/data/parsers/doc/open_api/tests/test_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

"""
import json
import unittest

from w3af.core.data.parsers.doc.url import URL
Expand Down Expand Up @@ -312,6 +313,24 @@ def test_array_with_model_items_param_in_json(self):
self.assertEqual(fuzzable_request.get_headers(), e_headers)
self.assertEqual(fuzzable_request.get_data(), e_data)

def test_array_param_not_required_in_json(self):
"""
Regression test when param type is array and param is not required.
Param must be in query, not in body.
"""
test_spec_filename = (
'w3af/core/data/parsers/doc/open_api/tests/data/array_not_required_model_items.json'
)
with open(test_spec_filename, 'r') as file_:
specification_as_string = file_.read()

http_response = self.generate_response(specification_as_string)
handler = SpecificationHandler(http_response)
data = [item for item in handler.get_api_information()]
for spec_obj in data:
factory = RequestFactory(*spec_obj)
req = factory.get_fuzzable_request()

def test_model_param_nested_allOf_in_json(self):
specification_as_string = NestedModel().get_specification()
http_response = self.generate_response(specification_as_string)
Expand Down
12 changes: 12 additions & 0 deletions w3af/core/data/parsers/doc/open_api/tests/test_specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,18 @@ def test_parameter_handler_multiple_paths_and_headers(self):
handler = SpecificationHandler(http_response)
self.check_parameter_setting(handler)

def test_specification_handler_can_handle_spec_with_non_ascii_chars(self):
with open(
'w3af/core/data/parsers/doc/open_api/tests/data/swagger-special-chars.json',
) as file_:
spec_as_string = file_.read()
http_response = self.generate_response(spec_as_string)
spec_handler = SpecificationHandler(http_response)
result = spec_handler.get_api_information()
for _ in result:
pass
self.assertFalse(spec_handler._parsing_errors)

def check_parameter_setting(self, spec_handler):
data = [d for d in spec_handler.get_api_information()]
self.assertIsNotNone(data)
Expand Down