httpd: expose http_send_headers to be used in CGI handlers
This commit is contained in:
parent
36d4bfa774
commit
d548803d38
@ -192,12 +192,83 @@ EXTERN const int g_httpd_numfiles;
|
|||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: httpd_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function initializes the web server and should be called at system
|
||||||
|
* boot-up.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
void httpd_init(void);
|
void httpd_init(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: httpd_listen
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This is the main processing thread for the webserver. It never returns
|
||||||
|
* unless an error occurs
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
int httpd_listen(void);
|
int httpd_listen(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: httpd_cgi_register
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Register a CGI handler
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
void httpd_cgi_register(struct httpd_cgi_call *cgi_call);
|
void httpd_cgi_register(struct httpd_cgi_call *cgi_call);
|
||||||
uint16_t httpd_fs_count(char *name);
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: httpd_send_datachunk
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Sends a chunk of HTML data using either chunked or non-chunked encoding.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* sockfd Socket to which to send the data.
|
||||||
|
* data Data to send
|
||||||
|
* len Length of data to send
|
||||||
|
* chunked If True, sends an HTTP Chunked-Encoding prolog before the data
|
||||||
|
* block, and a HTTP Chunked-Encoding epilog ("\r\n") after the
|
||||||
|
* data block. If False, just sends the data.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* On success, returns >=0. On failure, returns a negative number
|
||||||
|
* indicating the failure code.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
int httpd_send_datachunk(int sockfd, void *data, int len, bool chunked);
|
int httpd_send_datachunk(int sockfd, void *data, int len, bool chunked);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: httpd_send_headers
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Sends HTTP headers
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* pstate The httpd state
|
||||||
|
* status Numeric HTTP status code
|
||||||
|
* len Length of data to be sent in subsequent send
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* On success, returns >=0. On failure, returns a negative number
|
||||||
|
* indicating the failure code.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int httpd_send_headers(struct httpd_state *pstate, int status, int len);
|
||||||
|
|
||||||
|
#ifdef CONFIG_NETUTILS_HTTPDFSSTATS
|
||||||
|
uint16_t httpd_fs_count(char *name);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NETUTILS_HTTPD_DIRLIST
|
#ifdef CONFIG_NETUTILS_HTTPD_DIRLIST
|
||||||
bool httpd_is_file(FAR const char *filename);
|
bool httpd_is_file(FAR const char *filename);
|
||||||
ssize_t httpd_dirlist(int outfd, FAR struct httpd_fs_file *file);
|
ssize_t httpd_dirlist(int outfd, FAR struct httpd_fs_file *file);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* netutils/webserver/httpd.c
|
* apps/netutils/webserver/httpd.c
|
||||||
* httpd Web server
|
* httpd Web server
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
|
||||||
@ -192,76 +192,6 @@ static int httpd_close(struct httpd_fs_file *file)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: httpd_send_datachunk
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Sends a chunk of HTML data using either chunked or non-chunked encoding.
|
|
||||||
*
|
|
||||||
* Input Parameters:
|
|
||||||
* sockfd Socket to which to send the data.
|
|
||||||
* data Data to send
|
|
||||||
* len Length of data to send
|
|
||||||
* chunked If True, sends an HTTP Chunked-Encoding prolog before the data
|
|
||||||
* block, and a HTTP Chunked-Encoding epilog ("\r\n") after the
|
|
||||||
* data block. If False, just sends the data.
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* On success, returns >=0. On failure, returns a negative number
|
|
||||||
* indicating the failure code.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
int httpd_send_datachunk(int sockfd, void *data, int len, bool chunked)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
#if defined(CONFIG_NETUTILS_HTTPD_ENABLE_CHUNKED_ENCODING)
|
|
||||||
char chunked_info[HTTPD_MAX_CHUNKEDLEN];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_NETUTILS_HTTPD_ENABLE_CHUNKED_ENCODING)
|
|
||||||
/* Chunk prolog */
|
|
||||||
|
|
||||||
if (chunked)
|
|
||||||
{
|
|
||||||
int chunked_info_len = snprintf(chunked_info, HTTPD_MAX_CHUNKEDLEN,
|
|
||||||
"%X\r\n", len);
|
|
||||||
ret = send(sockfd, chunked_info, chunked_info_len, 0);
|
|
||||||
DEBUGASSERT(ret == chunked_info_len);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ret >= 0)
|
|
||||||
{
|
|
||||||
if (len == 0)
|
|
||||||
{
|
|
||||||
/* Lower layer does not tolerate buf = NULL even if len = 0
|
|
||||||
* so just pass a dummy pointer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
data = &len;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = send(sockfd, data, len, 0);
|
|
||||||
DEBUGASSERT(ret == len);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_NETUTILS_HTTPD_ENABLE_CHUNKED_ENCODING)
|
|
||||||
/* Chunk epilog */
|
|
||||||
|
|
||||||
if (ret >= 0)
|
|
||||||
{
|
|
||||||
if (chunked)
|
|
||||||
{
|
|
||||||
ret = send(sockfd, "\r\n", 2, 0);
|
|
||||||
DEBUGASSERT(ret == 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_NETUTILS_HTTPD_DUMPBUFFER
|
#ifdef CONFIG_NETUTILS_HTTPD_DUMPBUFFER
|
||||||
static void httpd_dumpbuffer(FAR const char *msg, FAR const char *buffer,
|
static void httpd_dumpbuffer(FAR const char *msg, FAR const char *buffer,
|
||||||
unsigned int nbytes)
|
unsigned int nbytes)
|
||||||
@ -440,153 +370,6 @@ static int send_chunk(struct httpd_state *pstate, const char *buf, int len)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_headers(struct httpd_state *pstate, int status, int len)
|
|
||||||
{
|
|
||||||
const char *mime;
|
|
||||||
const char *ptr;
|
|
||||||
char contentlen[HTTPD_MAX_CONTENTLEN] =
|
|
||||||
{
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
char header[HTTPD_MAX_HEADERLEN];
|
|
||||||
int hdrlen;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
static const struct
|
|
||||||
{
|
|
||||||
const char *ext;
|
|
||||||
const char *mime;
|
|
||||||
}
|
|
||||||
|
|
||||||
a[] =
|
|
||||||
{
|
|
||||||
#ifndef CONFIG_NETUTILS_HTTPD_SCRIPT_DISABLE
|
|
||||||
{
|
|
||||||
"shtml", "text/html"
|
|
||||||
},
|
|
||||||
#endif
|
|
||||||
|
|
||||||
{
|
|
||||||
"html", "text/html"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"css", "text/css"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"txt", "text/plain"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"js", "text/javascript"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"png", "image/png"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"gif", "image/gif"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"jpeg", "image/jpeg"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"jpg", "image/jpeg"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"mp3", "audio/mpeg"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ptr = strrchr(pstate->ht_filename, ISO_PERIOD);
|
|
||||||
if (ptr == NULL)
|
|
||||||
{
|
|
||||||
mime = "application/octet-stream";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mime = "text/plain";
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof a / sizeof *a; i++)
|
|
||||||
{
|
|
||||||
if (strncmp(a[i].ext, ptr + 1, strlen(a[i].ext)) == 0)
|
|
||||||
{
|
|
||||||
mime = a[i].mime;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_NETUTILS_HTTPD_DIRLIST
|
|
||||||
if (false == httpd_is_file(pstate->ht_filename))
|
|
||||||
{
|
|
||||||
/* we assume that it's a directory */
|
|
||||||
|
|
||||||
mime = "text/html";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (len >= 0)
|
|
||||||
{
|
|
||||||
snprintf(contentlen, HTTPD_MAX_CONTENTLEN,
|
|
||||||
"Content-Length: %d\r\n", len);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifndef CONFIG_NETUTILS_HTTPD_KEEPALIVE_DISABLE
|
|
||||||
/* Length unknown ahead of time */
|
|
||||||
|
|
||||||
pstate->ht_keepalive = false;
|
|
||||||
#endif
|
|
||||||
#if defined(CONFIG_NETUTILS_HTTPD_ENABLE_CHUNKED_ENCODING)
|
|
||||||
/* Turn on chunked encoding */
|
|
||||||
|
|
||||||
snprintf(contentlen, HTTPD_MAX_CONTENTLEN,
|
|
||||||
"Transfer-Encoding: chunked\r\n");
|
|
||||||
pstate->ht_chunked = true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status == 413)
|
|
||||||
{
|
|
||||||
/* TODO: here we "SHOULD" include a Retry-After header */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Construct the header.
|
|
||||||
*
|
|
||||||
* REVISIT: Wouldn't asprintf be a better option than a large stack
|
|
||||||
* array?
|
|
||||||
*/
|
|
||||||
|
|
||||||
hdrlen = snprintf(header, HTTPD_MAX_HEADERLEN,
|
|
||||||
"HTTP/1.0 %d %s\r\n"
|
|
||||||
#ifndef CONFIG_NETUTILS_HTTPD_SERVERHEADER_DISABLE
|
|
||||||
"Server: uIP/NuttX http://nuttx.org/\r\n"
|
|
||||||
#endif
|
|
||||||
"Connection: %s\r\n"
|
|
||||||
"Content-type: %s\r\n"
|
|
||||||
"%s"
|
|
||||||
"\r\n",
|
|
||||||
status,
|
|
||||||
status >= 400 ? "Error" : "OK",
|
|
||||||
#ifndef CONFIG_NETUTILS_HTTPD_KEEPALIVE_DISABLE
|
|
||||||
pstate->ht_keepalive ? "keep-alive" : "close",
|
|
||||||
#else
|
|
||||||
"close",
|
|
||||||
#endif
|
|
||||||
mime,
|
|
||||||
contentlen
|
|
||||||
);
|
|
||||||
|
|
||||||
return send_chunk(pstate, header, hdrlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int httpd_senderror(struct httpd_state *pstate, int status)
|
static int httpd_senderror(struct httpd_state *pstate, int status)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -611,7 +394,7 @@ static int httpd_senderror(struct httpd_state *pstate, int status)
|
|||||||
|
|
||||||
ret = httpd_openindex(pstate);
|
ret = httpd_openindex(pstate);
|
||||||
|
|
||||||
if (send_headers(pstate, status,
|
if (httpd_send_headers(pstate, status,
|
||||||
ret == OK ? pstate->ht_file.len : sizeof msg - 1) != OK)
|
ret == OK ? pstate->ht_file.len : sizeof msg - 1) != OK)
|
||||||
{
|
{
|
||||||
return ERROR;
|
return ERROR;
|
||||||
@ -682,7 +465,7 @@ static int httpd_sendfile(struct httpd_state *pstate)
|
|||||||
#ifndef CONFIG_NETUTILS_HTTPD_KEEPALIVE_DISABLE
|
#ifndef CONFIG_NETUTILS_HTTPD_KEEPALIVE_DISABLE
|
||||||
pstate->ht_keepalive = false;
|
pstate->ht_keepalive = false;
|
||||||
#endif
|
#endif
|
||||||
if (send_headers(pstate, 200, -1) != OK)
|
if (httpd_send_headers(pstate, 200, -1) != OK)
|
||||||
{
|
{
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -693,13 +476,13 @@ static int httpd_sendfile(struct httpd_state *pstate)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NETUTILS_HTTPD_DIRLIST
|
#ifdef CONFIG_NETUTILS_HTTPD_DIRLIST
|
||||||
if (send_headers(pstate, 200, -1) != OK)
|
if (httpd_send_headers(pstate, 200, -1) != OK)
|
||||||
{
|
{
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (send_headers(pstate, pstate->ht_file.len == 0 ? 204 : 200,
|
if (httpd_send_headers(pstate, pstate->ht_file.len == 0 ? 204 : 200,
|
||||||
pstate->ht_file.len) != OK)
|
pstate->ht_file.len) != OK)
|
||||||
{
|
{
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -1039,13 +822,19 @@ static void single_server(uint16_t portno, pthread_startroutine_t handler,
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: httpd_init
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void httpd_init(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_NETUTILS_HTTPD_CLASSIC
|
||||||
|
httpd_fs_init();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: httpd_listen
|
* Name: httpd_listen
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This is the main processing thread for the webserver. It never returns
|
|
||||||
* unless an error occurs
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int httpd_listen(void)
|
int httpd_listen(void)
|
||||||
@ -1064,17 +853,210 @@ int httpd_listen(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: httpd_init
|
* Name: httpd_send_datachunk
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function initializes the web server and should be called at system
|
|
||||||
* boot-up.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void httpd_init(void)
|
int httpd_send_datachunk(int sockfd, void *data, int len, bool chunked)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_NETUTILS_HTTPD_CLASSIC
|
int ret = 0;
|
||||||
httpd_fs_init();
|
#if defined(CONFIG_NETUTILS_HTTPD_ENABLE_CHUNKED_ENCODING)
|
||||||
|
char chunked_info[HTTPD_MAX_CHUNKEDLEN];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_NETUTILS_HTTPD_ENABLE_CHUNKED_ENCODING)
|
||||||
|
/* Chunk prolog */
|
||||||
|
|
||||||
|
if (chunked)
|
||||||
|
{
|
||||||
|
int chunked_info_len = snprintf(chunked_info, HTTPD_MAX_CHUNKEDLEN,
|
||||||
|
"%X\r\n", len);
|
||||||
|
ret = send(sockfd, chunked_info, chunked_info_len, 0);
|
||||||
|
DEBUGASSERT(ret == chunked_info_len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ret >= 0)
|
||||||
|
{
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
/* Lower layer does not tolerate buf = NULL even if len = 0
|
||||||
|
* so just pass a dummy pointer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
data = &len;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = send(sockfd, data, len, 0);
|
||||||
|
DEBUGASSERT(ret == len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_NETUTILS_HTTPD_ENABLE_CHUNKED_ENCODING)
|
||||||
|
/* Chunk epilog */
|
||||||
|
|
||||||
|
if (ret >= 0)
|
||||||
|
{
|
||||||
|
if (chunked)
|
||||||
|
{
|
||||||
|
ret = send(sockfd, "\r\n", 2, 0);
|
||||||
|
DEBUGASSERT(ret == 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: httpd_send_headers
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int httpd_send_headers(struct httpd_state *pstate, int status, int len)
|
||||||
|
{
|
||||||
|
const char *mime;
|
||||||
|
const char *ptr;
|
||||||
|
char contentlen[HTTPD_MAX_CONTENTLEN] =
|
||||||
|
{
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
char header[HTTPD_MAX_HEADERLEN];
|
||||||
|
int hdrlen;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
static const struct
|
||||||
|
{
|
||||||
|
const char *ext;
|
||||||
|
const char *mime;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[] =
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_NETUTILS_HTTPD_SCRIPT_DISABLE
|
||||||
|
{
|
||||||
|
"shtml", "text/html"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
"html", "text/html"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"css", "text/css"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"txt", "text/plain"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"json", "application/json"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"js", "text/javascript"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"png", "image/png"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"gif", "image/gif"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"jpeg", "image/jpeg"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"jpg", "image/jpeg"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"mp3", "audio/mpeg"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
ptr = strrchr(pstate->ht_filename, ISO_PERIOD);
|
||||||
|
if (ptr == NULL)
|
||||||
|
{
|
||||||
|
mime = "application/octet-stream";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mime = "text/plain";
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof a / sizeof *a; i++)
|
||||||
|
{
|
||||||
|
if (strncmp(a[i].ext, ptr + 1, strlen(a[i].ext)) == 0)
|
||||||
|
{
|
||||||
|
mime = a[i].mime;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NETUTILS_HTTPD_DIRLIST
|
||||||
|
if (false == httpd_is_file(pstate->ht_filename))
|
||||||
|
{
|
||||||
|
/* we assume that it's a directory */
|
||||||
|
|
||||||
|
mime = "text/html";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (len >= 0)
|
||||||
|
{
|
||||||
|
snprintf(contentlen, HTTPD_MAX_CONTENTLEN,
|
||||||
|
"Content-Length: %d\r\n", len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_NETUTILS_HTTPD_KEEPALIVE_DISABLE
|
||||||
|
/* Length unknown ahead of time */
|
||||||
|
|
||||||
|
pstate->ht_keepalive = false;
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_NETUTILS_HTTPD_ENABLE_CHUNKED_ENCODING)
|
||||||
|
/* Turn on chunked encoding */
|
||||||
|
|
||||||
|
snprintf(contentlen, HTTPD_MAX_CONTENTLEN,
|
||||||
|
"Transfer-Encoding: chunked\r\n");
|
||||||
|
pstate->ht_chunked = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == 413)
|
||||||
|
{
|
||||||
|
/* TODO: here we "SHOULD" include a Retry-After header */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct the header.
|
||||||
|
*
|
||||||
|
* REVISIT: Wouldn't asprintf be a better option than a large stack
|
||||||
|
* array?
|
||||||
|
*/
|
||||||
|
|
||||||
|
hdrlen = snprintf(header, HTTPD_MAX_HEADERLEN,
|
||||||
|
"HTTP/1.0 %d %s\r\n"
|
||||||
|
#ifndef CONFIG_NETUTILS_HTTPD_SERVERHEADER_DISABLE
|
||||||
|
"Server: uIP/NuttX http://nuttx.org/\r\n"
|
||||||
|
#endif
|
||||||
|
"Connection: %s\r\n"
|
||||||
|
"Content-type: %s\r\n"
|
||||||
|
"%s"
|
||||||
|
"\r\n",
|
||||||
|
status,
|
||||||
|
status >= 400 ? "Error" : "OK",
|
||||||
|
#ifndef CONFIG_NETUTILS_HTTPD_KEEPALIVE_DISABLE
|
||||||
|
pstate->ht_keepalive ? "keep-alive" : "close",
|
||||||
|
#else
|
||||||
|
"close",
|
||||||
|
#endif
|
||||||
|
mime,
|
||||||
|
contentlen
|
||||||
|
);
|
||||||
|
|
||||||
|
return send_chunk(pstate, header, hdrlen);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* httpd_cgi.c
|
* apps/netutils/webserver/httpd_cgi.c
|
||||||
* Web server script interface
|
* Web server script interface
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*
|
*
|
||||||
@ -58,6 +58,10 @@ struct httpd_cgi_call *cgi_calls = NULL;
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: httpd_cgi_register
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
void httpd_cgi_register(struct httpd_cgi_call *cgi_call)
|
void httpd_cgi_register(struct httpd_cgi_call *cgi_call)
|
||||||
{
|
{
|
||||||
if (cgi_calls == NULL)
|
if (cgi_calls == NULL)
|
||||||
@ -71,6 +75,10 @@ void httpd_cgi_register(struct httpd_cgi_call *cgi_call)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: httpd_cgi
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
httpd_cgifunction httpd_cgi(char *name)
|
httpd_cgifunction httpd_cgi(char *name)
|
||||||
{
|
{
|
||||||
struct httpd_cgi_call *cgi_call = cgi_calls;
|
struct httpd_cgi_call *cgi_call = cgi_calls;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user