Deleted
Added
1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) Valentin V. Bartenev 5 * Copyright (C) NGINX, Inc. 6 */ 7 8#include <nxt_main.h> --- 13 unchanged lines hidden (view full) --- 22 size_t length; 23 nxt_controller_conf_t conf; 24 nxt_conn_t *conn; 25 nxt_queue_link_t link; 26} nxt_controller_request_t; 27 28 29typedef struct { |
30 nxt_uint_t status; |
31 nxt_conf_value_t *conf; |
32 33 u_char *title; 34 u_char *detail; 35 ssize_t offset; 36 nxt_uint_t line; 37 nxt_uint_t column; |
38} nxt_controller_response_t; 39 40 41static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data); 42static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data); 43static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c, 44 uintptr_t data); 45static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj, --- 17 unchanged lines hidden (view full) --- 63 nxt_controller_request_t *req); 64static nxt_int_t nxt_controller_conf_apply(nxt_task_t *task, 65 nxt_controller_request_t *req); 66static void nxt_controller_process_waiting(nxt_task_t *task); 67static nxt_int_t nxt_controller_conf_pass(nxt_task_t *task, 68 nxt_conf_value_t *conf); 69static void nxt_controller_response(nxt_task_t *task, 70 nxt_controller_request_t *req, nxt_controller_response_t *resp); |
71static u_char *nxt_controller_date(u_char *buf, nxt_realtime_t *now, 72 struct tm *tm, size_t size, const char *format); |
73 74 75static nxt_http_fields_hash_entry_t nxt_controller_request_fields[] = { 76 { nxt_string("Content-Length"), 77 &nxt_controller_request_content_length, 0 }, 78 79 { nxt_null_string, NULL, 0 } 80}; --- 480 unchanged lines hidden (view full) --- 561 562static void 563nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) 564{ 565 nxt_mp_t *mp; 566 nxt_int_t rc; 567 nxt_str_t path; 568 nxt_conn_t *c; |
569 nxt_buf_mem_t *mbuf; 570 nxt_conf_op_t *ops; 571 nxt_conf_value_t *value; |
572 nxt_conf_json_error_t error; |
573 nxt_controller_response_t resp; 574 575 static const nxt_str_t empty_obj = nxt_string("{}"); 576 577 c = req->conn; 578 path = req->parser.path; 579 580 if (path.length > 1 && path.start[path.length - 1] == '/') { 581 path.length--; 582 } 583 584 nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 585 586 if (nxt_str_eq(&req->parser.method, "GET", 3)) { 587 588 value = nxt_conf_get_path(nxt_controller_conf.root, &path); 589 590 if (value == NULL) { |
591 goto not_found; |
592 } 593 |
594 resp.status = 200; |
595 resp.conf = value; 596 |
597 nxt_controller_response(task, req, &resp); 598 return; |
599 } 600 601 if (nxt_str_eq(&req->parser.method, "PUT", 3)) { 602 603 mp = nxt_mp_create(1024, 128, 256, 32); 604 605 if (nxt_slow_path(mp == NULL)) { |
606 goto alloc_fail; |
607 } 608 609 mbuf = &c->read->mem; 610 |
611 nxt_memzero(&error, sizeof(nxt_conf_json_error_t)); |
612 |
613 value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free, &error); 614 |
615 if (value == NULL) { 616 nxt_mp_destroy(mp); |
617 618 if (error.pos == NULL) { 619 goto alloc_fail; 620 } 621 622 resp.status = 400; 623 resp.title = (u_char *) "Invalid JSON."; 624 resp.detail = error.detail; 625 resp.offset = error.pos - mbuf->pos; 626 627 nxt_conf_json_position(mbuf->pos, error.pos, 628 &resp.line, &resp.column); 629 630 nxt_controller_response(task, req, &resp); 631 return; |
632 } 633 634 if (path.length != 1) { 635 rc = nxt_conf_op_compile(c->mem_pool, &ops, 636 nxt_controller_conf.root, 637 &path, value); 638 639 if (rc != NXT_OK) { 640 if (rc == NXT_DECLINED) { |
641 goto not_found; |
642 } 643 |
644 goto alloc_fail; |
645 } 646 647 value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 648 649 if (nxt_slow_path(value == NULL)) { 650 nxt_mp_destroy(mp); |
651 goto alloc_fail; |
652 } 653 } 654 655 if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) { 656 nxt_mp_destroy(mp); |
657 goto invalid_conf; |
658 } 659 660 req->conf.root = value; 661 req->conf.pool = mp; 662 663 if (nxt_controller_conf_apply(task, req) != NXT_OK) { 664 nxt_mp_destroy(mp); |
665 goto alloc_fail; |
666 } 667 668 return; 669 } 670 671 if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { 672 673 if (path.length == 1) { 674 mp = nxt_mp_create(1024, 128, 256, 32); 675 676 if (nxt_slow_path(mp == NULL)) { |
677 goto alloc_fail; |
678 } 679 680 value = nxt_conf_json_parse_str(mp, &empty_obj); 681 682 } else { 683 rc = nxt_conf_op_compile(c->mem_pool, &ops, 684 nxt_controller_conf.root, 685 &path, NULL); 686 687 if (rc != NXT_OK) { 688 if (rc == NXT_DECLINED) { |
689 goto not_found; |
690 } 691 |
692 goto alloc_fail; |
693 } 694 695 mp = nxt_mp_create(1024, 128, 256, 32); 696 697 if (nxt_slow_path(mp == NULL)) { |
698 goto alloc_fail; |
699 } 700 701 value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 702 } 703 704 if (nxt_slow_path(value == NULL)) { 705 nxt_mp_destroy(mp); |
706 goto alloc_fail; |
707 } 708 709 if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) { 710 nxt_mp_destroy(mp); |
711 goto invalid_conf; |
712 } 713 714 req->conf.root = value; 715 req->conf.pool = mp; 716 717 if (nxt_controller_conf_apply(task, req) != NXT_OK) { 718 nxt_mp_destroy(mp); |
719 goto alloc_fail; |
720 } 721 722 return; 723 } 724 |
725 resp.status = 405; 726 resp.title = (u_char *) "Invalid method."; 727 resp.offset = -1; |
728 |
729 nxt_controller_response(task, req, &resp); 730 return; |
731 |
732alloc_fail: |
733 |
734 resp.status = 500; 735 resp.title = (u_char *) "Memory allocation failed."; 736 resp.offset = -1; |
737 |
738 nxt_controller_response(task, req, &resp); 739 return; |
740 |
741not_found: |
742 |
743 resp.status = 404; 744 resp.title = (u_char *) "Value doesn't exist."; 745 resp.offset = -1; |
746 |
747 nxt_controller_response(task, req, &resp); 748 return; |
749 |
750invalid_conf: 751 752 resp.status = 400; 753 resp.title = (u_char *) "Invalid configuration."; 754 resp.offset = -1; 755 |
756 nxt_controller_response(task, req, &resp); |
757 return; |
758} 759 760 761static nxt_int_t 762nxt_controller_conf_apply(nxt_task_t *task, nxt_controller_request_t *req) 763{ 764 nxt_int_t rc; 765 --- 29 unchanged lines hidden (view full) --- 795 req = nxt_controller_current_request; 796 nxt_controller_current_request = NULL; 797 798 if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { 799 nxt_mp_destroy(nxt_controller_conf.pool); 800 801 nxt_controller_conf = req->conf; 802 |
803 resp.status = 200; 804 resp.title = (u_char *) "Reconfiguration done."; |
805 806 } else { 807 nxt_mp_destroy(req->conf.pool); 808 |
809 resp.status = 500; 810 resp.title = (u_char *) "Failed to apply new configuration."; 811 resp.offset = -1; |
812 } 813 814 nxt_controller_response(task, req, &resp); 815 816 nxt_controller_process_waiting(task); 817} 818 819 --- 9 unchanged lines hidden (view full) --- 829 nxt_queue_remove(&req->link); 830 831 if (nxt_fast_path(nxt_controller_conf_apply(task, req) == NXT_OK)) { 832 return; 833 } 834 835 nxt_mp_destroy(req->conf.pool); 836 |
837 nxt_memzero(&resp, sizeof(nxt_controller_response_t)); |
838 |
839 resp.status = 500; 840 resp.title = (u_char *) "Memory allocation failed."; 841 resp.offset = -1; 842 |
843 nxt_controller_response(task, req, &resp); 844 845 } nxt_queue_loop; 846} 847 848 849static nxt_int_t 850nxt_controller_conf_pass(nxt_task_t *task, nxt_conf_value_t *conf) --- 27 unchanged lines hidden (view full) --- 878 if (nxt_slow_path(rc != NXT_OK)) { 879 nxt_port_rpc_cancel(task, controller_port, stream); 880 } 881 882 return rc; 883} 884 885 |
886static void 887nxt_controller_response(nxt_task_t *task, nxt_controller_request_t *req, 888 nxt_controller_response_t *resp) 889{ |
890 size_t size; 891 nxt_str_t status_line, str; 892 nxt_buf_t *b, *body; 893 nxt_conn_t *c; 894 nxt_uint_t n; 895 nxt_conf_value_t *value, *location; 896 nxt_conf_json_pretty_t pretty; |
897 |
898 static nxt_str_t success_str = nxt_string("success"); 899 static nxt_str_t error_str = nxt_string("error"); 900 static nxt_str_t detail_str = nxt_string("detail"); 901 static nxt_str_t location_str = nxt_string("location"); 902 static nxt_str_t offset_str = nxt_string("offset"); 903 static nxt_str_t line_str = nxt_string("line"); 904 static nxt_str_t column_str = nxt_string("column"); |
905 |
906 static nxt_time_string_t date_cache = { 907 (nxt_atomic_uint_t) -1, 908 nxt_controller_date, 909 "%s, %02d %s %4d %02d:%02d:%02d GMT", 910 sizeof("Wed, 31 Dec 1986 16:40:00 GMT") - 1, 911 NXT_THREAD_TIME_GMT, 912 NXT_THREAD_TIME_SEC, 913 }; |
914 |
915 switch (resp->status) { |
916 |
917 case 200: 918 nxt_str_set(&status_line, "200 OK"); 919 break; |
920 |
921 case 400: 922 nxt_str_set(&status_line, "400 Bad Request"); 923 break; |
924 |
925 case 404: 926 nxt_str_set(&status_line, "404 Not Found"); 927 break; |
928 |
929 case 405: 930 nxt_str_set(&status_line, "405 Method Not Allowed"); 931 break; 932 933 case 500: 934 nxt_str_set(&status_line, "500 Internal Server Error"); 935 break; |
936 } 937 |
938 c = req->conn; 939 value = resp->conf; |
940 |
941 if (value == NULL) { 942 n = 1 943 + (resp->detail != NULL) 944 + (resp->status >= 400 && resp->offset != -1); |
945 |
946 value = nxt_conf_create_object(c->mem_pool, n); |
947 |
948 if (nxt_slow_path(value == NULL)) { 949 nxt_controller_conn_close(task, c, req); 950 return; 951 } |
952 |
953 str.length = nxt_strlen(resp->title); 954 str.start = resp->title; |
955 |
956 if (resp->status < 400) { 957 nxt_conf_set_member_string(value, &success_str, &str, 0); |
958 |
959 } else { 960 nxt_conf_set_member_string(value, &error_str, &str, 0); |
961 } |
962 963 n = 0; 964 965 if (resp->detail != NULL) { 966 str.length = nxt_strlen(resp->detail); 967 str.start = resp->detail; 968 969 n++; 970 971 nxt_conf_set_member_string(value, &detail_str, &str, n); 972 } 973 974 if (resp->status >= 400 && resp->offset != -1) { 975 n++; 976 977 location = nxt_conf_create_object(c->mem_pool, 978 resp->line != 0 ? 3 : 1); 979 980 nxt_conf_set_member(value, &location_str, location, n); 981 982 nxt_conf_set_member_integer(location, &offset_str, resp->offset, 0); 983 984 if (resp->line != 0) { 985 nxt_conf_set_member_integer(location, &line_str, 986 resp->line, 1); 987 988 nxt_conf_set_member_integer(location, &column_str, 989 resp->column, 2); 990 } 991 } |
992 } 993 994 nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); 995 996 size = nxt_conf_json_length(value, &pretty) + 2; 997 |
998 body = nxt_buf_mem_alloc(c->mem_pool, size, 0); 999 if (nxt_slow_path(body == NULL)) { 1000 nxt_controller_conn_close(task, c, req); 1001 return; |
1002 } 1003 1004 nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); 1005 |
1006 body->mem.free = nxt_conf_json_print(body->mem.free, value, &pretty); |
1007 |
1008 body->mem.free = nxt_cpymem(body->mem.free, "\r\n", 2); |
1009 |
1010 size = sizeof("HTTP/1.1 " "\r\n") - 1 + status_line.length 1011 + sizeof("Server: nginext/0.1\r\n") - 1 1012 + sizeof("Date: Wed, 31 Dec 1986 16:40:00 GMT\r\n") - 1 1013 + sizeof("Content-Type: application/json\r\n") - 1 1014 + sizeof("Content-Length: " "\r\n") - 1 + NXT_SIZE_T_LEN 1015 + sizeof("Connection: close\r\n") - 1 1016 + sizeof("\r\n") - 1; 1017 1018 b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 1019 if (nxt_slow_path(b == NULL)) { 1020 nxt_controller_conn_close(task, c, req); 1021 return; 1022 } 1023 1024 b->next = body; 1025 1026 nxt_str_set(&str, "HTTP/1.1 "); 1027 1028 b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); 1029 b->mem.free = nxt_cpymem(b->mem.free, status_line.start, 1030 status_line.length); 1031 1032 nxt_str_set(&str, "\r\n" 1033 "Server: nginext/0.1\r\n" 1034 "Date: "); 1035 1036 b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); 1037 1038 b->mem.free = nxt_thread_time_string(task->thread, &date_cache, 1039 b->mem.free); 1040 1041 nxt_str_set(&str, "\r\n" 1042 "Content-Type: application/json\r\n" 1043 "Content-Length: "); 1044 1045 b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); 1046 1047 b->mem.free = nxt_sprintf(b->mem.free, b->mem.end, "%uz", 1048 nxt_buf_mem_used_size(&body->mem)); 1049 1050 nxt_str_set(&str, "\r\n" 1051 "Connection: close\r\n" 1052 "\r\n"); 1053 1054 b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); 1055 1056 c->write = b; 1057 c->write_state = &nxt_controller_conn_write_state; 1058 1059 nxt_conn_write(task->thread->engine, c); |
1060} |
1061 1062 1063static u_char * 1064nxt_controller_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, 1065 size_t size, const char *format) 1066{ 1067 static const char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", 1068 "Sat" }; 1069 1070 static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 1071 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 1072 1073 return nxt_sprintf(buf, buf + size, format, 1074 week[tm->tm_wday], tm->tm_mday, 1075 month[tm->tm_mon], tm->tm_year + 1900, 1076 tm->tm_hour, tm->tm_min, tm->tm_sec); 1077} |