In [ ]:
import sys
sys.path.append('/opt/rhc')
and importing a couple of components.
In [ ]:
import rhc.micro as micro
import rhc.async as async
Connections to HTTP resources can be defined using the
CONNECTION
and RESOURCE
directives in a micro
file.
A simple definition follows.
In [ ]:
p=micro.load_connection([
'CONNECTION placeholder http://jsonplaceholder.typicode.com',
'RESOURCE document /posts/1',
])
Now, make a connection and see what happens.
In [ ]:
async.wait(micro.connection.placeholder.document(_trace=True))
This code performs a GET on http://jsonplaceholder.typicode.com/posts/1
and prints the result.
There are simpler ways to perform this task, like using the wonderful requests
library, but
this solution is designed to perform well in a microservice environment where numerous connections
are being handled simultaneously.
load_connection
The load_connection
helper function
allows for the dynamic loading of connection definitions. In this case, the definition is contained
in a list
, but could also be loaded from a file by specifying the file's name, or by specifying
a dot-separated path to the file in the python code tree.
In a microservice implementation, the connection definitions are included in the
micro
file, or in one of the imported files.
This function is included for experimentation and development.
The CONNECTION
directive provides a name
and a url
for a service. The connection is
added to rhc.micro
, and can be accessed as rhc.micro.connection.{name}
.
Since rhc.micro
is imported as micro
, the rhc
preface is skipped in the example.
All by itself, a CONNECTION
doesn't provide much.
The RESOURCE
directive adds a specific HTTP resource to the most recently specified CONNECTION
.
In this case, the resource name is document
and the path to the resource is /posts/1
;
when combined with the CONNECTION
, the full resource url is
http://jsonplaceholder.typicode.com/posts/1
.
The resource is added to the connection, and can be accessed as
micro.connection.{connection name}.{resource name}
or, specifically,
micro.connection.placeholder.document
.
wait
The wait
helper function starts a connection to the resource and waits until
it is done, printing the result.
This hints at the asynchronous activity underpinning micro.connection
, which
will become more apparent in subsequent examples.
In a microservice, the wait
function is never used, since it would cause the
entire service to block until wait
completes.
This function is included for testing and development.
In [ ]:
micro.load_connection([
'CONNECTION placeholder http://jsonplaceholder.typicode.com',
'RESOURCE document /posts/{document_id}',
])
which adds a required argument to the micro.connection.placeholder.document
function.
Now the wait
call looks like this:
In [ ]:
async.wait(micro.connection.placeholder.document(1))
In [ ]:
micro.load_connection([
'CONNECTION placeholder http://jsonplaceholder.typicode.com',
'RESOURCE document /posts/{document_id} trace=true',
])
This will log the entire HTTP document when it is sent, making it easy for us to see what is going on. Make sure to enable debug logging, by doing something like the following:
In [ ]:
import logging
logging.basicConfig(level=logging.DEBUG)
Note: In a production microservice, you should never use trace=debug
. Documents
often contain sensitive information that you don't want to end
up in logs.
A json document will be assembled from the keyword arguments to
micro.connection.placeholder.document
. Try running the example with this
wait
call:
In [ ]:
async.wait(micro.connection.placeholder.document('1', a=1, b=2))
In [ ]:
micro.load_connection([
'CONNECTION placeholder http://jsonplaceholder.typicode.com',
'RESOURCE document /posts/{document_number} trace=true',
'REQUIRED first_name',
'OPTIONAL planet default=earth',
])
The document
resource now has two required arguments: document_id
from
the path and first_name
from the REQUIRED
directive.
If the optional argument planet
is not supplied, it will use the default value
of earth
.
Run the example with this wait
call:
In [ ]:
async.wait(micro.connection.placeholder.document(1, 2))
Note: path
substitutions come first, in left-to-right order as
encountered in the path, followed, in order, by each REQUIRED
argument.
OPTIONAL
arguments, if specified, can be in any order.