File: router_http.c

package info (click to toggle)
uwsgi 2.0.31-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 6,624 kB
  • sloc: ansic: 87,072; python: 7,010; cpp: 1,133; java: 708; perl: 678; sh: 585; ruby: 555; makefile: 148; xml: 130; cs: 121; objc: 37; php: 28; erlang: 20; javascript: 11
file content (162 lines) | stat: -rw-r--r-- 4,950 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <uwsgi.h>

#ifdef UWSGI_ROUTING

extern struct uwsgi_server uwsgi;

static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
	
	struct uwsgi_buffer *ub = NULL;

	// mark a route request
        wsgi_req->via = UWSGI_VIA_ROUTE;

	char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
        uint16_t *subject_len = (uint16_t *)  (((char *)(wsgi_req))+ur->subject_len);

	struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
	if (!ub_addr) return UWSGI_ROUTE_BREAK;

	struct uwsgi_buffer *ub_url = NULL;
	if (ur->data3_len) {
		ub_url = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data3, ur->data3_len);
        	if (!ub_url) {
			uwsgi_buffer_destroy(ub_addr);
			return UWSGI_ROUTE_BREAK;
		}
	}

	// convert the wsgi_request to an http proxy request
	if (ur->custom & 0x02) {
		ub = uwsgi_buffer_new(uwsgi.page_size);
	}
	else if (ur->custom & 0x04) {
		ub = uwsgi_to_http_dumb(wsgi_req, ur->data2, ur->data2_len, ub_url ? ub_url->buf : NULL, ub_url ? ub_url->pos : 0);
	}
	else {
		ub = uwsgi_to_http(wsgi_req, ur->data2, ur->data2_len, ub_url ? ub_url->buf : NULL, ub_url ? ub_url->pos : 0);	
	}

	if (!ub) {
		if (ub_url) uwsgi_buffer_destroy(ub_url);
		uwsgi_log("unable to generate http request for %s\n", ub_addr->buf);
		uwsgi_buffer_destroy(ub_addr);
                return UWSGI_ROUTE_NEXT;
	}

	if (ub_url) uwsgi_buffer_destroy(ub_url);

	// amount of body to send
	size_t remains = wsgi_req->post_cl - wsgi_req->proto_parser_remains;
	// append remaining body...
	if (wsgi_req->proto_parser_remains > 0) {
		if (uwsgi_buffer_append(ub, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains)) {
			uwsgi_buffer_destroy(ub);
			uwsgi_log("unable to generate http request for %s\n", ub_addr->buf);
			uwsgi_buffer_destroy(ub_addr);
               		return UWSGI_ROUTE_NEXT;
		}
		wsgi_req->post_pos += wsgi_req->proto_parser_remains;
		wsgi_req->proto_parser_remains = 0;
	}

	// ok now if have offload threads, directly use them
	if (!wsgi_req->post_file && !(ur->custom & 0x01) && wsgi_req->socket->can_offload) {
		// append buffered body
		if (uwsgi.post_buffering > 0 && wsgi_req->post_cl > 0) {
			if (uwsgi_buffer_append(ub, wsgi_req->post_buffering_buf, wsgi_req->post_cl)) {
				uwsgi_buffer_destroy(ub);
				uwsgi_log("unable to generate http request for %s\n", ub_addr->buf);
				uwsgi_buffer_destroy(ub_addr);
               			return UWSGI_ROUTE_NEXT;
			}
		}

		// if we have a CONNECT request, let's confirm it to the client
		if (ur->custom & 0x02) {
			if (uwsgi_response_prepare_headers(wsgi_req, "200 Connection established", 26)) goto end;
                        // no need to check for return value
                        uwsgi_response_write_headers_do(wsgi_req);	
		}

        	if (!uwsgi_offload_request_net_do(wsgi_req, ub_addr->buf, ub)) {
                	wsgi_req->via = UWSGI_VIA_OFFLOAD;
			wsgi_req->status = 202;
			uwsgi_buffer_destroy(ub_addr);
			return UWSGI_ROUTE_BREAK;
                }
	}

	if (uwsgi_proxy_nb(wsgi_req, ub_addr->buf, ub, remains, uwsgi.socket_timeout)) {
		uwsgi_log("error routing request to http server %s\n", ub_addr->buf);
	}

end:
	uwsgi_buffer_destroy(ub);
	uwsgi_buffer_destroy(ub_addr);

	return UWSGI_ROUTE_BREAK;

}

static int uwsgi_router_http(struct uwsgi_route *ur, char *args) {

	ur->func = uwsgi_routing_func_http;
	ur->data = (void *) args;
	ur->data_len = strlen(args);

	char *comma = strchr(ur->data, ',');
	if (comma) {
		*comma = 0;
		ur->data_len = strlen(ur->data);
		ur->data2 = comma+1;
		comma = strchr(ur->data2, ',');
		if (comma) {
			*comma = 0;
			ur->data3 = comma+1;
			ur->data3_len = strlen(ur->data3);
		}
		ur->data2_len = strlen(ur->data2);
	}
	return 0;
}

static int uwsgi_router_proxyhttp(struct uwsgi_route *ur, char *args) {
	ur->custom = 0x1;
	return uwsgi_router_http(ur, args);
}

static int uwsgi_router_proxyhttp_connect(struct uwsgi_route *ur, char *args) {
        ur->custom = 0x1|0x02;
        return uwsgi_router_http(ur, args);
}

static int uwsgi_router_http_connect(struct uwsgi_route *ur, char *args) {
        ur->custom = 0x02;
        return uwsgi_router_http(ur, args);
}

static int uwsgi_router_httpdumb(struct uwsgi_route *ur, char *args) {
        ur->custom = 0x04;
        return uwsgi_router_http(ur, args);
}


static void router_http_register(void) {

	uwsgi_register_router("http", uwsgi_router_http);
	uwsgi_register_router("httpdumb", uwsgi_router_httpdumb);
	uwsgi_register_router("proxyhttp", uwsgi_router_proxyhttp);
	uwsgi_register_router("httpconnect", uwsgi_router_http_connect);
	uwsgi_register_router("proxyhttpconnect", uwsgi_router_proxyhttp_connect);
}

struct uwsgi_plugin router_http_plugin = {
	.name = "router_http",
	.on_load = router_http_register,
};
#else
struct uwsgi_plugin router_http_plugin = {
	.name = "router_http",
};
#endif