123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /*
- file.c -- File handler
- This module serves static file documents
- */
- /********************************* Includes ***********************************/
- #include "goahead.h"
- /*********************************** Locals ***********************************/
- static char *websIndex; /* Default page name */
- static char *websDocuments; /* Default Web page directory */
- /**************************** Forward Declarations ****************************/
- static void fileWriteEvent(Webs *wp);
- /*********************************** Code *************************************/
- /*
- Serve static files
- Return true to indicate the request was handled, even for errors.
- */
- static bool fileHandler(Webs *wp)
- {
- WebsFileInfo info;
- char *tmp, *date;
- ssize nchars;
- int code;
- assert(websValid(wp));
- assert(wp->method);
- assert(wp->filename && wp->filename[0]);
- // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>1.1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
- #if !ME_ROM
- if (smatch(wp->method, "DELETE")) {
- if (unlink(wp->filename) < 0) {
- websError(wp, HTTP_CODE_NOT_FOUND, "Cannot delete the URI");
- } else {
- /* No content */
- websResponse(wp, 204, 0);
- }
- } else if (smatch(wp->method, "PUT")) {
- /* Code is already set for us by processContent() */
- websResponse(wp, wp->code, 0);
- } else
- #endif /* !ME_ROM */
- {
- // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>1.2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
- /*
- If the file is a directory, redirect using the nominated default page
- */
- if (websPageIsDirectory(wp)) {
- nchars = strlen(wp->path);
- if (wp->path[nchars - 1] == '/' || wp->path[nchars - 1] == '\\') {
- wp->path[--nchars] = '\0';
- }
- tmp = sfmt("%s/%s", wp->path, websIndex);
- printf("Redirect %s\n", tmp);
- websRedirect(wp, tmp);
- wfree(tmp);
- return 1;
- }
- // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>1.3>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
- if (websPageOpen(wp, O_RDONLY | O_BINARY, 0666) < 0) {
- #if ME_DEBUG
- if (wp->referrer) {
- printf( "From %s", wp->referrer);
- }
- #endif
- websError(wp, HTTP_CODE_NOT_FOUND, "Cannot open document for: %s", wp->path);
- return 1;
- }
- // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>1.4>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
- if (websPageStat(wp, &info) < 0) {
- websError(wp, HTTP_CODE_NOT_FOUND, "Cannot stat page for URL");
- return 1;
- }
- code = 200;
- // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>4.3>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
- if (wp->since && info.mtime <= wp->since) {//应该是这个判定的问题 正常来说 应该是 code=304
- // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>4.6>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
- code = 304;
- info.size = 0;
- }
- websSetStatus(wp, code);
- websWriteHeaders(wp, info.size, 0);
- if ((date = websGetDateString(&info)) != NULL) {
- websWriteHeader(wp, "Last-Modified", "%s", date);
- wfree(date);
- }
- websWriteEndHeaders(wp);
- /*
- All done if the browser did a HEAD request
- */
- if (smatch(wp->method, "HEAD")) {
- websDone(wp);
- return 1;
- }
- if (info.size > 0) {
- websSetBackgroundWriter(wp, fileWriteEvent);
- } else {
- websDone(wp);
- }
- }
- return 1;
- }
- /*
- Do output back to the browser in the background. This is a socket write handler.
- This bypasses the output buffer and writes directly to the socket.
- */
- static void fileWriteEvent(Webs *wp)
- {
- char *buf;
- ssize len, wrote;
- int err;
- assert(wp);
- assert(websValid(wp));
- if ((buf = walloc(ME_GOAHEAD_LIMIT_BUFFER)) == NULL) {
- websError(wp, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot get memory");
- return;
- }
- while ((len = websPageReadData(wp, buf, ME_GOAHEAD_LIMIT_BUFFER)) > 0) {
- if ((wrote = websWriteSocket(wp, buf, len)) < 0) {
- err = socketGetError();
- if (err == EWOULDBLOCK || err == EAGAIN) {
- websPageSeek(wp, -len, SEEK_CUR);
- } else {
- /* Will call websDone below */
- wp->state = WEBS_COMPLETE;
- }
- break;
- }
- if (wrote != len) {
- websPageSeek(wp, - (len - wrote), SEEK_CUR);
- break;
- }
- }
- wfree(buf);
- if (len <= 0) {
- websDone(wp);
- }
- }
- #if !ME_ROM
- PUBLIC bool websProcessPutData(Webs *wp)
- {
- ssize nbytes;
- assert(wp);
- assert(wp->putfd >= 0);
- assert(wp->input.buf);
- nbytes = bufLen(&wp->input);
- wp->putLen += nbytes;
- if (wp->putLen > ME_GOAHEAD_LIMIT_PUT) {
- websError(wp, HTTP_CODE_REQUEST_TOO_LARGE | WEBS_CLOSE, "Put file too large");
- } else if (write(wp->putfd, wp->input.servp, (int) nbytes) != nbytes) {
- websError(wp, HTTP_CODE_INTERNAL_SERVER_ERROR | WEBS_CLOSE, "Cannot write to file");
- }
- websConsumeInput(wp, nbytes);
- return 1;
- }
- #endif
- static void fileClose()
- {
- wfree(websIndex);
- websIndex = NULL;
- wfree(websDocuments);
- websDocuments = NULL;
- }
- PUBLIC void websFileOpen()
- {
- // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>333>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- websIndex = sclone("index.html");
- websDefineHandler("file", 0, fileHandler, fileClose, 0);
- }
- /*
- Get the default page for URL requests ending in "/"
- */
- PUBLIC char *websGetIndex()
- {
- // printf(">>>>>>>>>>>>>>>>>>>>>>>>is here ???>>>>>>>>>>>>>>>>>>>>>>");
- return websIndex;
- }
- PUBLIC char *websGetDocuments()
- {
- return websDocuments;
- }
- /*
- Set the default page for URL requests ending in "/"
- */
- PUBLIC void websSetIndex(char *page)
- {
- assert(page && *page);
- if (websIndex) {
- wfree(websIndex);
- }
- websIndex = sclone(page);
- }
- /*
- Set the default web directory
- */
- PUBLIC void websSetDocuments(char *dir)
- {
- assert(dir && *dir);
- if (websDocuments) {
- wfree(websDocuments);
- }
- websDocuments = sclone(dir);
- }
- /*
- Copyright (c) Embedthis Software. All Rights Reserved.
- This software is distributed under commercial and open source licenses.
- You may use the Embedthis GoAhead open source license or you may acquire
- a commercial license from Embedthis Software. You agree to be fully bound
- by the terms of either license. Consult the LICENSE.md distributed with
- this software for full details and other copyrights.
- */
|