file.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. file.c -- File handler
  3. This module serves static file documents
  4. */
  5. /********************************* Includes ***********************************/
  6. #include "goahead.h"
  7. /*********************************** Locals ***********************************/
  8. static char *websIndex; /* Default page name */
  9. static char *websDocuments; /* Default Web page directory */
  10. /**************************** Forward Declarations ****************************/
  11. static void fileWriteEvent(Webs *wp);
  12. /*********************************** Code *************************************/
  13. /*
  14. Serve static files
  15. Return true to indicate the request was handled, even for errors.
  16. */
  17. static bool fileHandler(Webs *wp)
  18. {
  19. WebsFileInfo info;
  20. char *tmp, *date;
  21. ssize nchars;
  22. int code;
  23. assert(websValid(wp));
  24. assert(wp->method);
  25. assert(wp->filename && wp->filename[0]);
  26. // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>1.1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  27. #if !ME_ROM
  28. if (smatch(wp->method, "DELETE")) {
  29. if (unlink(wp->filename) < 0) {
  30. websError(wp, HTTP_CODE_NOT_FOUND, "Cannot delete the URI");
  31. } else {
  32. /* No content */
  33. websResponse(wp, 204, 0);
  34. }
  35. } else if (smatch(wp->method, "PUT")) {
  36. /* Code is already set for us by processContent() */
  37. websResponse(wp, wp->code, 0);
  38. } else
  39. #endif /* !ME_ROM */
  40. {
  41. // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>1.2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  42. /*
  43. If the file is a directory, redirect using the nominated default page
  44. */
  45. if (websPageIsDirectory(wp)) {
  46. nchars = strlen(wp->path);
  47. if (wp->path[nchars - 1] == '/' || wp->path[nchars - 1] == '\\') {
  48. wp->path[--nchars] = '\0';
  49. }
  50. tmp = sfmt("%s/%s", wp->path, websIndex);
  51. printf("Redirect %s\n", tmp);
  52. websRedirect(wp, tmp);
  53. wfree(tmp);
  54. return 1;
  55. }
  56. // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>1.3>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  57. if (websPageOpen(wp, O_RDONLY | O_BINARY, 0666) < 0) {
  58. #if ME_DEBUG
  59. if (wp->referrer) {
  60. printf( "From %s", wp->referrer);
  61. }
  62. #endif
  63. websError(wp, HTTP_CODE_NOT_FOUND, "Cannot open document for: %s", wp->path);
  64. return 1;
  65. }
  66. // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>1.4>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  67. if (websPageStat(wp, &info) < 0) {
  68. websError(wp, HTTP_CODE_NOT_FOUND, "Cannot stat page for URL");
  69. return 1;
  70. }
  71. code = 200;
  72. // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>4.3>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  73. if (wp->since && info.mtime <= wp->since) {//应该是这个判定的问题 正常来说 应该是 code=304
  74. // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>4.6>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  75. code = 304;
  76. info.size = 0;
  77. }
  78. websSetStatus(wp, code);
  79. websWriteHeaders(wp, info.size, 0);
  80. if ((date = websGetDateString(&info)) != NULL) {
  81. websWriteHeader(wp, "Last-Modified", "%s", date);
  82. wfree(date);
  83. }
  84. websWriteEndHeaders(wp);
  85. /*
  86. All done if the browser did a HEAD request
  87. */
  88. if (smatch(wp->method, "HEAD")) {
  89. websDone(wp);
  90. return 1;
  91. }
  92. if (info.size > 0) {
  93. websSetBackgroundWriter(wp, fileWriteEvent);
  94. } else {
  95. websDone(wp);
  96. }
  97. }
  98. return 1;
  99. }
  100. /*
  101. Do output back to the browser in the background. This is a socket write handler.
  102. This bypasses the output buffer and writes directly to the socket.
  103. */
  104. static void fileWriteEvent(Webs *wp)
  105. {
  106. char *buf;
  107. ssize len, wrote;
  108. int err;
  109. assert(wp);
  110. assert(websValid(wp));
  111. if ((buf = walloc(ME_GOAHEAD_LIMIT_BUFFER)) == NULL) {
  112. websError(wp, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot get memory");
  113. return;
  114. }
  115. while ((len = websPageReadData(wp, buf, ME_GOAHEAD_LIMIT_BUFFER)) > 0) {
  116. if ((wrote = websWriteSocket(wp, buf, len)) < 0) {
  117. err = socketGetError();
  118. if (err == EWOULDBLOCK || err == EAGAIN) {
  119. websPageSeek(wp, -len, SEEK_CUR);
  120. } else {
  121. /* Will call websDone below */
  122. wp->state = WEBS_COMPLETE;
  123. }
  124. break;
  125. }
  126. if (wrote != len) {
  127. websPageSeek(wp, - (len - wrote), SEEK_CUR);
  128. break;
  129. }
  130. }
  131. wfree(buf);
  132. if (len <= 0) {
  133. websDone(wp);
  134. }
  135. }
  136. #if !ME_ROM
  137. PUBLIC bool websProcessPutData(Webs *wp)
  138. {
  139. ssize nbytes;
  140. assert(wp);
  141. assert(wp->putfd >= 0);
  142. assert(wp->input.buf);
  143. nbytes = bufLen(&wp->input);
  144. wp->putLen += nbytes;
  145. if (wp->putLen > ME_GOAHEAD_LIMIT_PUT) {
  146. websError(wp, HTTP_CODE_REQUEST_TOO_LARGE | WEBS_CLOSE, "Put file too large");
  147. } else if (write(wp->putfd, wp->input.servp, (int) nbytes) != nbytes) {
  148. websError(wp, HTTP_CODE_INTERNAL_SERVER_ERROR | WEBS_CLOSE, "Cannot write to file");
  149. }
  150. websConsumeInput(wp, nbytes);
  151. return 1;
  152. }
  153. #endif
  154. static void fileClose()
  155. {
  156. wfree(websIndex);
  157. websIndex = NULL;
  158. wfree(websDocuments);
  159. websDocuments = NULL;
  160. }
  161. PUBLIC void websFileOpen()
  162. {
  163. // printf(">>>>>>>>>>>>>>>>>>>>>>>>>>333>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
  164. websIndex = sclone("index.html");
  165. websDefineHandler("file", 0, fileHandler, fileClose, 0);
  166. }
  167. /*
  168. Get the default page for URL requests ending in "/"
  169. */
  170. PUBLIC char *websGetIndex()
  171. {
  172. // printf(">>>>>>>>>>>>>>>>>>>>>>>>is here ???>>>>>>>>>>>>>>>>>>>>>>");
  173. return websIndex;
  174. }
  175. PUBLIC char *websGetDocuments()
  176. {
  177. return websDocuments;
  178. }
  179. /*
  180. Set the default page for URL requests ending in "/"
  181. */
  182. PUBLIC void websSetIndex(char *page)
  183. {
  184. assert(page && *page);
  185. if (websIndex) {
  186. wfree(websIndex);
  187. }
  188. websIndex = sclone(page);
  189. }
  190. /*
  191. Set the default web directory
  192. */
  193. PUBLIC void websSetDocuments(char *dir)
  194. {
  195. assert(dir && *dir);
  196. if (websDocuments) {
  197. wfree(websDocuments);
  198. }
  199. websDocuments = sclone(dir);
  200. }
  201. /*
  202. Copyright (c) Embedthis Software. All Rights Reserved.
  203. This software is distributed under commercial and open source licenses.
  204. You may use the Embedthis GoAhead open source license or you may acquire
  205. a commercial license from Embedthis Software. You agree to be fully bound
  206. by the terms of either license. Consult the LICENSE.md distributed with
  207. this software for full details and other copyrights.
  208. */