server
Routes HTTP Server.
Attributes
mlogger = get_logger(__name__)
module-attribute
REQUEST_HNDLR = handler.RequestHandler()
module-attribute
EVENT_HNDLR = UI.ExternalEvent.Create(REQUEST_HNDLR)
module-attribute
Classes
HttpRequestHandler
Bases: BaseHTTPRequestHandler
HTTP Requests Handler.
Methods:
log_message(message_format, *args)
Log request messages through pyRevit's logger.
do_POST()
do_GET()
do_PUT()
do_DELETE()
do_HEAD()
do_CONNECT()
do_OPTIONS()
do_TRACE()
ThreadedHttpServer
Bases: ThreadingMixIn, HTTPServer
Threaded HTTP server.
Requests are served on threads that are never STA, while pyRevit directs stdout and stderr to its script output console, a WPF window that can only be created on Revit's STA UI thread. An exception escaping one of these threads is printed there and terminates the Revit process, so nothing here may write to stderr and no exception may leave a thread.
Request threads are daemons and are not joined on close, because a request
in flight when the session is reloaded must not hold the host: they are
abandoned with the process, and server_close() runs on whatever thread
collects the server, including a session reload that is waiting on it.
Attributes
allow_reuse_address = True
class-attribute
instance-attribute
daemon_threads = True
class-attribute
instance-attribute
block_on_close = False
class-attribute
instance-attribute
Methods:
handle_error(request, client_address)
Report a failed request without writing to stderr.
See the class docstring for why stderr is unsafe here.
Note
Called outside an except block there is no exception to format,
and IronPython 3's traceback.format_exc() raises on that instead
of returning a placeholder, so the traceback is only formatted when
one is active.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
The request being processed. |
required | |
client_address
|
tuple
|
Client address the request came from. |
required |
Source code in pyrevitlib/pyrevit/routes/server/server.py
process_request_thread(request, client_address)
Serve a request, letting no exception escape the thread.
Stopping the server closes sockets while requests are still in flight, so the per-request cleanup can raise. The inherited implementation leaves that path unguarded, and an exception escaping here terminates Revit for the reason given in the class docstring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
The request to process. |
required | |
client_address
|
tuple
|
Client address the request came from. |
required |
Source code in pyrevitlib/pyrevit/routes/server/server.py
shutdown()
Stop the accept loop, and always release the listening socket.
The socket release is in a finally because the inherited shutdown
waits for the accept loop to acknowledge, which is the step that fails
when the socket is already gone - and a socket left bound is the port a
reloaded session cannot rebind.
Source code in pyrevitlib/pyrevit/routes/server/server.py
RoutesServer(host, port)
Bases: object
Route server thread handler.
It runs an HTTP server on the given host and port.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
host
|
str
|
host |
required |
port
|
int
|
port |
required |
Source code in pyrevitlib/pyrevit/routes/server/server.py
Attributes
server = ThreadedHttpServer((host, port), HttpRequestHandler)
instance-attribute
host = host
instance-attribute
port = port
instance-attribute
server_thread = None
instance-attribute
is_running
property
Check if the accept loop is still up.
Returns:
| Type | Description |
|---|---|
bool
|
True if the server is accepting requests. |
Methods:
start()
Start the accept loop, at most once, on a guarded thread.
Activation starts each server more than once, which left a second
accept loop running against the same socket that nothing tracked and
shutdown never joined. The thread is guarded because an exception
escaping it terminates Revit; see the ThreadedHttpServer docstring.
Source code in pyrevitlib/pyrevit/routes/server/server.py
waitForThread(timeout=5.0)
Join the accept loop thread, reporting a loop that outlives the wait.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timeout
|
float
|
seconds to wait for the accept loop to finish. |
5.0
|
Source code in pyrevitlib/pyrevit/routes/server/server.py
request_shutdown(timeout)
Ask the accept loop to stop, without waiting on it indefinitely.
BaseServer.shutdown sets the shutdown flag and then blocks until the
accept loop acknowledges it, with no timeout of its own. That wait is
the one unbounded step left in a teardown the host runs on a worker
thread, so it is issued on its own daemon thread and given the same
bound as the join that follows. A loop that never acknowledges is
abandoned rather than waited for: the thread is a daemon, and the socket
is closed on the way out either way, which is what stops a wedged loop
in the end.
A failure is contained inside the thread, because an exception leaving a thread is printed to stderr by the runtime, which this class may not do.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timeout
|
float
|
seconds to wait for the loop to acknowledge. |
required |
Source code in pyrevitlib/pyrevit/routes/server/server.py
stop(timeout=5.0)
Stop serving and release the port. Never raises, never waits longer than timeout.
This runs while a session is being reloaded or torn down, so a failure
here would be reported through the output console and, unhandled on a
worker thread, terminate Revit (see ThreadedHttpServer). Every
failure is logged instead.
The two waits share one budget. The shutdown request and the join that
follows are given the time the first one did not use, so a wedged accept
loop delays the reload by at most timeout in total rather than once
per wait.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timeout
|
float
|
seconds to wait, in total, for the accept loop to finish. |
5.0
|