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_str_t status_line;
31 nxt_conf_value_t *conf;
32 nxt_str_t json;
33} nxt_controller_response_t;
34
35
36static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data);
37static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data);
38static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c,
39 uintptr_t data);
40static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj,

--- 17 unchanged lines hidden (view full) ---

58 nxt_controller_request_t *req);
59static nxt_int_t nxt_controller_conf_apply(nxt_task_t *task,
60 nxt_controller_request_t *req);
61static void nxt_controller_process_waiting(nxt_task_t *task);
62static nxt_int_t nxt_controller_conf_pass(nxt_task_t *task,
63 nxt_conf_value_t *conf);
64static void nxt_controller_response(nxt_task_t *task,
65 nxt_controller_request_t *req, nxt_controller_response_t *resp);
66static nxt_buf_t *nxt_controller_response_body(nxt_controller_response_t *resp,
67 nxt_mp_t *pool);
68
69
70static nxt_http_fields_hash_entry_t nxt_controller_request_fields[] = {
71 { nxt_string("Content-Length"),
72 &nxt_controller_request_content_length, 0 },
73
74 { nxt_null_string, NULL, 0 }
75};

--- 480 unchanged lines hidden (view full) ---

556
557static void
558nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
559{
560 nxt_mp_t *mp;
561 nxt_int_t rc;
562 nxt_str_t path;
563 nxt_conn_t *c;
564 nxt_uint_t status;
565 nxt_buf_mem_t *mbuf;
566 nxt_conf_op_t *ops;
567 nxt_conf_value_t *value;
568 nxt_controller_response_t resp;
569
570 static const nxt_str_t empty_obj = nxt_string("{}");
571
572 c = req->conn;
573 path = req->parser.path;
574
575 if (path.length > 1 && path.start[path.length - 1] == '/') {
576 path.length--;
577 }
578
579 nxt_memzero(&resp, sizeof(nxt_controller_response_t));
580
581 if (nxt_str_eq(&req->parser.method, "GET", 3)) {
582
583 value = nxt_conf_get_path(nxt_controller_conf.root, &path);
584
585 if (value == NULL) {
586 status = 404;
587 goto done;
588 }
589
590 resp.conf = value;
591
592 status = 200;
593 goto done;
594 }
595
596 if (nxt_str_eq(&req->parser.method, "PUT", 3)) {
597
598 mp = nxt_mp_create(1024, 128, 256, 32);
599
600 if (nxt_slow_path(mp == NULL)) {
601 status = 500;
602 goto done;
603 }
604
605 mbuf = &c->read->mem;
606
607 value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free);
608
609 if (value == NULL) {
610 nxt_mp_destroy(mp);
611 status = 400;
612 nxt_str_set(&resp.json, "{ \"error\": \"Invalid JSON.\" }");
613 goto done;
614 }
615
616 if (path.length != 1) {
617 rc = nxt_conf_op_compile(c->mem_pool, &ops,
618 nxt_controller_conf.root,
619 &path, value);
620
621 if (rc != NXT_OK) {
622 if (rc == NXT_DECLINED) {
623 status = 404;
624 goto done;
625 }
626
627 status = 500;
628 goto done;
629 }
630
631 value = nxt_conf_clone(mp, ops, nxt_controller_conf.root);
632
633 if (nxt_slow_path(value == NULL)) {
634 nxt_mp_destroy(mp);
635 status = 500;
636 goto done;
637 }
638 }
639
640 if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) {
641 nxt_mp_destroy(mp);
642 status = 400;
643 nxt_str_set(&resp.json,
644 "{ \"error\": \"Invalid configuration.\" }");
645 goto done;
646 }
647
648 req->conf.root = value;
649 req->conf.pool = mp;
650
651 if (nxt_controller_conf_apply(task, req) != NXT_OK) {
652 nxt_mp_destroy(mp);
653 status = 500;
654 goto done;
655 }
656
657 return;
658 }
659
660 if (nxt_str_eq(&req->parser.method, "DELETE", 6)) {
661
662 if (path.length == 1) {
663 mp = nxt_mp_create(1024, 128, 256, 32);
664
665 if (nxt_slow_path(mp == NULL)) {
666 status = 500;
667 goto done;
668 }
669
670 value = nxt_conf_json_parse_str(mp, &empty_obj);
671
672 } else {
673 rc = nxt_conf_op_compile(c->mem_pool, &ops,
674 nxt_controller_conf.root,
675 &path, NULL);
676
677 if (rc != NXT_OK) {
678 if (rc == NXT_DECLINED) {
679 status = 404;
680 goto done;
681 }
682
683 status = 500;
684 goto done;
685 }
686
687 mp = nxt_mp_create(1024, 128, 256, 32);
688
689 if (nxt_slow_path(mp == NULL)) {
690 status = 500;
691 goto done;
692 }
693
694 value = nxt_conf_clone(mp, ops, nxt_controller_conf.root);
695 }
696
697 if (nxt_slow_path(value == NULL)) {
698 nxt_mp_destroy(mp);
699 status = 500;
700 goto done;
701 }
702
703 if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) {
704 nxt_mp_destroy(mp);
705 status = 400;
706 nxt_str_set(&resp.json,
707 "{ \"error\": \"Invalid configuration.\" }");
708 goto done;
709 }
710
711 req->conf.root = value;
712 req->conf.pool = mp;
713
714 if (nxt_controller_conf_apply(task, req) != NXT_OK) {
715 nxt_mp_destroy(mp);
716 status = 500;
717 goto done;
718 }
719
720 return;
721 }
722
723 status = 405;
724
725done:
726
727 switch (status) {
728
729 case 200:
730 nxt_str_set(&resp.status_line, "200 OK");
731 break;
732
733 case 400:
734 nxt_str_set(&resp.status_line, "400 Bad Request");
735 break;
736
737 case 404:
738 nxt_str_set(&resp.status_line, "404 Not Found");
739 nxt_str_set(&resp.json, "{ \"error\": \"Value doesn't exist.\" }");
740 break;
741
742 case 405:
743 nxt_str_set(&resp.status_line, "405 Method Not Allowed");
744 nxt_str_set(&resp.json, "{ \"error\": \"Invalid method.\" }");
745 break;
746
747 case 500:
748 nxt_str_set(&resp.status_line, "500 Internal Server Error");
749 nxt_str_set(&resp.json, "{ \"error\": \"Memory allocation failed.\" }");
750 break;
751 }
752
753 nxt_controller_response(task, req, &resp);
754}
755
756
757static nxt_int_t
758nxt_controller_conf_apply(nxt_task_t *task, nxt_controller_request_t *req)
759{
760 nxt_int_t rc;
761

--- 29 unchanged lines hidden (view full) ---

791 req = nxt_controller_current_request;
792 nxt_controller_current_request = NULL;
793
794 if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) {
795 nxt_mp_destroy(nxt_controller_conf.pool);
796
797 nxt_controller_conf = req->conf;
798
799 nxt_str_set(&resp.status_line, "200 OK");
800 nxt_str_set(&resp.json, "{ \"success\": \"Reconfiguration done.\" }");
801
802 } else {
803 nxt_mp_destroy(req->conf.pool);
804
805 nxt_str_set(&resp.status_line, "500 Internal Server Error");
806 nxt_str_set(&resp.json,
807 "{ \"error\": \"Failed to apply new configuration.\" }");
808 }
809
810 nxt_controller_response(task, req, &resp);
811
812 nxt_controller_process_waiting(task);
813}
814
815

--- 9 unchanged lines hidden (view full) ---

825 nxt_queue_remove(&req->link);
826
827 if (nxt_fast_path(nxt_controller_conf_apply(task, req) == NXT_OK)) {
828 return;
829 }
830
831 nxt_mp_destroy(req->conf.pool);
832
833 nxt_str_set(&resp.status_line, "500 Internal Server Error");
834 nxt_str_set(&resp.json,
835 "{ \"error\": \"Memory allocation failed.\" }");
836
837 nxt_controller_response(task, req, &resp);
838
839 } nxt_queue_loop;
840}
841
842
843static nxt_int_t
844nxt_controller_conf_pass(nxt_task_t *task, nxt_conf_value_t *conf)

--- 27 unchanged lines hidden (view full) ---

872 if (nxt_slow_path(rc != NXT_OK)) {
873 nxt_port_rpc_cancel(task, controller_port, stream);
874 }
875
876 return rc;
877}
878
879
880
881static void
882nxt_controller_response(nxt_task_t *task, nxt_controller_request_t *req,
883 nxt_controller_response_t *resp)
884{
885 size_t size;
886 nxt_buf_t *b;
887 nxt_conn_t *c;
888
889 c = req->conn;
890
891 size = sizeof("HTTP/1.0 " "\r\n\r\n") - 1 + resp->status_line.length;
892
893 b = nxt_buf_mem_alloc(c->mem_pool, size, 0);
894 if (nxt_slow_path(b == NULL)) {
895 nxt_controller_conn_close(task, c, req);
896 return;
897 }
898
899 b->mem.free = nxt_cpymem(b->mem.free, "HTTP/1.0 ", sizeof("HTTP/1.0 ") - 1);
900 b->mem.free = nxt_cpymem(b->mem.free, resp->status_line.start,
901 resp->status_line.length);
902
903 b->mem.free = nxt_cpymem(b->mem.free, "\r\n\r\n", sizeof("\r\n\r\n") - 1);
904
905 b->next = nxt_controller_response_body(resp, c->mem_pool);
906
907 if (nxt_slow_path(b->next == NULL)) {
908 nxt_controller_conn_close(task, c, req);
909 return;
910 }
911
912 c->write = b;
913 c->write_state = &nxt_controller_conn_write_state;
914
915 nxt_conn_write(task->thread->engine, c);
916}
917
918
919static nxt_buf_t *
920nxt_controller_response_body(nxt_controller_response_t *resp, nxt_mp_t *pool)
921{
922 size_t size;
923 nxt_buf_t *b;
924 nxt_conf_value_t *value;
925 nxt_conf_json_pretty_t pretty;
926
927 if (resp->conf) {
928 value = resp->conf;
929
930 } else {
931 value = nxt_conf_json_parse_str(pool, &resp->json);
932
933 if (nxt_slow_path(value == NULL)) {
934 return NULL;
935 }
936 }
937
938 nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t));
939
940 size = nxt_conf_json_length(value, &pretty) + 2;
941
942 b = nxt_buf_mem_alloc(pool, size, 0);
943 if (nxt_slow_path(b == NULL)) {
944 return NULL;
945 }
946
947 nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t));
948
949 b->mem.free = nxt_conf_json_print(b->mem.free, value, &pretty);
950
951 *b->mem.free++ = '\r';
952 *b->mem.free++ = '\n';
953
954 return b;
955}