Reverse-engineer legacy HTTP APIs
Project description
===============================
httpreverse
===============================
.. image:: https://img.shields.io/pypi/v/httpreverse.svg
:target: https://pypi-hypernode.com/pypi/httpreverse
Tool to help reverse-engineer legacy HTTP APIs.
Rationale and scope
--------------------
This package was born of a need to be able to use multiple different kinds of
existing, undocumented legacy HTTP APIs not following any kind of consistent,
well planned design. It was also thought helpful to be able to add a little bit
of documentation about what those legacy APIs do.
This package is NOT meant for defining new APIs. Use e.g. Swagger for that.
Why then not just use Swagger or some other such tool? They are really meant for
creating new APIs from scratch and as such cater to a bit different use case.
For example they tend to be geared toward the verbose. When reverse-engineering
and documenting existing APIs, all the details are not that important. We just
need to make it easy to use the APIs and be able to add an explanation of what
they do, rather than documenting everything.
The examples hopefully clarify the difference and some of the benefits of this
package.
Note that this package does NOT make HTTP requests using some client library.
That is up to you; use something from the Python standard library, or the
'requests' package, or something asynchronous, whatever.
API specification examples
------------------------
**Simple example**
An example API definition in YAML that specifies two operations for querying
single and double rooms reservations, respectively::
label: Hotel API
description: An API to check room reservations
operations:
list-singlerooms:
label: List single room reservations
description: List all reserved single rooms
request:
method: GET
path: /hotel/reservations
params:
size: single
response:
type: application/json
parser: hotelapi.parseresponse
list-doublerooms:
label: List double room reservations
description: List all reserved double rooms
request:
method: GET
path: /hotel/reservations
params:
size: double
response:
type: application/json
parser: hotelapi.parseresponse
This is similar to how many specification syntaxes express HTTP APIs. Clear,
but often lots of boilerplate and repetition. Let's see how to save some
effort.
**Using Jinja templating for API spec expansion**
The API document can be expanded using Jinja2 templating. Using our room
reservation example, we could generate an API operation for each room size
variation::
operations:
{% for size in sizes %}
list-{{size}}-rooms:
label: List {{size}} room reservations
description: List all reserved {{size}} rooms
request:
method: GET
path: /hotel/reservations
params:
size: {{size}}
{% endfor %}
Given a context such as ``{"sizes":["single", "double"]}``, the
template would generate the two different API operations.
For blunt copying of parts of the YAML document to another place, the standard
YAML anchor/alias mechanism can of course be used as well.
**Templated request specifications**
Besides Jinja templating, a custom templating mechanism is provided for request
and response specification convenience. Here's an example with a ``roomapi``
request that is used to move repetitive request and response specifications into
a common template that is merely referred to from the actual specs::
label: Hotel API
description: An API to check room reservations
templates:
roomapi:
request:
method: GET
path: /hotel/reservations
response:
type: application/json
parser: hotelapi.parseresponse
operations:
list-singlerooms:
label: List single room reservations
description: List all reserved single rooms
template: roomapi
request:
params:
size: single
list-doublerooms:
label: List double room reservations
description: List all reserved double rooms
template: roomapi
request:
params:
size: double
The example illustrates how the request ``size`` parameter has been overriden
in each of the operation specs.
**Simple parametrization**
The API definitions can also be parametrized for convenient run-time use. The
parametrization function accepts an optional context argument that is simply
a dictionary that is used to assign values to all the named parameters found
in the operations. Parameters are prefixed with the dollar sign ('$'). So it
would be possible to also specify a single dynamically invoked operation for
listing the rooms::
operations:
list-rooms:
label: List room reservations
description: List reserved rooms
template: roomapi
request:
params:
size: $size
By passing either ``{"size":"single"}`` or ``{"size": "double"}`` as context,
room size values would then be assigned. More complex parametrizations are
possible using the same simple mechanism::
operations:
add-reservation:
label: Add reservation
description: Add a room reservation
template: roomapi
request:
method: POST
body: {"size": $roomsize, "customers": $customers}
type: application/json
The context would then have to include both the room size and occupants:
``{"roomsize":"double", "customers":["John Doe", "Jane Doe"]}``.
Consult the YAML documentation for what kind of data structures are
possible to express.
If the request body is given and includes either 'json' or 'xml', the request
body data structure can be converted into JSON or XML after parametrization.
=======
History
=======
0.1.0 (2017-02-17)
------------------
* First release on PyPI.
httpreverse
===============================
.. image:: https://img.shields.io/pypi/v/httpreverse.svg
:target: https://pypi-hypernode.com/pypi/httpreverse
Tool to help reverse-engineer legacy HTTP APIs.
Rationale and scope
--------------------
This package was born of a need to be able to use multiple different kinds of
existing, undocumented legacy HTTP APIs not following any kind of consistent,
well planned design. It was also thought helpful to be able to add a little bit
of documentation about what those legacy APIs do.
This package is NOT meant for defining new APIs. Use e.g. Swagger for that.
Why then not just use Swagger or some other such tool? They are really meant for
creating new APIs from scratch and as such cater to a bit different use case.
For example they tend to be geared toward the verbose. When reverse-engineering
and documenting existing APIs, all the details are not that important. We just
need to make it easy to use the APIs and be able to add an explanation of what
they do, rather than documenting everything.
The examples hopefully clarify the difference and some of the benefits of this
package.
Note that this package does NOT make HTTP requests using some client library.
That is up to you; use something from the Python standard library, or the
'requests' package, or something asynchronous, whatever.
API specification examples
------------------------
**Simple example**
An example API definition in YAML that specifies two operations for querying
single and double rooms reservations, respectively::
label: Hotel API
description: An API to check room reservations
operations:
list-singlerooms:
label: List single room reservations
description: List all reserved single rooms
request:
method: GET
path: /hotel/reservations
params:
size: single
response:
type: application/json
parser: hotelapi.parseresponse
list-doublerooms:
label: List double room reservations
description: List all reserved double rooms
request:
method: GET
path: /hotel/reservations
params:
size: double
response:
type: application/json
parser: hotelapi.parseresponse
This is similar to how many specification syntaxes express HTTP APIs. Clear,
but often lots of boilerplate and repetition. Let's see how to save some
effort.
**Using Jinja templating for API spec expansion**
The API document can be expanded using Jinja2 templating. Using our room
reservation example, we could generate an API operation for each room size
variation::
operations:
{% for size in sizes %}
list-{{size}}-rooms:
label: List {{size}} room reservations
description: List all reserved {{size}} rooms
request:
method: GET
path: /hotel/reservations
params:
size: {{size}}
{% endfor %}
Given a context such as ``{"sizes":["single", "double"]}``, the
template would generate the two different API operations.
For blunt copying of parts of the YAML document to another place, the standard
YAML anchor/alias mechanism can of course be used as well.
**Templated request specifications**
Besides Jinja templating, a custom templating mechanism is provided for request
and response specification convenience. Here's an example with a ``roomapi``
request that is used to move repetitive request and response specifications into
a common template that is merely referred to from the actual specs::
label: Hotel API
description: An API to check room reservations
templates:
roomapi:
request:
method: GET
path: /hotel/reservations
response:
type: application/json
parser: hotelapi.parseresponse
operations:
list-singlerooms:
label: List single room reservations
description: List all reserved single rooms
template: roomapi
request:
params:
size: single
list-doublerooms:
label: List double room reservations
description: List all reserved double rooms
template: roomapi
request:
params:
size: double
The example illustrates how the request ``size`` parameter has been overriden
in each of the operation specs.
**Simple parametrization**
The API definitions can also be parametrized for convenient run-time use. The
parametrization function accepts an optional context argument that is simply
a dictionary that is used to assign values to all the named parameters found
in the operations. Parameters are prefixed with the dollar sign ('$'). So it
would be possible to also specify a single dynamically invoked operation for
listing the rooms::
operations:
list-rooms:
label: List room reservations
description: List reserved rooms
template: roomapi
request:
params:
size: $size
By passing either ``{"size":"single"}`` or ``{"size": "double"}`` as context,
room size values would then be assigned. More complex parametrizations are
possible using the same simple mechanism::
operations:
add-reservation:
label: Add reservation
description: Add a room reservation
template: roomapi
request:
method: POST
body: {"size": $roomsize, "customers": $customers}
type: application/json
The context would then have to include both the room size and occupants:
``{"roomsize":"double", "customers":["John Doe", "Jane Doe"]}``.
Consult the YAML documentation for what kind of data structures are
possible to express.
If the request body is given and includes either 'json' or 'xml', the request
body data structure can be converted into JSON or XML after parametrization.
=======
History
=======
0.1.0 (2017-02-17)
------------------
* First release on PyPI.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
httpreverse-0.1.0.tar.gz
(9.2 kB
view details)
Built Distributions
httpreverse-0.1.0-py3.6.egg
(6.7 kB
view details)
File details
Details for the file httpreverse-0.1.0.tar.gz
.
File metadata
- Download URL: httpreverse-0.1.0.tar.gz
- Upload date:
- Size: 9.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d92b794fb3ef11a9bb9bc3fdec93b2e2b6a9f07f4ba0b5b2f3a91d8c1eacf188 |
|
MD5 | 918e9e230d6644e495d8e4c035137154 |
|
BLAKE2b-256 | 3fbdf9f39f2d8d7e0cb044debe20582955bc84f15c8fd7c44edcfdc6653c61c9 |
File details
Details for the file httpreverse-0.1.0-py3.6.egg
.
File metadata
- Download URL: httpreverse-0.1.0-py3.6.egg
- Upload date:
- Size: 6.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 66d2253db0a22aa4dae651f23927ffe806f043d32faa9c33535e8dd23c9a69e4 |
|
MD5 | 24e716b1e4154fe62ca9420191b937a5 |
|
BLAKE2b-256 | 4c4d648596907c7f3a9bfec85451ca4a19061c9cd39897b0eff739a3f2c9dc00 |
File details
Details for the file httpreverse-0.1.0-py2.py3-none-any.whl
.
File metadata
- Download URL: httpreverse-0.1.0-py2.py3-none-any.whl
- Upload date:
- Size: 7.7 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4e4c7db21e68d70a1eef6573ca8a806e84ee459e24cc01c96c8371583f599364 |
|
MD5 | fd7757f592e05cc904257bd1b425b3ea |
|
BLAKE2b-256 | 8f0f23b3cc396f751fd705735330787a07b5c4b1162323911e3b776e802b73df |