<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, &quot;%s&quot;, 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, &quot;Internal error.\n&quot;);</p><p class="">        goto cleanup;</p><p class="">    }</p><p class=""><br></p><p class="">    if (!acs-&gt;listener || !switch_test_flag(acs-&gt;listener, LFLAG_RUNNING) ||</p><p class="">        !acs-&gt;listener-&gt;rwlock || switch_thread_rwlock_tryrdlock(acs-&gt;listener-&gt;rwlock) != SWITCH_STATUS_SUCCESS) {</p><p class="">        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, &quot;Error! cannot get read lock.\n&quot;);</p><p class="">        acs-&gt;ack = -1;</p><p class="">        goto done;</p><p class="">    }</p><p class=""><br></p><p class="">    acs-&gt;ack = 1;</p><p class=""><br></p><p class="">    SWITCH_STANDARD_STREAM(stream);</p><p class=""><br></p><p class="">    if (acs-&gt;console_execute) {</p><p class="">        if ((status = switch_console_execute(acs-&gt;api_cmd, 0, &amp;stream)) != SWITCH_STATUS_SUCCESS) {</p><p class="">            stream.write_function(&amp;stream, &quot;-ERR %s Command not found!\n&quot;, acs-&gt;api_cmd);</p><p class="">        }</p><p class="">    } else {</p><p class="">        status = switch_api_execute(acs-&gt;api_cmd, acs-&gt;arg, NULL, &amp;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(&quot;-ERR %s Command not found!\n&quot;, acs-&gt;api_cmd);</p><p class="">        reply = freply;</p><p class="">    }</p><p class=""><br></p><p class="">    if (!reply) {</p><p class="">        reply = &quot;Command returned no output!&quot;;</p><p class="">    }</p><p class=""><br></p><p class="">    if (acs-&gt;bg) {</p><p class="">        switch_event_t *event;</p><p class=""><br></p><p class="">        if (switch_event_create(&amp;event, SWITCH_EVENT_BACKGROUND_JOB) == SWITCH_STATUS_SUCCESS) {</p><p class="">            switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, &quot;Job-UUID&quot;, acs-&gt;uuid_str);</p><p class="">            switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, &quot;Job-Command&quot;, acs-&gt;api_cmd);</p><p class="">            if (acs-&gt;arg) {</p><p class="">                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, &quot;Job-Command-Arg&quot;, acs-&gt;arg);</p><p class="">            }</p><p class="">            switch_event_add_body(event, &quot;%s&quot;, reply);</p><p class="">            switch_event_fire(&amp;event);</p><p class="">        }</p><p class="">    } else {</p><p class="">        switch_size_t rlen, blen;</p><p class="">        char buf[1024] = &quot;&quot;;</p><p class=""><br></p><p class="">        if (!(rlen = strlen(reply))) {</p><p class="">            reply = &quot;-ERR no reply\n&quot;;</p><p class="">            rlen = strlen(reply);</p><p class="">        }</p><p class=""><br></p><p class="">        switch_snprintf(buf, sizeof(buf), &quot;Content-Type: api/response\nContent-Length: %&quot; SWITCH_SSIZE_T_FMT &quot;\n\n&quot;, rlen);</p><p class="">        blen = strlen(buf);</p><p class="">        switch_socket_send(acs-&gt;listener-&gt;sock, buf, &amp;blen);</p><p class="">        switch_socket_send(acs-&gt;listener-&gt;sock, reply, &amp;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-&gt;listener-&gt;rwlock) {</p><p class="">        switch_thread_rwlock_unlock(acs-&gt;listener-&gt;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>