controller_api

controller_api exposes MQTT topics over HTTP at /api/:topic, including model calls. Requests use the normal MQTT and model access checks for the current user.

Model calls

The topic can refer to a model. In this case the topic pattern is one of:

  • /api/model/mymodel/get/foo/bar maps to m_mymodel:m_get([ <<"foo">>, <<"bar">> ], Msg, Context)
  • /api/model/mymodel/post/foo/bar maps to m_mymodel:m_post([ <<"foo">>, <<"bar">> ], Msg, Context)
  • /api/model/mymodel/delete/foo/bar maps to m_mymodel:m_delete([ <<"foo">>, <<"bar">> ], Msg, Context)

In all cases, Msg is an MQTT message map, with the payload set to the body of the received request. In case of a GET, HEAD or DELETE the payload is set to a map of the query arguments.

Note that for a POST the payload might not be the complete message as additional query arguments are passed via z_context:get_q(<<"argument_name">>, Context). If the model function is called using MQTT, then all arguments are contained in the payload.

HTTP methods

HTTP methodSupported topics
GETModel get topics and non-model topics.
HEADModel get topics only.
POSTAny topic, including model get, post and delete topics.
DELETEModel delete topics only.
OPTIONSAny topic; does not call the model or publish a message.

A method/topic mismatch returns 400 Bad Request. Known HTTP methods outside this list return 405 Method Not Allowed; unrecognized methods return 501 Not Implemented. The Allow header lists the controller's methods, rather than filtering them for the requested topic.

HEAD executes the model call and returns the same status and headers as GET, without a response body. It still performs authorization and model validation; it does not return success without checking the result. For example, to check whether all sites are running:

curl --head https://example.com/api/model/zotonic_status/get/check

On a site exposing the zotonic_status model, this returns 200 OK when all sites are running, or 500 Internal Server Error when the check fails.

Replies

By default, the controller publishes a message to the topic and waits up to 60 seconds for its response. The response is encoded in the negotiated content type, with JSON as the default. Model errors determine the HTTP status, for example 403 for eacces and 404 for enoent or unknown_path.

With the response_topic query argument, the controller publishes the message and returns without waiting for the model's result. A non-empty value supplies the MQTT response topic; an empty value publishes without a response topic. The HTTP reply then reports the outcome of publishing, not the outcome of the model call.

HEAD rejects any response_topic query argument with 400 Bad Request, including an empty value or a bare ?response_topic. This ensures that HEAD waits for the model's result.

Edit on GitHub