📄 httpd.c
字号:
urll = strlen(req->req_url);
if ((index = NutHeapAllocClear(urll + 12)) == 0) {
NutHttpSendError(stream, req, 500);
return;
}
if (urll)
strcpy(index, req->req_url);
if (urll && index[urll - 1] != '/')
strcat(index, "/");
strcat(index, "index.html");
if (http_root) {
filename = NutHeapAlloc(strlen(http_root) + strlen(index) + 1);
strcpy(filename, http_root);
} else {
filename = NutHeapAlloc(strlen(index) + 6);
strcpy(filename, "UROM:");
}
strcat(filename, index);
NutHeapFree(index);
fd = _open(filename, _O_BINARY | _O_RDONLY);
NutHeapFree(filename);
if (fd == -1) {
NutHttpSendError(stream, req, 404);
return;
}
}
file_len = _filelength(fd);
NutHttpSendHeaderTop(stream, req, 200, "Ok");
NutHttpSendHeaderBot(stream, NutGetMimeType(req->req_url), file_len);
if (req->req_method != METHOD_HEAD) {
size = 512;
if ((data = NutHeapAlloc(size)) != 0) {
while (file_len) {
if (file_len < 512L)
size = (int) file_len;
n = _read(fd, data, size);
fwrite(data, 1, n, stream);
file_len -= (long) n;
}
NutHeapFree(data);
}
}
_close(fd);
}
/*!
*
*/
static char *NextWord(char *str)
{
while (*str && *str != ' ' && *str != '\t')
str++;
if (*str)
*str++ = 0;
while (*str == ' ' || *str == '\t')
str++;
return str;
}
/*!
*
*/
static REQUEST *CreateRequestInfo(void)
{
return NutHeapAllocClear(sizeof(REQUEST));
}
/*!
*
*/
static void DestroyRequestInfo(REQUEST * req)
{
if (req->req_url)
NutHeapFree(req->req_url);
if (req->req_query)
NutHeapFree(req->req_query);
if (req->req_type)
NutHeapFree(req->req_type);
if (req->req_cookie)
NutHeapFree(req->req_cookie);
if (req->req_auth)
NutHeapFree(req->req_auth);
if (req->req_agent)
NutHeapFree(req->req_agent);
NutHeapFree(req);
}
/*!
* \brief Register the HTTP server's root directory.
*
* Only one root directory is supported. Subsequent calls will
* override previous settings.
*
* \param path Pathname of the root directory. Must include the
* device name followed by a colon followed by a
* directory path followed by a trailing slash.
*
* \return 0 on success, -1 otherwise.
*/
int NutRegisterHttpRoot(char *path)
{
int len;
if (http_root)
NutHeapFree(http_root);
if (path && (len = strlen(path)) != 0) {
if ((http_root = NutHeapAlloc(len + 1)) != 0)
strcpy(http_root, path);
} else
http_root = 0;
return 0;
}
/*!
* \brief Process the next HTTP request.
*
* Waits for the next HTTP request on an established connection
* and processes it.
*
* \param stream Stream of the socket connection, previously opened for
* binary read and write.
*/
void NutHttpProcessRequest(FILE * stream)
{
REQUEST *req;
char *method;
char *path;
char *line;
char *protocol;
char *cp;
/*
* Parse the first line of the request.
* <method> <path> <protocol>
*/
if ((req = CreateRequestInfo()) == 0)
return;
if ((method = NutHeapAlloc(256)) == 0) {
DestroyRequestInfo(req);
return;
}
fgets(method, 256, stream);
if ((cp = strchr(method, '\r')) != 0)
*cp = 0;
if ((cp = strchr(method, '\n')) != 0)
*cp = 0;
/*
* Parse remaining request headers.
*/
if ((line = NutHeapAlloc(256)) == 0) {
NutHeapFree(method);
DestroyRequestInfo(req);
return;
}
for (;;) {
if (fgets(line, 256, stream) == 0)
break;
if ((cp = strchr(line, '\r')) != 0)
*cp = 0;
if ((cp = strchr(line, '\n')) != 0)
*cp = 0;
if (*line == 0)
break;
if (strncasecmp(line, "Authorization:", 14) == 0) {
if (req->req_auth == 0) {
cp = &line[14];
while (*cp == ' ' || *cp == '\t')
cp++;
if ((req->req_auth = NutHeapAlloc(strlen(cp) + 1)) == 0)
break;
strcpy(req->req_auth, cp);
}
} else if (strncasecmp(line, "Content-Length:", 15) == 0)
req->req_length = 0 /*atoi(&line[15]) */ ;
else if (strncasecmp(line, "Content-Type:", 13) == 0) {
if (req->req_type == 0) {
cp = &line[13];
while (*cp == ' ' || *cp == '\t')
cp++;
if ((req->req_type = NutHeapAlloc(strlen(cp) + 1)) == 0)
break;
strcpy(req->req_type, cp);
}
} else if (strncasecmp(line, "Cookie:", 7) == 0) {
if (req->req_cookie == 0) {
cp = &line[7];
while (*cp == ' ' || *cp == '\t')
cp++;
if ((req->req_cookie = NutHeapAlloc(strlen(cp) + 1)) == 0)
break;
strcpy(req->req_cookie, cp);
}
} else if (strncasecmp(line, "User-Agent:", 11) == 0) {
if (req->req_agent == 0) {
cp = &line[11];
while (*cp == ' ' || *cp == '\t')
cp++;
if ((req->req_agent = NutHeapAlloc(strlen(cp) + 1)) == 0)
break;
strcpy(req->req_agent, cp);
}
}
}
NutHeapFree(line);
path = NextWord(method);
protocol = NextWord(path);
NextWord(protocol);
if (strcasecmp(method, "GET") == 0)
req->req_method = METHOD_GET;
else if (strcasecmp(method, "HEAD") == 0)
req->req_method = METHOD_HEAD;
else if (strcasecmp(method, "POST") == 0)
req->req_method = METHOD_POST;
else {
NutHeapFree(method);
DestroyRequestInfo(req);
NutHttpSendError(stream, req, 501);
return;
}
if (*path == 0 || *protocol == 0) {
NutHeapFree(method);
DestroyRequestInfo(req);
NutHttpSendError(stream, req, 400);
return;
}
req->req_version = 10;
if (strcasecmp(protocol, "HTTP/0.9") == 0)
req->req_version = 9;
if ((cp = strchr(path, '?')) != 0) {
*cp++ = 0;
if ((req->req_query = NutHeapAlloc(strlen(cp) + 1)) == 0) {
NutHeapFree(method);
DestroyRequestInfo(req);
return;
}
strcpy(req->req_query, cp);
}
if ((req->req_url = NutHeapAlloc(strlen(path) + 1)) == 0) {
NutHeapFree(method);
DestroyRequestInfo(req);
return;
}
strcpy(req->req_url, path);
NutHeapFree(method);
if (NutDecodePath(req->req_url) == 0)
NutHttpSendError(stream, req, 400);
else
NutHttpProcessFileRequest(stream, req);
DestroyRequestInfo(req);
}
/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -