mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-17 10:00:45 +00:00
163 lines
4.8 KiB
C
163 lines
4.8 KiB
C
#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
|