Overview
Comment: | Added redirect support for index pages as well as early-return paths for error pages |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
e6e6a5a6471a0696fecb3d3bdfd0b3e2 |
User & Date: | rkeene on 2014-02-18 20:57:48 |
Other Links: | manifest | tags |
Context
2014-02-19
| ||
16:32 | Filed 1.8 check-in: 3e81ad96c8 user: rkeene tags: trunk, 1.8 | |
2014-02-18
| ||
20:57 | Added redirect support for index pages as well as early-return paths for error pages check-in: e6e6a5a647 user: rkeene tags: trunk | |
20:03 | Removed index.html serving workaround check-in: 6255e77ee6 user: rkeene tags: trunk | |
Changes
Modified filed.c from [02ed31827c] to [9e958014b2].
︙ | ︙ | |||
72 73 74 75 76 77 78 79 80 81 82 83 84 85 | enum { FILED_REQUEST_METHOD_GET, FILED_REQUEST_METHOD_HEAD } method; /*** Path being requested ***/ char path[FILED_PATH_BUFFER_SIZE]; struct { struct { int present; off_t offset; /*** Range start ***/ off_t length; /*** Range length ***/ } range; | > > > > > > | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | enum { FILED_REQUEST_METHOD_GET, FILED_REQUEST_METHOD_HEAD } method; /*** Path being requested ***/ char path[FILED_PATH_BUFFER_SIZE]; /*** Path type ***/ enum { FILED_REQUEST_TYPE_DIRECTORY, FILED_REQUEST_TYPE_OTHER } type; struct { struct { int present; off_t offset; /*** Range start ***/ off_t length; /*** Range length ***/ } range; |
︙ | ︙ | |||
630 631 632 633 634 635 636 | } /* Process an HTTP request and return the path requested */ static struct filed_http_request *filed_get_http_request(FILE *fp, struct filed_http_request *buffer_st, struct filed_options *options) { char *method, *path; char *buffer, *workbuffer, *workbuffer_next; char *fgets_ret; | | | 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | } /* Process an HTTP request and return the path requested */ static struct filed_http_request *filed_get_http_request(FILE *fp, struct filed_http_request *buffer_st, struct filed_options *options) { char *method, *path; char *buffer, *workbuffer, *workbuffer_next; char *fgets_ret; size_t buffer_len, path_len; off_t range_start, range_end, range_length; int range_request; int snprintf_ret; int i; /* Set to default values */ range_start = 0; |
︙ | ︙ | |||
684 685 686 687 688 689 690 | buffer_st->method = FILED_REQUEST_METHOD_GET; } else { /* HEAD request */ buffer_st->method = FILED_REQUEST_METHOD_HEAD; } /* Note path */ | > | > > > > > > > > > > > | 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 | buffer_st->method = FILED_REQUEST_METHOD_GET; } else { /* HEAD request */ buffer_st->method = FILED_REQUEST_METHOD_HEAD; } /* Note path */ path_len = strlen(path); memcpy(buffer_st->path, path, path_len + 1); /* Determine type of request from path */ if (path_len == 0) { buffer_st->type = FILED_REQUEST_TYPE_DIRECTORY; } else { if (path[path_len - 1] == '/') { buffer_st->type = FILED_REQUEST_TYPE_DIRECTORY; } else { buffer_st->type = FILED_REQUEST_TYPE_OTHER; } } /* Reset buffer for later use */ buffer = buffer_st->tmpbuf; for (i = 0; i < 100; i++) { fgets_ret = fgets(buffer, buffer_len, fp); if (fgets_ret == NULL) { |
︙ | ︙ | |||
779 780 781 782 783 784 785 | } } return(buffer_st); } /* Return an error page */ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 | } } return(buffer_st); } /* Return an error page */ static void filed_error_page(FILE *fp, const char *date_current, int error_number, int method, const char *reason, struct filed_log_entry *log) { char *error_string = "<html><head><title>ERROR</title></head><body>Unable to process request</body></html>"; fprintf(fp, "HTTP/1.1 %i Not OK\r\nDate: %s\r\nServer: filed\r\nLast-Modified: %s\r\nContent-Length: %llu\r\nContent-Type: %s\r\nConnection: close\r\n\r\n", error_number, date_current, date_current, (unsigned long long) strlen(error_string), "text/html" ); /* silence error string for HEAD requests */ if (method != FILED_REQUEST_METHOD_HEAD) { fprintf(fp, "%s", error_string); } /* Log error */ /** reason must point to a globally allocated value **/ log->reason = reason; log->http_code = error_number; filed_log_entry(log); /* Close connection */ fclose(fp); return; } /* Return a redirect to index.html */ static void filed_redirect_index(FILE *fp, const char *date_current, const char *path, struct filed_log_entry *log) { int http_code = 301; fprintf(fp, "HTTP/1.1 %i OK\r\nDate: %s\r\nServer: filed\r\nLast-Modified: %s\r\nContent-Length: 0\r\nConnection: close\r\nLocation: %s\r\n\r\n", http_code, date_current, date_current, "index.html" ); /* Log redirect */ log->reason = "redirect"; log->http_code = http_code; filed_log_entry(log); /* Close connection */ fclose(fp); return; /* Currently unused: path */ path = path; } /* Handle a single request from a client */ static void filed_handle_client(int fd, struct filed_http_request *request, struct filed_log_entry *log, struct filed_options *options) { struct filed_fileinfo *fileinfo; ssize_t sendfile_ret; size_t sendfile_size; |
︙ | ︙ | |||
829 830 831 832 833 834 835 | return; } request = filed_get_http_request(fp, request, options); if (request == NULL) { | < < < < < | < > > > | > | > | < | | | < > | > | | | | < | | | | | | | | | | | < | | < | | | | > | | | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | < | 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 | return; } request = filed_get_http_request(fp, request, options); if (request == NULL) { log->buffer[0] = '\0'; filed_error_page(fp, date_current, 500, FILED_REQUEST_METHOD_GET, "format", log); return; } path = request->path; strcpy(log->buffer, path); log->method = request->method; /* If the requested path is a directory, redirect to index page */ if (request->type == FILED_REQUEST_TYPE_DIRECTORY) { filed_redirect_index(fp, date_current, path, log); return; } fileinfo = filed_open_file(path, &request->fileinfo); if (fileinfo == NULL) { filed_error_page(fp, date_current, 404, request->method, "open_failed", log); return; } if (request->headers.range.present) { if (request->headers.range.offset != 0 || request->headers.range.length >= 0) { if (request->headers.range.offset >= fileinfo->len) { filed_error_page(fp, date_current, 416, request->method, "range_invalid", log); close(fileinfo->fd); return; } if (request->headers.range.length == ((off_t) -1)) { filed_log_msg_debug("Computing length to fit in bounds: fileinfo->len = %llu, request->headers.range.offset = %llu", (unsigned long long) fileinfo->len, (unsigned long long) request->headers.range.offset ); request->headers.range.length = fileinfo->len - request->headers.range.offset; } filed_log_msg_debug("Partial request, starting at: %llu and running for %lli bytes", (unsigned long long) request->headers.range.offset, (long long) request->headers.range.length ); } http_code = 206; } else { http_code = 200; /* Compute fake range parameters that includes the entire file */ request->headers.range.offset = 0; request->headers.range.length = fileinfo->len; } fprintf(fp, "HTTP/1.1 %i OK\r\nDate: %s\r\nServer: filed\r\nLast-Modified: %s\r\nContent-Length: %llu\r\nAccept-Ranges: bytes\r\nContent-Type: %s\r\nConnection: close\r\nETag: \"%s\"\r\n", http_code, date_current, fileinfo->lastmod, (unsigned long long) request->headers.range.length, fileinfo->type, fileinfo->etag ); if (http_code == 206) { fprintf(fp, "Content-Range: bytes %llu-%llu/%llu\r\n", (unsigned long long) request->headers.range.offset, (unsigned long long) (request->headers.range.offset + request->headers.range.length - 1), (unsigned long long) fileinfo->len ); } fprintf(fp, "\r\n"); fflush(fp); log->http_code = http_code; log->reason = "OK"; log->starttime = time(NULL); log->req_offset = request->headers.range.offset; log->req_length = request->headers.range.length; log->file_length = fileinfo->len; #ifdef FILED_NONBLOCK_HTTP int socket_flags; fd_set rfd, wfd; char sinkbuf[8192]; ssize_t read_ret; FD_ZERO(&rfd); FD_ZERO(&wfd); FD_SET(fd, &rfd); FD_SET(fd, &wfd); socket_flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, socket_flags | O_NONBLOCK); #endif sendfile_offset = request->headers.range.offset; sendfile_len = request->headers.range.length; sendfile_sent = 0; while (request->method == FILED_REQUEST_METHOD_GET) { if (sendfile_len > FILED_SENDFILE_MAX) { sendfile_size = FILED_SENDFILE_MAX; } else { sendfile_size = sendfile_len; } sendfile_ret = sendfile(fd, fileinfo->fd, &sendfile_offset, sendfile_size); if (sendfile_ret <= 0) { #ifdef FILED_NONBLOCK_HTTP if (errno == EAGAIN) { sendfile_ret = 0; while (1) { select(fd + 1, &rfd, &wfd, NULL, NULL); if (FD_ISSET(fd, &rfd)) { read_ret = read(fd, sinkbuf, sizeof(sinkbuf)); if (read_ret <= 0) { break; } } if (FD_ISSET(fd, &wfd)) { read_ret = 1; break; } } if (read_ret <= 0) { break; } } else { break; } #else break; #endif } sendfile_len -= sendfile_ret; sendfile_sent += sendfile_ret; if (sendfile_len == 0) { break; } } log->endtime = (time_t) -1; log->sent_length = sendfile_sent; filed_log_entry(log); close(fileinfo->fd); fclose(fp); return; } /* Handle incoming connections */ |
︙ | ︙ |