<div dir="ltr">
<p class="">Hi guys - Happy Friday - I have a question:</p><p class="">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?</p><p class=""><br></p><p class="">- is the only mechanism using this stream object?</p><p class=""><br></p><p class="">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?</p><p class=""><br></p><p class="">I want to provide a response to an API command defined in a module via:</p><p class=""><br></p><p class=""><br></p><p class="">#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)</p><p class=""><br></p><p class=""><br></p><p class="">and my understanding (which may be incorrect) is that the stream object can be used to provide a response.</p><p class=""><br></p><p class="">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?</p><p class=""><br></p><p class=""><br></p><p class="">it looks like the stream data is put in the body of the response as per: switch_event_add_body(event, "%s", reply);</p><p class=""><br></p><p class=""><br></p><p class="">the relevant code is in api_exec</p><p class=""><br></p><p class=""><br></p><p class="">static void *SWITCH_THREAD_FUNC api_exec(switch_thread_t *thread, void *obj)</p><p class="">{</p><p class=""><br></p><p class=""> struct api_command_struct *acs = (struct api_command_struct *) obj;</p><p class=""> switch_stream_handle_t stream = { 0 };</p><p class=""> char *reply, *freply = NULL;</p><p class=""> switch_status_t status;</p><p class=""><br></p><p class=""> switch_mutex_lock(globals.listener_mutex);</p><p class=""> prefs.threads++;</p><p class=""> switch_mutex_unlock(globals.listener_mutex);</p><p class=""><br></p><p class=""><br></p><p class=""> if (!acs) {</p><p class=""> switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Internal error.\n");</p><p class=""> goto cleanup;</p><p class=""> }</p><p class=""><br></p><p class=""> if (!acs->listener || !switch_test_flag(acs->listener, LFLAG_RUNNING) ||</p><p class=""> !acs->listener->rwlock || switch_thread_rwlock_tryrdlock(acs->listener->rwlock) != SWITCH_STATUS_SUCCESS) {</p><p class=""> switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! cannot get read lock.\n");</p><p class=""> acs->ack = -1;</p><p class=""> goto done;</p><p class=""> }</p><p class=""><br></p><p class=""> acs->ack = 1;</p><p class=""><br></p><p class=""> SWITCH_STANDARD_STREAM(stream);</p><p class=""><br></p><p class=""> if (acs->console_execute) {</p><p class=""> if ((status = switch_console_execute(acs->api_cmd, 0, &stream)) != SWITCH_STATUS_SUCCESS) {</p><p class=""> stream.write_function(&stream, "-ERR %s Command not found!\n", acs->api_cmd);</p><p class=""> }</p><p class=""> } else {</p><p class=""> status = switch_api_execute(acs->api_cmd, acs->arg, NULL, &stream);</p><p class=""> }</p><p class=""><br></p><p class=""> if (status == SWITCH_STATUS_SUCCESS) {</p><p class=""> reply = stream.data;</p><p class=""> } else {</p><p class=""> freply = switch_mprintf("-ERR %s Command not found!\n", acs->api_cmd);</p><p class=""> reply = freply;</p><p class=""> }</p><p class=""><br></p><p class=""> if (!reply) {</p><p class=""> reply = "Command returned no output!";</p><p class=""> }</p><p class=""><br></p><p class=""> if (acs->bg) {</p><p class=""> switch_event_t *event;</p><p class=""><br></p><p class=""> if (switch_event_create(&event, SWITCH_EVENT_BACKGROUND_JOB) == SWITCH_STATUS_SUCCESS) {</p><p class=""> switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-UUID", acs->uuid_str);</p><p class=""> switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command", acs->api_cmd);</p><p class=""> if (acs->arg) {</p><p class=""> switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command-Arg", acs->arg);</p><p class=""> }</p><p class=""> switch_event_add_body(event, "%s", reply);</p><p class=""> switch_event_fire(&event);</p><p class=""> }</p><p class=""> } else {</p><p class=""> switch_size_t rlen, blen;</p><p class=""> char buf[1024] = "";</p><p class=""><br></p><p class=""> if (!(rlen = strlen(reply))) {</p><p class=""> reply = "-ERR no reply\n";</p><p class=""> rlen = strlen(reply);</p><p class=""> }</p><p class=""><br></p><p class=""> switch_snprintf(buf, sizeof(buf), "Content-Type: api/response\nContent-Length: %" SWITCH_SSIZE_T_FMT "\n\n", rlen);</p><p class=""> blen = strlen(buf);</p><p class=""> switch_socket_send(acs->listener->sock, buf, &blen);</p><p class=""> switch_socket_send(acs->listener->sock, reply, &rlen);</p><p class=""> }</p><p class=""><br></p><p class=""> switch_safe_free(stream.data);</p><p class=""> switch_safe_free(freply);</p><p class=""><br></p><p class=""> if (acs->listener->rwlock) {</p><p class=""> switch_thread_rwlock_unlock(acs->listener->rwlock);</p><p class=""> }</p><p class=""><br></p><p class="">Thanks, as ever, for your help,</p><p class="">chris</p><p class=""><br></p>
</div>