1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7 #include <nxt_router.h>
8 #include <nxt_http.h>
9 #include <nxt_upstream.h>
10
11
12 static nxt_http_action_t *nxt_upstream_handler(nxt_task_t *task,
13 nxt_http_request_t *r, nxt_http_action_t *action);
14
15
16 nxt_int_t
nxt_upstreams_create(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_conf_value_t * conf)17 nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
18 nxt_conf_value_t *conf)
19 {
20 size_t size;
21 uint32_t i, n, next;
22 nxt_mp_t *mp;
23 nxt_int_t ret;
24 nxt_str_t name, *string;
25 nxt_upstreams_t *upstreams;
26 nxt_conf_value_t *upstreams_conf, *upcf;
27
28 static nxt_str_t upstreams_name = nxt_string("upstreams");
29
30 upstreams_conf = nxt_conf_get_object_member(conf, &upstreams_name, NULL);
31
32 if (upstreams_conf == NULL) {
33 return NXT_OK;
34 }
35
36 n = nxt_conf_object_members_count(upstreams_conf);
37
38 if (n == 0) {
39 return NXT_OK;
40 }
41
42 mp = tmcf->router_conf->mem_pool;
43 size = sizeof(nxt_upstreams_t) + n * sizeof(nxt_upstream_t);
44
45 upstreams = nxt_mp_zalloc(mp, size);
46 if (nxt_slow_path(upstreams == NULL)) {
47 return NXT_ERROR;
48 }
49
50 upstreams->items = n;
51 next = 0;
52
53 for (i = 0; i < n; i++) {
54 upcf = nxt_conf_next_object_member(upstreams_conf, &name, &next);
55
56 string = nxt_str_dup(mp, &upstreams->upstream[i].name, &name);
57 if (nxt_slow_path(string == NULL)) {
58 return NXT_ERROR;
59 }
60
61 ret = nxt_upstream_round_robin_create(task, tmcf, upcf,
62 &upstreams->upstream[i]);
63 if (nxt_slow_path(ret != NXT_OK)) {
64 return NXT_ERROR;
65 }
66 }
67
68 tmcf->router_conf->upstreams = upstreams;
69
70 return NXT_OK;
71 }
72
73
74 nxt_int_t
nxt_upstream_find(nxt_upstreams_t * upstreams,nxt_str_t * name,nxt_http_action_t * action)75 nxt_upstream_find(nxt_upstreams_t *upstreams, nxt_str_t *name,
76 nxt_http_action_t *action)
77 {
78 uint32_t i, n;
79 nxt_upstream_t *upstream;
80
81 if (upstreams == NULL) {
82 return NXT_DECLINED;
83 }
84
85 upstream = &upstreams->upstream[0];
86 n = upstreams->items;
87
88 for (i = 0; i < n; i++) {
89 if (nxt_strstr_eq(&upstream[i].name, name)) {
90 action->u.upstream_number = i;
91 action->handler = nxt_upstream_handler;
92
93 return NXT_OK;
94 }
95 }
96
97 return NXT_DECLINED;
98 }
99
100
101 nxt_int_t
nxt_upstreams_joint_create(nxt_router_temp_conf_t * tmcf,nxt_upstream_t *** upstream_joint)102 nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf,
103 nxt_upstream_t ***upstream_joint)
104 {
105 uint32_t i, n;
106 nxt_upstream_t *u, **up;
107 nxt_upstreams_t *upstreams;
108 nxt_router_conf_t *router_conf;
109
110 router_conf = tmcf->router_conf;
111 upstreams = router_conf->upstreams;
112
113 if (upstreams == NULL) {
114 *upstream_joint = NULL;
115 return NXT_OK;
116 }
117
118 n = upstreams->items;
119
120 up = nxt_mp_zalloc(router_conf->mem_pool, n * sizeof(nxt_upstream_t *));
121 if (nxt_slow_path(up == NULL)) {
122 return NXT_ERROR;
123 }
124
125 u = &upstreams->upstream[0];
126
127 for (i = 0; i < n; i++) {
128 up[i] = u[i].proto->joint_create(tmcf, &u[i]);
129 if (nxt_slow_path(up[i] == NULL)) {
130 return NXT_ERROR;
131 }
132 }
133
134 *upstream_joint = up;
135
136 return NXT_OK;
137 }
138
139
140 static nxt_http_action_t *
nxt_upstream_handler(nxt_task_t * task,nxt_http_request_t * r,nxt_http_action_t * action)141 nxt_upstream_handler(nxt_task_t *task, nxt_http_request_t *r,
142 nxt_http_action_t *action)
143 {
144 nxt_upstream_t *u;
145
146 u = r->conf->upstreams[action->u.upstream_number];
147
148 nxt_debug(task, "upstream handler: \"%V\"", &u->name);
149
150 return nxt_upstream_proxy_handler(task, r, u);
151 }
152