Hi guys - Happy Friday - I have a question:
My main question is how can I generate a custom reply event for an api call with custom body and headers for an API method defined in a custom module?
- is the only mechanism using this stream object?
or can you directly create the reply event. and if so, how does the caller receive the reply event and know it corresponds to the API call made?
I want to provide a response to an API command defined in a module via:
#define SWITCH_STANDARD_API(name) static switch_status_t name (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream)
and my understanding (which may be incorrect) is that the stream object can be used to provide a response.
When the API is called, an event is automatically generated which uses the stream object. Is there a way to directly modify the event that is generated in response to an API call? How can I modify the headers and body of the event generated from an API call directly?
it looks like the stream data is put in the body of the response as per: switch_event_add_body(event, "%s", reply);
the relevant code is in api_exec
static void *SWITCH_THREAD_FUNC api_exec(switch_thread_t *thread, void *obj)
{
struct api_command_struct *acs = (struct api_command_struct *) obj;
switch_stream_handle_t stream = { 0 };
char *reply, *freply = NULL;
switch_status_t status;
switch_mutex_lock(globals.listener_mutex);
prefs.threads++;
switch_mutex_unlock(globals.listener_mutex);
if (!acs) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Internal error.\n");
goto cleanup;
}
if (!acs->listener || !switch_test_flag(acs->listener, LFLAG_RUNNING) ||
!acs->listener->rwlock || switch_thread_rwlock_tryrdlock(acs->listener->rwlock) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! cannot get read lock.\n");
acs->ack = -1;
goto done;
}
acs->ack = 1;
SWITCH_STANDARD_STREAM(stream);
if (acs->console_execute) {
if ((status = switch_console_execute(acs->api_cmd, 0, &stream)) != SWITCH_STATUS_SUCCESS) {
stream.write_function(&stream, "-ERR %s Command not found!\n", acs->api_cmd);
}
} else {
status = switch_api_execute(acs->api_cmd, acs->arg, NULL, &stream);
}
if (status == SWITCH_STATUS_SUCCESS) {
reply = stream.data;
} else {
freply = switch_mprintf("-ERR %s Command not found!\n", acs->api_cmd);
reply = freply;
}
if (!reply) {
reply = "Command returned no output!";
}
if (acs->bg) {
switch_event_t *event;
if (switch_event_create(&event, SWITCH_EVENT_BACKGROUND_JOB) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-UUID", acs->uuid_str);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command", acs->api_cmd);
if (acs->arg) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command-Arg", acs->arg);
}
switch_event_add_body(event, "%s", reply);
switch_event_fire(&event);
}
} else {
switch_size_t rlen, blen;
char buf[1024] = "";
if (!(rlen = strlen(reply))) {
reply = "-ERR no reply\n";
rlen = strlen(reply);
}
switch_snprintf(buf, sizeof(buf), "Content-Type: api/response\nContent-Length: %" SWITCH_SSIZE_T_FMT "\n\n", rlen);
blen = strlen(buf);
switch_socket_send(acs->listener->sock, buf, &blen);
switch_socket_send(acs->listener->sock, reply, &rlen);
}
switch_safe_free(stream.data);
switch_safe_free(freply);
if (acs->listener->rwlock) {
switch_thread_rwlock_unlock(acs->listener->rwlock);
}
Thanks, as ever, for your help,
chris