static void test_resolve(void) { h2o_mem_pool_t pool; h2o_url_t base, relative, resolved; h2o_iovec_t final; int ret; h2o_mem_init_pool(&pool); ret = h2o_url_parse("http://example.com/dir/index.html", SIZE_MAX, &base); ok(ret == 0); ret = h2o_url_parse_relative("../assets/jquery.js", SIZE_MAX, &relative); ok(ret == 0); final = h2o_url_resolve(&pool, &base, &relative, &resolved);
static h2o_iovec_t rewrite_location(h2o_mem_pool_t *pool, const char *location, size_t location_len, h2o_url_t *match, const h2o_url_scheme_t *req_scheme, h2o_iovec_t req_authority, h2o_iovec_t req_basepath) { h2o_url_t loc_parsed; if (h2o_url_parse(location, location_len, &loc_parsed) != 0) goto NoRewrite; if (loc_parsed.scheme != &H2O_URL_SCHEME_HTTP) goto NoRewrite; if (!h2o_lcstris(loc_parsed.host.base, loc_parsed.host.len, match->host.base, match->host.len)) goto NoRewrite; if (h2o_url_get_port(&loc_parsed) != h2o_url_get_port(match)) goto NoRewrite; if (loc_parsed.path.len < match->path.len) goto NoRewrite; if (memcmp(loc_parsed.path.base, match->path.base, match->path.len) != 0) goto NoRewrite; return h2o_concat(pool, req_scheme->name, h2o_iovec_init(H2O_STRLIT("://")), req_authority, req_basepath, h2o_iovec_init(loc_parsed.path.base + match->path.len, loc_parsed.path.len - match->path.len)); NoRewrite: return (h2o_iovec_t){}; }
static void test_parse(void) { h2o_url_t parsed; int ret; ret = h2o_url_parse("http://example.com/abc", SIZE_MAX, &parsed); ok(ret == 0); ok(parsed.scheme == &H2O_URL_SCHEME_HTTP); ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("example.com"))); ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("example.com"))); ok(parsed._port == 65535); ok(h2o_url_get_port(&parsed) == 80); ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc"))); ret = h2o_url_parse("http://example.com", SIZE_MAX, &parsed); ok(ret == 0); ok(parsed.scheme == &H2O_URL_SCHEME_HTTP); ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("example.com"))); ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("example.com"))); ok(parsed._port == 65535); ok(h2o_url_get_port(&parsed) == 80); ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/"))); ret = h2o_url_parse("http://example.com:81/abc", SIZE_MAX, &parsed); ok(ret == 0); ok(parsed.scheme == &H2O_URL_SCHEME_HTTP); ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("example.com:81"))); ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("example.com"))); ok(parsed._port == 81); ok(h2o_url_get_port(&parsed) == 81); ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc"))); ret = h2o_url_parse("http://example.com:81", SIZE_MAX, &parsed); ok(ret == 0); ok(parsed.scheme == &H2O_URL_SCHEME_HTTP); ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("example.com:81"))); ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("example.com"))); ok(parsed._port == 81); ok(h2o_url_get_port(&parsed) == 81); ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/"))); ret = h2o_url_parse("https://example.com/abc", SIZE_MAX, &parsed); ok(ret == 0); ok(parsed.scheme == &H2O_URL_SCHEME_HTTPS); ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("example.com"))); ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("example.com"))); ok(parsed._port == 65535); ok(h2o_url_get_port(&parsed) == 443); ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc"))); ret = h2o_url_parse("http:/abc", SIZE_MAX, &parsed); ok(ret != 0); ret = h2o_url_parse("ftp://example.com/abc", SIZE_MAX, &parsed); ok(ret != 0); ret = h2o_url_parse("http://abc:111111/def", SIZE_MAX, &parsed); ok(ret != 0); ret = h2o_url_parse("http://[::ffff:192.0.2.128]", SIZE_MAX, &parsed); ok(ret == 0); ok(parsed.scheme == &H2O_URL_SCHEME_HTTP); ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("[::ffff:192.0.2.128]"))); ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("::ffff:192.0.2.128"))); ok(parsed._port == 65535); ok(h2o_url_get_port(&parsed) == 80); ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/"))); ret = h2o_url_parse("https://[::ffff:192.0.2.128]/abc", SIZE_MAX, &parsed); ok(ret == 0); ok(parsed.scheme == &H2O_URL_SCHEME_HTTPS); ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("[::ffff:192.0.2.128]"))); ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("::ffff:192.0.2.128"))); ok(parsed._port == 65535); ok(h2o_url_get_port(&parsed) == 443); ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc"))); ret = h2o_url_parse("https://[::ffff:192.0.2.128]:111/abc", SIZE_MAX, &parsed); ok(ret == 0); ok(parsed.scheme == &H2O_URL_SCHEME_HTTPS); ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("[::ffff:192.0.2.128]:111"))); ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("::ffff:192.0.2.128"))); ok(parsed._port == 111); ok(h2o_url_get_port(&parsed) == 111); ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc"))); }
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; }