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