Skip to content

Commit

Permalink
Merge pull request #10 from FireTail-io/feat-log-format-updated
Browse files Browse the repository at this point in the history
Added support for custom content type handling
  • Loading branch information
rileyfiretail authored Nov 24, 2022
2 parents 3192e85 + da9842f commit 8533e81
Show file tree
Hide file tree
Showing 173 changed files with 22,635 additions and 18,844 deletions.
16 changes: 16 additions & 0 deletions examples/openapi3/enforcedefaults_aiohttp/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
========================
Custom Validator Example
========================

In this example we fill-in non-provided properties with their defaults.
Validator code is based on example from `python-jsonschema docs`_.

Running:

.. code-block:: bash
$ ./enforcedefaults.py
Now open your browser and go to http://localhost:8080/v1/ui/ to see the Swagger
UI. If you send a ``POST`` request with empty body ``{}``, you should receive
echo with defaults filled-in.
39 changes: 39 additions & 0 deletions examples/openapi3/enforcedefaults_aiohttp/enforcedefaults-api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
openapi: '3.0.0'
info:
version: '1'
title: Custom Validator Example
servers:
- url: http://localhost:8080/{basePath}
variables:
basePath:
default: api
paths:
/echo:
post:
description: Echo passed data
operationId: enforcedefaults.echo
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Data'
responses:
'200':
description: Data with defaults filled in by validator
default:
description: Unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Data:
type: object
properties:
foo:
type: string
default: foo
Error:
type: string
56 changes: 56 additions & 0 deletions examples/openapi3/enforcedefaults_aiohttp/enforcedefaults.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env python3

import firetail
import jsonschema
import six
from firetail.decorators.validation import RequestBodyValidator
from firetail.json_schema import Draft4RequestValidator


async def echo(body):
return body


# via https://python-jsonschema.readthedocs.io/
def extend_with_set_default(validator_class):
validate_properties = validator_class.VALIDATORS['properties']

def set_defaults(validator, properties, instance, schema):
for property, subschema in six.iteritems(properties):
if 'default' in subschema:
instance.setdefault(property, subschema['default'])

for error in validate_properties(
validator, properties, instance, schema):
yield error

return jsonschema.validators.extend(
validator_class, {'properties': set_defaults})

DefaultsEnforcingDraft4Validator = extend_with_set_default(Draft4RequestValidator)


class DefaultsEnforcingRequestBodyValidator(RequestBodyValidator):
def __init__(self, *args, **kwargs):
super(DefaultsEnforcingRequestBodyValidator, self).__init__(
*args, validator=DefaultsEnforcingDraft4Validator, **kwargs)


validator_map = {
'body': DefaultsEnforcingRequestBodyValidator
}


if __name__ == '__main__':
app = firetail.AioHttpApp(
__name__,
port=8080,
specification_dir='.',
options={'swagger_ui': True}
)
app.add_api(
'enforcedefaults-api.yaml',
arguments={'title': 'Hello World Example'},
validator_map=validator_map,
)
app.run()
11 changes: 11 additions & 0 deletions examples/openapi3/helloworld_aiohttp/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
===================
Hello World Example
===================

Running:

.. code-block:: bash
$ ./hello.py
Now open your browser and go to http://localhost:9090/v1.0/ui/ to see the Swagger UI.
14 changes: 14 additions & 0 deletions examples/openapi3/helloworld_aiohttp/hello.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env python3

import firetail
from aiohttp import web


async def post_greeting(name):
return web.Response(text=f'Hello {name}')


if __name__ == '__main__':
app = firetail.AioHttpApp(__name__, port=9090, specification_dir='openapi/')
app.add_api('helloworld-api.yaml', arguments={'title': 'Hello World Example'})
app.run()
30 changes: 30 additions & 0 deletions examples/openapi3/helloworld_aiohttp/openapi/helloworld-api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
openapi: "3.0.0"

info:
title: Hello World
version: "1.0"
servers:
- url: http://localhost:9090/v1.0

paths:
/greeting/{name}:
post:
summary: Generate greeting
description: Generates a greeting message.
operationId: hello.post_greeting
responses:
200:
description: greeting response
content:
text/plain:
schema:
type: string
example: "hello dave!"
parameters:
- name: name
in: path
description: Name of the person to greet.
required: true
schema:
type: string
example: "dave"
58 changes: 58 additions & 0 deletions examples/openapi3/reverseproxy_aiohttp/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
=====================
Reverse Proxy Example
=====================

This example demonstrates how to run a firetail application behind a path-altering reverse proxy.

You can either set the path in your app, or set the ``X-Forwarded-Path`` header.

Running:

.. code-block:: bash
$ sudo pip3 install --upgrade firetail[swagger-ui] aiohttp-remotes
$ ./app.py
Now open your browser and go to http://localhost:8080/reverse_proxied/ui/ to see the Swagger UI.


You can also use the ``X-Forwarded-Path`` header to modify the reverse proxy path.
For example:

.. code-block:: bash
curl -H "X-Forwarded-Path: /banana/" http://localhost:8080/openapi.json
{
"servers" : [
{
"url" : "banana"
}
],
"paths" : {
"/hello" : {
"get" : {
"responses" : {
"200" : {
"description" : "hello",
"content" : {
"text/plain" : {
"schema" : {
"type" : "string"
}
}
}
}
},
"operationId" : "app.hello",
"summary" : "say hi"
}
}
},
"openapi" : "3.0.0",
"info" : {
"version" : "1.0",
"title" : "Path-Altering Reverse Proxy Example"
}
}
82 changes: 82 additions & 0 deletions examples/openapi3/reverseproxy_aiohttp/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env python3
'''
example of aiohttp firetail running behind a path-altering reverse-proxy
'''

import json
import logging

import firetail
from aiohttp import web
from aiohttp_remotes.exceptions import RemoteError, TooManyHeaders
from aiohttp_remotes.x_forwarded import XForwardedBase
from yarl import URL

X_FORWARDED_PATH = "X-Forwarded-Path"


class XPathForwarded(XForwardedBase):

def __init__(self, num=1):
self._num = num

def get_forwarded_path(self, headers):
forwarded_host = headers.getall(X_FORWARDED_PATH, [])
if len(forwarded_host) > 1:
raise TooManyHeaders(X_FORWARDED_PATH)
return forwarded_host[0] if forwarded_host else None

@web.middleware
async def middleware(self, request, handler):
logging.warning(
"this demo is not secure by default!! "
"You'll want to make sure these headers are coming from your proxy, "
"and not directly from users on the web!"
)
try:
overrides = {}
headers = request.headers

forwarded_for = self.get_forwarded_for(headers)
if forwarded_for:
overrides['remote'] = str(forwarded_for[-self._num])

proto = self.get_forwarded_proto(headers)
if proto:
overrides['scheme'] = proto[-self._num]

host = self.get_forwarded_host(headers)
if host is not None:
overrides['host'] = host

prefix = self.get_forwarded_path(headers)
if prefix is not None:
prefix = '/' + prefix.strip('/') + '/'
request_path = URL(request.path.lstrip('/'))
overrides['rel_url'] = URL(prefix).join(request_path)

request = request.clone(**overrides)

return await handler(request)
except RemoteError as exc:
exc.log(request)
await self.raise_error(request)


def hello(request):
ret = {
"host": request.host,
"scheme": request.scheme,
"path": request.path,
"_href": str(request.url)
}
return web.Response(text=json.dumps(ret), status=200)


if __name__ == '__main__':
app = firetail.AioHttpApp(__name__)
app.add_api('openapi.yaml', pass_context_arg_name='request')
aio = app.app
reverse_proxied = XPathForwarded()
aio.middlewares.append(reverse_proxied.middleware)
app.run(port=8080)
38 changes: 38 additions & 0 deletions examples/openapi3/reverseproxy_aiohttp/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
worker_processes 1;
error_log stderr;
daemon off;
pid nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

sendfile on;

keepalive_timeout 65;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
access_log access.log;
server {

listen localhost:9000;

location /reverse_proxied/ {
# Define the location of the proxy server to send the request to
proxy_pass http://localhost:8080/;
# Add prefix header
proxy_set_header X-Forwarded-Path /reverse_proxied/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto http;
}

}
}
18 changes: 18 additions & 0 deletions examples/openapi3/reverseproxy_aiohttp/openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
openapi: 3.0.0
info:
title: Path-Altering Reverse Proxy Example
version: '1.0'
servers:
- url: /api
paths:
/hello:
get:
summary: say hi
operationId: app.hello
responses:
'200':
description: hello
content:
text/plain:
schema:
type: string
14 changes: 14 additions & 0 deletions examples/swagger2/basicauth/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
=======================
HTTP Basic Auth Example
=======================

Running:

.. code-block:: bash
$ sudo pip3 install --upgrade firetail[swagger-ui] # install Firetail from PyPI
$ ./app.py
Now open your browser and go to http://localhost:8080/ui/ to see the Swagger UI.

The hardcoded credentials are ``admin:secret`` and ``foo:bar``.
Loading

0 comments on commit 8533e81

Please sign in to comment.