int32_t elasticsearch_connection_init(const char *url, bool debug, struct elasticsearch_connection **conn_r, const char **error_r) { struct http_client_settings http_set; struct elasticsearch_connection *conn = NULL; struct http_url *http_url = NULL; const char *error = NULL; if (error_r == NULL || url == NULL || conn_r == NULL) { i_debug("fts_elasticsearch: error initialising ElasticSearch connection"); return -1; } else { /* safe to continue */ } /* validate the url */ if (http_url_parse(url, NULL, 0, pool_datastack_create(), &http_url, &error) < 0) { *error_r = t_strdup_printf( "fts_elasticsearch: Failed to parse HTTP url: %s", error); return -1; } conn = i_new(struct elasticsearch_connection, 1); conn->http_host = i_strdup(http_url->host_name); conn->http_port = http_url->port; conn->http_base_url = i_strconcat(http_url->path, http_url->enc_query, NULL); conn->http_ssl = http_url->have_ssl; conn->debug = debug; /* guard against init being called multiple times */ if (elasticsearch_http_client == NULL) { memset(&http_set, 0, sizeof(http_set)); http_set.max_idle_time_msecs = 5 * 1000; http_set.max_parallel_connections = 1; http_set.max_pipelined_requests = 1; http_set.max_redirects = 1; http_set.max_attempts = 3; http_set.debug = debug; elasticsearch_http_client = http_client_init(&http_set); } *conn_r = conn; return 0; }
int solr_connection_init(const char *url, bool debug, struct solr_connection **conn_r, const char **error_r) { struct http_client_settings http_set; struct solr_connection *conn; struct http_url *http_url; const char *error; if (http_url_parse(url, NULL, 0, pool_datastack_create(), &http_url, &error) < 0) { *error_r = t_strdup_printf( "fts_solr: Failed to parse HTTP url: %s", error); return -1; } conn = i_new(struct solr_connection, 1); conn->http_host = i_strdup(http_url->host.name); conn->http_port = http_url->port; conn->http_base_url = i_strconcat(http_url->path, http_url->enc_query, NULL); conn->http_ssl = http_url->have_ssl; conn->debug = debug; if (solr_http_client == NULL) { memset(&http_set, 0, sizeof(http_set)); http_set.max_idle_time_msecs = 5*1000; http_set.max_parallel_connections = 1; http_set.max_pipelined_requests = 1; http_set.max_redirects = 1; http_set.max_attempts = 3; http_set.debug = debug; http_set.connect_timeout_msecs = 5*1000; http_set.request_timeout_msecs = 60*1000; solr_http_client = http_client_init(&http_set); } conn->xml_parser = XML_ParserCreate("UTF-8"); if (conn->xml_parser == NULL) { i_fatal_status(FATAL_OUTOFMEM, "fts_solr: Failed to allocate XML parser"); } *conn_r = conn; return 0; }
static int tika_get_http_client_url(struct mail_user *user, struct http_url **http_url_r) { struct fts_parser_tika_user *tuser = TIKA_USER_CONTEXT(user); struct http_client_settings http_set; const char *url, *error; url = mail_user_plugin_getenv(user, "fts_tika"); if (url == NULL) { /* fts_tika disabled */ return -1; } if (tuser != NULL) { *http_url_r = tuser->http_url; return *http_url_r == NULL ? -1 : 0; } tuser = p_new(user->pool, struct fts_parser_tika_user, 1); MODULE_CONTEXT_SET(user, fts_parser_tika_user_module, tuser); if (http_url_parse(url, NULL, 0, user->pool, &tuser->http_url, &error) < 0) { i_error("fts_tika: Failed to parse HTTP url %s: %s", url, error); return -1; } if (tika_http_client == NULL) { memset(&http_set, 0, sizeof(http_set)); http_set.max_idle_time_msecs = 100; http_set.max_parallel_connections = 1; http_set.max_pipelined_requests = 1; http_set.max_redirects = 1; http_set.max_attempts = 3; http_set.connect_timeout_msecs = 5*1000; http_set.request_timeout_msecs = 60*1000; http_set.debug = user->mail_debug; tika_http_client = http_client_init(&http_set); } *http_url_r = tuser->http_url; return 0; }
int main(int argc, char **argv) { struct c_command_line *cmdline; const char *url_string; struct http_url *url; char *result; cmdline = c_command_line_new(); c_command_line_add_argument(cmdline, "the url string", "url"); if (c_command_line_parse(cmdline, argc, argv) == -1) httpex_die("%s", c_get_error()); url_string = c_command_line_argument_value(cmdline, 0); url = http_url_parse(url_string); if (!url) httpex_die("cannot parse url: %s", c_get_error()); if (http_url_scheme(url)) printf("- %-12s '%s'\n", "scheme", http_url_scheme(url)); if (http_url_user(url)) printf("- %-12s '%s'\n", "user", http_url_user(url)); if (http_url_password(url)) printf("- %-12s '%s'\n", "password", http_url_password(url)); if (http_url_host(url)) printf("- %-12s '%s'\n", "host", http_url_host(url)); if (http_url_port(url)) { printf("- %-12s '%s'\n", "port", http_url_port(url)); printf(" %-12s %u\n", "port number", http_url_port_number(url)); } if (http_url_path(url)) printf("- %-12s '%s'\n", "path", http_url_path(url)); if (http_url_query(url)) { size_t nb_params; printf("- %-12s '%s'\n", "query", http_url_query(url)); nb_params = http_url_nb_query_parameters(url); for (size_t i = 0; i < nb_params; i++) { const char *name, *value; name = http_url_nth_query_parameter(url, i, &value); if (value) { printf(" %-12s %s\n", name, value); } else { printf(" %-12s\n", name); } } } if (http_url_fragment(url)) printf("- %-12s '%s'\n", "fragment", http_url_fragment(url)); result = http_url_to_string(url); printf("\n%s\n", result); c_free(result); http_url_delete(url); c_command_line_delete(cmdline); return 0; }
void http_client_request_redirect(struct http_client_request *req, unsigned int status, const char *location) { struct http_url *url; const char *error, *target, *origin_url; i_assert(!req->payload_wait); /* parse URL */ if (http_url_parse(location, NULL, 0, pool_datastack_create(), &url, &error) < 0) { http_client_request_error(&req, HTTP_CLIENT_REQUEST_ERROR_INVALID_REDIRECT, t_strdup_printf("Invalid redirect location: %s", error)); return; } if (++req->redirects > req->client->set.max_redirects) { if (req->client->set.max_redirects > 0) { http_client_request_error(&req, HTTP_CLIENT_REQUEST_ERROR_INVALID_REDIRECT, t_strdup_printf("Redirected more than %d times", req->client->set.max_redirects)); } else { http_client_request_error(&req, HTTP_CLIENT_REQUEST_ERROR_INVALID_REDIRECT, "Redirect refused"); } return; } /* rewind payload stream */ if (req->payload_input != NULL && req->payload_size > 0 && status != 303) { if (req->payload_input->v_offset != req->payload_offset && !req->payload_input->seekable) { http_client_request_error(&req, HTTP_CLIENT_REQUEST_ERROR_ABORTED, "Redirect failed: Cannot resend payload; stream is not seekable"); return; } else { i_stream_seek(req->payload_input, req->payload_offset); } } /* drop payload output stream from previous attempt */ if (req->payload_output != NULL) o_stream_unref(&req->payload_output); target = http_url_create_target(url); http_url_copy(req->pool, &req->origin_url, url); req->target = p_strdup(req->pool, target); req->host = NULL; req->conn = NULL; origin_url = http_url_create(&req->origin_url); http_client_request_debug(req, "Redirecting to %s%s", origin_url, target); req->label = p_strdup_printf(req->pool, "[%s %s%s]", req->method, origin_url, req->target); /* RFC 7231, Section 6.4.4: -> A 303 `See Other' redirect status response is handled a bit differently. Basically, the response content is located elsewhere, but the original (POST) request is handled already. */ if (status == 303 && strcasecmp(req->method, "HEAD") != 0 && strcasecmp(req->method, "GET") != 0) { // FIXME: should we provide the means to skip this step? The original // request was already handled at this point. req->method = p_strdup(req->pool, "GET"); /* drop payload */ if (req->payload_input != NULL) i_stream_unref(&req->payload_input); req->payload_size = 0; req->payload_offset = 0; } /* resubmit */ req->state = HTTP_REQUEST_STATE_NEW; http_client_request_do_submit(req); }
static int http_response_preprocess_headers(struct http_response *response) { #define HTTP_FAIL(fmt_, ...) \ do { \ if (fmt_) \ c_set_error(fmt_, ##__VA_ARGS__); \ return -1; \ } while (0) for (size_t i = 0; i < http_response_nb_headers(response); i++) { const char *name, *value; name = http_response_nth_header(response, i, &value); #define HTTP_HEADER_IS(name_) (strcasecmp(name, name_) == 0) /* -- Content-Length ---------------------------------------------- */ if (HTTP_HEADER_IS("Content-Length")) { response->has_content_length = true; if (c_parse_size(value, &response->content_length, NULL) == -1) { HTTP_FAIL("cannot parse %s header: %s", name, c_get_error()); } /* -- Content-Encoding -------------------------------------------- */ } else if (HTTP_HEADER_IS("Content-Encoding")) { struct c_ptr_vector *tokens; tokens = http_list_parse(value); if (!tokens) HTTP_FAIL("cannot parse %s header: %s", name, c_get_error()); response->content_codings = c_vector_new( sizeof(enum http_content_coding)); for (size_t i = 0; i < c_ptr_vector_length(tokens); i++) { enum http_content_coding coding; const char *token; token = c_ptr_vector_entry(tokens, i); if (http_content_coding_parse(token, &coding) == -1) { http_string_vector_delete(tokens); HTTP_FAIL("unknown content coding '%s'", token); } c_vector_append(response->content_codings, &coding); } http_string_vector_delete(tokens); /* -- Connection -------------------------------------------------- */ } else if (HTTP_HEADER_IS("Connection")) { if (strcasecmp(value, "close") == 0) response->has_connection_close = true; /* -- Transfer-Encoding ------------------------------------------- */ } else if (HTTP_HEADER_IS("Transfer-Encoding")) { struct c_ptr_vector *tokens; tokens = http_list_parse(value); if (!tokens) HTTP_FAIL("cannot parse %s header: %s", name, c_get_error()); for (size_t i = 0; i < c_ptr_vector_length(tokens); i++) { const char *token; token = c_ptr_vector_entry(tokens, i); if (strcasecmp(token, "chunked") == 0) { response->is_body_chunked = true; } else if (strcasecmp(token, "compressed") == 0 || strcasecmp(token, "deflate") == 0 || strcasecmp(token, "gzip") == 0) { http_string_vector_delete(tokens); HTTP_FAIL("'%s' transfer coding not supported", token); } else { http_string_vector_delete(tokens); HTTP_FAIL("unknown transfer coding '%s'", token); } } http_string_vector_delete(tokens); /* -- Location ---------------------------------------------------- */ } else if (HTTP_HEADER_IS("Location")) { if (response->status >= 300 && response->status < 400) { struct http_url *url; url = http_url_parse(value); if (!url) HTTP_FAIL("invalid %s header: %s", name, c_get_error()); response->redirection_location = url; } } #undef HTTP_HEADER_IS } #undef HTTP_FAIL return 0; }
int main() { int logi, ch, y, x; display_log_type = INFO; log_init(&log); log_register_message_callback(&log, message_logged); current_action = NO_ACTION; initscr(); create_windows(); cdk_screen = initCDKScreen(log_window); log_swindow = newCDKSwindow(cdk_screen, 0, 0, log_lines, log_cols, "", 255, 0, 0); draw_stdscr(); draw_url_input(); draw_commands(); select_form(); raw(); noecho(); keypad(stdscr, TRUE); while ((ch = wgetch(input_window)) != '' || current_action & CANCEL_SHOWING) if (ch == KEY_LEFT) form_driver(url_form, REQ_LEFT_CHAR); else if (ch == KEY_RIGHT) form_driver(url_form, REQ_RIGHT_CHAR); else if (ch == KEY_BACKSPACE || ch == 127) { getyx(input_window, y, x); if (x == FIELD_START + 1) { form_driver(url_form, REQ_SCR_HBHALF); form_driver(url_form, REQ_END_LINE); } form_driver(url_form, REQ_LEFT_CHAR); form_driver(url_form, REQ_DEL_CHAR); } else if (ch == KEY_DC) form_driver(url_form, REQ_DEL_CHAR); else if (ch == KEY_HOME) form_driver(url_form, REQ_BEG_FIELD); else if (ch == KEY_END) form_driver(url_form, REQ_END_FIELD); else if (ch == KEY_UP || ch == KEY_DOWN) injectCDKSwindow(log_swindow, ch); else if (ch == '') cleanCDKSwindow(log_swindow); else if (ch == ' ') change_display_log_type(INFO); else if (ch == '') change_display_log_type(DETAILS); else if (ch == '\n' && current_action & URL_INPUTTING) { int ret; form_driver(url_form, REQ_END_FIELD); form_driver(url_form, 'a'); form_driver(url_form, REQ_VALIDATION); strncpy(url, field_buffer(url_field[0], 0), FIELD_BUF_SIZE); url[FIELD_BUF_SIZE - 1] = '\0'; *strrchr(url, 'a') = '\0'; http_url_init(&http_url); if (ret = http_url_parse(&http_url, url)) { char *message; switch (ret) { case INVALID_SERVER_AUTHORITY: message = "Invalid server authority"; break; case INVALID_SCHEME: message = "Invalid scheme"; break; case INVALID_PORT: message = "Invalid port"; break; default: message = "Invalid URI"; break; } log_printf(&log, INFO, "http_url_parse", "%s", message); draw_url_input(); draw_commands(); } else { draw_method_selection(); draw_cancel(); } } else if (tolower(ch) == 'g' && current_action & METHOD_SELECTING) { http_init(&http, &http_url, GET, NULL, 0, 3, &log); pthread_create(&http_thread, NULL, http_run_thread, &http); draw_cancel(); } else if (tolower(ch) == 'h' && current_action & METHOD_SELECTING) { http_init(&http, &http_url, HEAD, NULL, 0, 3, &log); pthread_create(&http_thread, NULL, http_run_thread, &http); draw_cancel(); } else if (tolower(ch) == 'p' && current_action & METHOD_SELECTING) { draw_post_input(); draw_cancel(); select_form(); } else if (ch == '\n' && current_action & POST_INPUTTING) { form_driver(url_form, REQ_END_FIELD); form_driver(url_form, 'a'); form_driver(url_form, REQ_VALIDATION); strncpy(post, field_buffer(url_field[0], 0), FIELD_BUF_SIZE); post[FIELD_BUF_SIZE - 1] = '\0'; *strrchr(post, 'a') = '\0'; http_init(&http, &http_url, POST, post, strlen(post), 3, &log); pthread_create(&http_thread, NULL, http_run_thread, &http); draw_cancel(); } else if (ch == '\n' && current_action & FILE_INPUTTING) { form_driver(url_form, REQ_END_FIELD); form_driver(url_form, 'a'); form_driver(url_form, REQ_VALIDATION); strncpy(file, field_buffer(url_field[0], 0), FIELD_BUF_SIZE); file[FIELD_BUF_SIZE - 1] = '\0'; *strrchr(file, 'a') = '\0'; pthread_mutex_lock(&input_mutex); inputted = 1; pthread_cond_broadcast(&input_cond); pthread_mutex_unlock(&input_mutex); } else if ((ch == 'y' || ch == 'Y') && current_action & OVERWRITE_INPUTTING) { do_overwrite = 1; pthread_mutex_lock(&input_mutex); inputted = 1; pthread_cond_broadcast(&input_cond); pthread_mutex_unlock(&input_mutex); } else if ((ch == 'n' || ch == 'N') && current_action & OVERWRITE_INPUTTING) { do_overwrite = 0; pthread_mutex_lock(&input_mutex); inputted = 1; pthread_cond_broadcast(&input_cond); pthread_mutex_unlock(&input_mutex); }else if (ch == '') { if (http.status != DISCONNECTED) http_disconnect(&http); draw_url_input(); draw_commands(); select_form(); } else form_driver(url_form, ch); delete_input_form(); destroyCDKSwindow(log_swindow); destroyCDKScreen(cdk_screen); endwin(); pthread_mutex_destroy(&input_mutex); pthread_cond_destroy(&input_cond); return 0; }