void h2o__proxy_process_request(h2o_req_t *req) { h2o_req_overrides_t *overrides = req->overrides; h2o_http1client_ctx_t *client_ctx = get_client_ctx(req); struct rp_generator_t *self; if (overrides != NULL) { if (overrides->socketpool != NULL) { self = proxy_send_prepare(req, 1); h2o_http1client_connect_with_pool(&self->client, self, client_ctx, overrides->socketpool, on_connect); return; } else if (overrides->hostport.host.base != NULL) { self = proxy_send_prepare(req, 0); h2o_http1client_connect(&self->client, self, client_ctx, req->overrides->hostport.host, req->overrides->hostport.port, 0, on_connect); return; } } { /* default logic */ h2o_iovec_t host; uint16_t port; if (h2o_url_parse_hostport(req->authority.base, req->authority.len, &host, &port) == NULL) { h2o_req_log_error(req, "lib/core/proxy.c", "invalid URL supplied for internal redirection:%s://%.*s%.*s", req->scheme->name.base, (int)req->authority.len, req->authority.base, (int)req->path.len, req->path.base); h2o_send_error(req, 502, "Gateway Error", "internal error", 0); return; } if (port == 65535) port = req->scheme->default_port; self = proxy_send_prepare(req, 0); h2o_http1client_connect(&self->client, self, client_ctx, host, port, req->scheme == &H2O_URL_SCHEME_HTTPS, on_connect); return; } }
int h2o_proxy_send(h2o_req_t *req, h2o_http1client_ctx_t *client_ctx, h2o_proxy_location_t *upstream) { struct rp_generator_t *self = proxy_send_prepare(req, upstream, 0); self->client = h2o_http1client_connect( client_ctx, &req->pool, h2o_strdup(&req->pool, upstream->host.base, upstream->host.len).base, upstream->port, on_connect); self->client->data = self; return 0; }
static void start_request(h2o_http1client_ctx_t *ctx) { char *scheme, *host, *path; uint16_t port; h2o_iovec_t *req; h2o_http1client_t *client; /* clear memory pool */ h2o_mempool_clear(&pool); /* parse URL */ if (h2o_parse_url(&pool, url, &scheme, &host, &port, &path) != 0) { fprintf(stderr, "unrecognized type of URL: %s\n", url); exit(1); } if (strcmp(scheme, "https") == 0) { fprintf(stderr, "https is not (yet) supported\n"); exit(1); } /* build request */ req = h2o_mempool_alloc(&pool, sizeof(*req)); req->base = h2o_mempool_alloc(&pool, 1024); req->len = snprintf(req->base, 1024, "GET %s HTTP/1.1\r\nhost: %s:%u\r\n\r\n", path, host, (unsigned)port); assert(req->len < 1024); /* initiate the request */ if (1) { if (sockpool == NULL) { sockpool = h2o_malloc(sizeof(*sockpool)); h2o_socketpool_init(sockpool, host, port, 10); h2o_socketpool_set_timeout(sockpool, ctx->loop, 5000 /* in msec */); } client = h2o_http1client_connect_with_pool(ctx, &pool, sockpool, on_connect); } else { client = h2o_http1client_connect(ctx, &pool, host, port, on_connect); } assert(client != NULL); client->data = req; }
static mrb_value http_request_method(mrb_state *mrb, mrb_value self) { h2o_mruby_generator_t *generator; struct st_h2o_mruby_http_request_context_t *ctx; const char *arg_url; mrb_int arg_url_len; mrb_value arg_hash; h2o_iovec_t method; h2o_url_t url; /* parse args */ arg_hash = mrb_nil_value(); mrb_get_args(mrb, "s|H", &arg_url, &arg_url_len, &arg_hash); /* precond check */ if ((generator = h2o_mruby_current_generator) == NULL || generator->req == NULL) mrb_exc_raise(mrb, create_downstream_closed_exception(mrb)); /* allocate context and initialize */ ctx = h2o_mem_alloc_shared(&generator->req->pool, sizeof(*ctx), on_dispose); memset(ctx, 0, sizeof(*ctx)); ctx->generator = generator; ctx->receiver = mrb_nil_value(); h2o_buffer_init(&ctx->req.buf, &h2o_socket_buffer_prototype); h2o_buffer_init(&ctx->resp.after_closed, &h2o_socket_buffer_prototype); ctx->refs.request = mrb_nil_value(); ctx->refs.input_stream = mrb_nil_value(); /* uri */ if (h2o_url_parse(arg_url, arg_url_len, &url) != 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "invaild URL"); /* method */ method = h2o_iovec_init(H2O_STRLIT("GET")); if (mrb_hash_p(arg_hash)) { mrb_value t = mrb_hash_get(mrb, arg_hash, mrb_symbol_value(generator->ctx->symbols.sym_method)); if (!mrb_nil_p(t)) { t = mrb_str_to_str(mrb, t); method = h2o_iovec_init(RSTRING_PTR(t), RSTRING_LEN(t)); } } /* start building the request */ h2o_buffer_reserve(&ctx->req.buf, method.len + 1); append_to_buffer(&ctx->req.buf, method.base, method.len); append_to_buffer(&ctx->req.buf, H2O_STRLIT(" ")); h2o_buffer_reserve(&ctx->req.buf, url.path.len + url.authority.len + sizeof(" HTTP/1.1\r\nConnection: close\r\nHost: \r\n") - 1); append_to_buffer(&ctx->req.buf, url.path.base, url.path.len); append_to_buffer(&ctx->req.buf, H2O_STRLIT(" HTTP/1.1\r\nConnection: close\r\nHost: ")); append_to_buffer(&ctx->req.buf, url.authority.base, url.authority.len); append_to_buffer(&ctx->req.buf, H2O_STRLIT("\r\n")); /* headers */ if (mrb_hash_p(arg_hash)) { mrb_value headers = mrb_hash_get(mrb, arg_hash, mrb_symbol_value(generator->ctx->symbols.sym_headers)); if (!mrb_nil_p(headers)) { if (h2o_mruby_iterate_headers(generator->ctx, headers, flatten_request_header, ctx) != 0) { mrb_value exc = mrb_obj_value(mrb->exc); mrb->exc = NULL; mrb_exc_raise(mrb, exc); } } } /* body */ if (mrb_hash_p(arg_hash)) { mrb_value body = mrb_hash_get(mrb, arg_hash, mrb_symbol_value(generator->ctx->symbols.sym_body)); if (!mrb_nil_p(body)) { if (mrb_obj_eq(mrb, body, generator->rack_input)) { /* fast path */ mrb_int pos; mrb_input_stream_get_data(mrb, body, NULL, NULL, &pos, NULL, NULL); ctx->req.body = generator->req->entity; ctx->req.body.base += pos; ctx->req.body.len -= pos; } else { if (!mrb_string_p(body)) { body = mrb_funcall(mrb, body, "read", 0); if (!mrb_string_p(body)) mrb_raise(mrb, E_ARGUMENT_ERROR, "body.read did not return string"); } ctx->req.body = h2o_strdup(&ctx->generator->req->pool, RSTRING_PTR(body), RSTRING_LEN(body)); } if (!ctx->req.has_transfer_encoding) { char buf[64]; size_t l = (size_t)sprintf(buf, "content-length: %zu\r\n", ctx->req.body.len); h2o_buffer_reserve(&ctx->req.buf, l); append_to_buffer(&ctx->req.buf, buf, l); } } } h2o_buffer_reserve(&ctx->req.buf, 2); append_to_buffer(&ctx->req.buf, H2O_STRLIT("\r\n")); /* build request and connect */ h2o_http1client_connect(&ctx->client, ctx, &generator->req->conn->ctx->proxy.client_ctx, url.host, h2o_url_get_port(&url), on_connect); ctx->refs.request = h2o_mruby_create_data_instance(mrb, mrb_ary_entry(generator->ctx->constants, H2O_MRUBY_HTTP_REQUEST_CLASS), ctx, &request_type); return ctx->refs.request; }