cgi: also allow for generic spawn
This commit is contained in:
parent
4a0db7fbf1
commit
66a402cc96
4 changed files with 72 additions and 30 deletions
|
@ -230,7 +230,6 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
int n;
|
||||
#endif
|
||||
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_HTTP:
|
||||
#ifndef LWS_NO_SERVER
|
||||
|
|
|
@ -1249,6 +1249,8 @@ lws_now_secs(void)
|
|||
LWS_VISIBLE int
|
||||
lws_get_socket_fd(struct lws *wsi)
|
||||
{
|
||||
if (!wsi)
|
||||
return -1;
|
||||
return wsi->desc.sockfd;
|
||||
}
|
||||
|
||||
|
@ -2511,8 +2513,8 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
cgi->stdwsi[n]->cgi_channel = n;
|
||||
cgi->stdwsi[n]->vhost = wsi->vhost;
|
||||
|
||||
// lwsl_err("%s: cgi %p: pipe fd %d -> fd %d / %d\n", __func__, wsi, n,
|
||||
// cgi->pipe_fds[n][!!(n == 0)], cgi->pipe_fds[n][!(n == 0)]);
|
||||
lwsl_debug("%s: cgi %p: pipe fd %d -> fd %d / %d\n", __func__, cgi->stdwsi[n], n,
|
||||
cgi->pipe_fds[n][!!(n == 0)], cgi->pipe_fds[n][!(n == 0)]);
|
||||
|
||||
/* read side is 0, stdin we want the write side, others read */
|
||||
cgi->stdwsi[n]->desc.sockfd = cgi->pipe_fds[n][!!(n == 0)];
|
||||
|
@ -2540,7 +2542,8 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
cgi->stdwsi[LWS_STDOUT]->desc.sockfd,
|
||||
cgi->stdwsi[LWS_STDERR]->desc.sockfd);
|
||||
|
||||
lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, timeout_secs);
|
||||
if (timeout_secs)
|
||||
lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, timeout_secs);
|
||||
|
||||
/* the cgi stdout is always sending us http1.x header data first */
|
||||
wsi->hdr_state = LCHS_HEADER;
|
||||
|
@ -2569,15 +2572,18 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
"GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE",
|
||||
};
|
||||
|
||||
for (m = 0; m < ARRAY_SIZE(meths); m++)
|
||||
if (lws_hdr_total_length(wsi, meths[m]) >=
|
||||
script_uri_path_len) {
|
||||
uritok = meths[m];
|
||||
break;
|
||||
}
|
||||
if (script_uri_path_len >= 0)
|
||||
for (m = 0; m < ARRAY_SIZE(meths); m++)
|
||||
if (lws_hdr_total_length(wsi, meths[m]) >=
|
||||
script_uri_path_len) {
|
||||
uritok = meths[m];
|
||||
break;
|
||||
}
|
||||
|
||||
if (uritok < 0)
|
||||
if (script_uri_path_len < 0 && uritok < 0)
|
||||
goto bail3;
|
||||
if (script_uri_path_len < 0)
|
||||
uritok = 0;
|
||||
|
||||
lws_snprintf(cgi_path, sizeof(cgi_path) - 1, "REQUEST_URI=%s",
|
||||
lws_hdr_simple_ptr(wsi, uritok));
|
||||
|
@ -2593,7 +2599,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
p += lws_snprintf(p, end - p, "QUERY_STRING=");
|
||||
/* dump the individual URI Arg parameters */
|
||||
m = 0;
|
||||
while (1) {
|
||||
while (script_uri_path_len >= 0) {
|
||||
i = lws_hdr_copy_fragment(wsi, tok, sizeof(tok),
|
||||
WSI_TOKEN_HTTP_URI_ARGS, m);
|
||||
if (i < 0)
|
||||
|
@ -2614,37 +2620,44 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
p--;
|
||||
*p++ = '\0';
|
||||
|
||||
env_array[n++] = p;
|
||||
p += lws_snprintf(p, end - p, "PATH_INFO=%s",
|
||||
lws_hdr_simple_ptr(wsi, uritok) +
|
||||
script_uri_path_len);
|
||||
p++;
|
||||
if (script_uri_path_len >= 0) {
|
||||
env_array[n++] = p;
|
||||
p += lws_snprintf(p, end - p, "PATH_INFO=%s",
|
||||
lws_hdr_simple_ptr(wsi, uritok) +
|
||||
script_uri_path_len);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_REFERER)) {
|
||||
if (script_uri_path_len >= 0 &&
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_REFERER)) {
|
||||
env_array[n++] = p;
|
||||
p += lws_snprintf(p, end - p, "HTTP_REFERER=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_REFERER));
|
||||
p++;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
|
||||
if (script_uri_path_len >= 0 &&
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
|
||||
env_array[n++] = p;
|
||||
p += lws_snprintf(p, end - p, "HTTP_HOST=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
|
||||
p++;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {
|
||||
if (script_uri_path_len >= 0 &&
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {
|
||||
env_array[n++] = p;
|
||||
p += lws_snprintf(p, end - p, "HTTP_COOKIE=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COOKIE));
|
||||
p++;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT)) {
|
||||
if (script_uri_path_len >= 0 &&
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT)) {
|
||||
env_array[n++] = p;
|
||||
p += lws_snprintf(p, end - p, "USER_AGENT=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_USER_AGENT));
|
||||
p++;
|
||||
}
|
||||
if (uritok == WSI_TOKEN_POST_URI) {
|
||||
if (script_uri_path_len >= 0 &&
|
||||
uritok == WSI_TOKEN_POST_URI) {
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
|
||||
env_array[n++] = p;
|
||||
p += lws_snprintf(p, end - p, "CONTENT_TYPE=%s",
|
||||
|
@ -2685,7 +2698,8 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
* Actually having made the env, as a cgi we don't need the ah
|
||||
* any more
|
||||
*/
|
||||
if (lws_header_table_is_in_detachable_state(wsi))
|
||||
if (script_uri_path_len >= 0 &&
|
||||
lws_header_table_is_in_detachable_state(wsi))
|
||||
lws_header_table_detach(wsi, 0);
|
||||
|
||||
/* we are ready with the redirection pipes... run the thing */
|
||||
|
@ -2713,6 +2727,12 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
for (n = 0; n < 3; n++)
|
||||
close(cgi->pipe_fds[n][!(n == 0)]);
|
||||
|
||||
/* inform cgi owner of the child PID */
|
||||
n = user_callback_handle_rxflow(wsi->protocol->callback, wsi,
|
||||
LWS_CALLBACK_CGI_PROCESS_ATTACH,
|
||||
wsi->user_space, NULL, cgi->pid);
|
||||
(void)n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3106,7 +3126,7 @@ handled:
|
|||
n = user_callback_handle_rxflow(wsi->protocol->callback, wsi,
|
||||
LWS_CALLBACK_CGI_TERMINATED,
|
||||
wsi->user_space,
|
||||
(void *)&args, 0);
|
||||
(void *)&args, wsi->cgi->pid);
|
||||
wsi->cgi->pid = -1;
|
||||
if (n && !wsi->cgi->being_closed)
|
||||
lws_close_free_wsi(wsi, 0);
|
||||
|
@ -3251,6 +3271,16 @@ finish_him:
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_cgi_get_stdwsi(struct lws *wsi, enum lws_enum_stdinouterr ch)
|
||||
{
|
||||
if (!wsi->cgi)
|
||||
return NULL;
|
||||
|
||||
return wsi->cgi->stdwsi[ch];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LWS_NO_EXTENSIONS
|
||||
|
|
|
@ -1213,7 +1213,7 @@ enum lws_callback_reasons {
|
|||
* the wsi is closed. Used to, eg, terminate chunking.
|
||||
* The provided `lws_callback_http_dummy()`
|
||||
* handles this and the callback should be directed there if
|
||||
* you use CGI. */
|
||||
* you use CGI. The child PID that terminated is in @len. */
|
||||
LWS_CALLBACK_CGI_STDIN_DATA = 42,
|
||||
/**< CGI: Data is, to be sent to the CGI process stdin, eg from
|
||||
* a POST body. The provided `lws_callback_http_dummy()`
|
||||
|
@ -1389,6 +1389,9 @@ enum lws_callback_reasons {
|
|||
/**< Sent to parent to notify them a child is closing / being
|
||||
* destroyed. @in is the child wsi.
|
||||
*/
|
||||
LWS_CALLBACK_CGI_PROCESS_ATTACH = 70,
|
||||
/**< CGI: Sent when the CGI process is spawned for the wsi. The
|
||||
* @len parameter is the PID of the child process */
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
|
||||
|
@ -5140,7 +5143,7 @@ lws_b64_decode_string(const char *in, char *out, int out_size);
|
|||
* However for most cases, binding the cgi to http in and out, the default
|
||||
* lws implementation already does the right thing.
|
||||
*/
|
||||
#ifdef LWS_WITH_CGI
|
||||
|
||||
enum lws_enum_stdinouterr {
|
||||
LWS_STDIN = 0,
|
||||
LWS_STDOUT = 1,
|
||||
|
@ -5167,13 +5170,14 @@ struct lws_cgi_args {
|
|||
int len; /**< length */
|
||||
};
|
||||
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
/**
|
||||
* lws_cgi: spawn network-connected cgi process
|
||||
*
|
||||
* \param wsi: connection to own the process
|
||||
* \param exec_array: array of "exec-name" "arg1" ... "argn" NULL
|
||||
* \param script_uri_path_len: how many chars on the left of the uri are the path to the cgi
|
||||
* \param script_uri_path_len: how many chars on the left of the uri are the
|
||||
* path to the cgi, or -1 to spawn without URL-related env vars
|
||||
* \param timeout_secs: seconds script should be allowed to run
|
||||
* \param mp_cgienv: pvo list with per-vhost cgi options to put in env
|
||||
*/
|
||||
|
@ -5197,6 +5201,15 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi);
|
|||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cgi_kill(struct lws *wsi);
|
||||
|
||||
/**
|
||||
* lws_cgi_get_stdwsi: get wsi for stdin, stdout, or stderr
|
||||
*
|
||||
* \param wsi: parent wsi that has cgi
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_cgi_get_stdwsi(struct lws *wsi, enum lws_enum_stdinouterr ch);
|
||||
|
||||
#endif
|
||||
///@}
|
||||
|
||||
|
|
|
@ -1418,8 +1418,8 @@ drain:
|
|||
args.stdwsi = &wsi->parent->cgi->stdwsi[0];
|
||||
args.hdr_state = wsi->hdr_state;
|
||||
|
||||
//lwsl_err("CGI LWS_STDOUT waiting wsi %p mode %d state %d\n",
|
||||
// wsi->parent, wsi->parent->mode, wsi->parent->state);
|
||||
lwsl_debug("CGI LWS_STDOUT waiting wsi %p mode %d state %d\n",
|
||||
wsi->parent, wsi->parent->mode, wsi->parent->state);
|
||||
|
||||
if (user_callback_handle_rxflow(
|
||||
wsi->parent->protocol->callback,
|
||||
|
|
Loading…
Add table
Reference in a new issue