Lines Matching refs:req

38 http_client_request_send_error(struct http_client_request *req,
42 http_client_request_label(struct http_client_request *req)
44 if (req->label == NULL) {
45 req->label = p_strdup_printf(req->pool,
46 "[Req%u: %s %s%s]", req->id, req->method,
47 http_url_create_host(&req->origin_url), req->target);
49 return req->label;
53 http_client_request_update_event(struct http_client_request *req)
55 event_add_str(req->event, "method", req->method);
56 event_add_str(req->event, "host", req->origin_url.host.name);
57 event_add_int(req->event, "port", http_url_get_port(&req->origin_url));
58 if (req->target != NULL)
59 event_add_str(req->event, "target", req->target);
60 event_set_append_log_prefix(req->event, t_strdup_printf(
61 "request %s: ", http_client_request_label(req)));
65 http_client_request_result_event(struct http_client_request *req)
67 struct http_client_connection *conn = req->conn;
70 if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT) {
72 i_assert(req->request_offset <
74 req->bytes_out = conn->conn.output->offset -
75 req->request_offset;
78 (req->state == HTTP_REQUEST_STATE_GOT_RESPONSE ||
79 req->state == HTTP_REQUEST_STATE_PAYLOAD_IN)) {
82 conn->pending_request == req);
83 i_assert(req->response_offset <
85 req->bytes_in = conn->conn.input->v_offset -
86 req->response_offset;
90 return event_create_passthrough(req->event)->
91 add_int("status_code", req->last_status)->
92 add_int("attempts", req->attempts)->
93 add_int("redirects", req->redirects)->
94 add_int("bytes_in", req->bytes_in)->
95 add_int("bytes_out", req->bytes_out);
104 struct http_client_request *req;
107 req = p_new(pool, struct http_client_request, 1);
108 req->pool = pool;
109 req->refcount = 1;
110 req->client = client;
111 req->id = ++id_counter;
112 req->method = p_strdup(pool, method);
113 req->callback = callback;
114 req->context = context;
115 req->date = (time_t)-1;
116 req->event = event_create(client->event);
119 req->max_attempts = client->set.max_attempts;
120 req->attempt_timeout_msecs = client->set.request_timeout_msecs;
122 req->state = HTTP_REQUEST_STATE_NEW;
123 return req;
132 struct http_client_request *req;
134 req = http_client_request_new(client, method, callback, context);
135 req->origin_url.host.name = p_strdup(req->pool, host);
136 req->target = (target == NULL ? "/" : p_strdup(req->pool, target));
137 http_client_request_update_event(req);
138 return req;
147 struct http_client_request *req;
149 req = http_client_request_new(client, method, callback, context);
150 http_url_copy_authority(req->pool, &req->origin_url, target_url);
151 req->target = p_strdup(req->pool, http_url_create_target(target_url));
154 req->username = p_strdup(req->pool, target_url->user);
155 req->password = p_strdup(req->pool, target_url->password);
157 http_client_request_update_event(req);
158 return req;
167 struct http_client_request *req, *tmpreq;
171 req = tmpreq = http_client_request_new
175 req->pool, &target_url, &error) < 0) {
176 req->label = p_strdup_printf(req->pool,
177 "[Req%u: %s %s]", req->id, req->method, url_str);
181 http_client_request_update_event(req);
182 return req;
185 req->origin_url = *target_url;
186 req->target = p_strdup(req->pool, http_url_create_target(target_url));
189 req->username = p_strdup(req->pool, target_url->user);
190 req->password = p_strdup(req->pool, target_url->password);
192 http_client_request_update_event(req);
193 return req;
203 struct http_client_request *req;
205 req = http_client_request_new(client, "CONNECT", callback, context);
206 req->origin_url.host.name = p_strdup(req->pool, host);
207 req->origin_url.port = port;
208 req->connect_tunnel = TRUE;
209 req->target = req->origin_url.host.name;
210 http_client_request_update_event(req);
211 return req;
221 struct http_client_request *req;
227 req = http_client_request_connect
229 req->origin_url.host.ip = *ip;
230 return req;
233 void http_client_request_set_event(struct http_client_request *req,
236 event_unref(&req->event);
237 req->event = event_create(event);
238 if (req->client->set.debug)
239 event_set_forced_debug(req->event, TRUE);
240 http_client_request_update_event(req);
244 http_client_request_add(struct http_client_request *req)
246 struct http_client *client = req->client;
248 DLLIST_PREPEND(&client->requests_list, req);
250 req->listed = TRUE;
254 http_client_request_remove(struct http_client_request *req)
256 struct http_client *client = req->client;
259 i_assert(!req->listed);
262 if (req->listed) {
264 DLLIST_REMOVE(&client->requests_list, req);
267 req->listed = FALSE;
273 void http_client_request_ref(struct http_client_request *req)
275 i_assert(req->refcount > 0);
276 req->refcount++;
281 struct http_client_request *req = *_req;
282 struct http_client *client = req->client;
284 i_assert(req->refcount > 0);
288 if (--req->refcount > 0)
292 e_debug(req->event, "Free (client already destroyed)");
294 e_debug(req->event, "Free (requests left=%d)",
299 i_assert(req->conn == NULL);
301 if (req->queue != NULL)
302 http_client_queue_drop_request(req->queue, req);
304 if (req->destroy_callback != NULL) {
305 req->destroy_callback(req->destroy_context);
306 req->destroy_callback = NULL;
309 http_client_request_remove(req);
314 if (req->delayed_error != NULL)
315 http_client_remove_request_error(req->client, req);
317 i_stream_unref(&req->payload_input);
318 o_stream_unref(&req->payload_output);
319 str_free(&req->headers);
320 event_unref(&req->event);
321 pool_unref(&req->pool);
327 struct http_client_request *req = *_req, *tmp_req;
328 struct http_client *client = req->client;
333 e_debug(req->event, "Destroy (client already destroyed)");
335 e_debug(req->event, "Destroy (requests left=%d)",
340 if (req->state < HTTP_REQUEST_STATE_FINISHED)
341 req->state = HTTP_REQUEST_STATE_ABORTED;
342 req->callback = NULL;
344 if (req->queue != NULL)
345 http_client_queue_drop_request(req->queue, req);
347 if (client != NULL && req->delayed_error != NULL)
348 http_client_remove_request_error(req->client, req);
349 req->delayed_error = NULL;
351 if (req->destroy_callback != NULL) {
352 void (*callback)(void *) = req->destroy_callback;
354 req->destroy_callback = NULL;
355 callback(req->destroy_context);
358 if (req->conn != NULL)
359 http_client_connection_request_destroyed(req->conn, req);
361 tmp_req = req;
362 http_client_request_remove(req);
364 req->client = NULL;
367 void http_client_request_set_port(struct http_client_request *req,
370 i_assert(req->state == HTTP_REQUEST_STATE_NEW);
371 req->origin_url.port = port;
372 event_add_int(req->event, "port", port);
375 void http_client_request_set_ssl(struct http_client_request *req,
378 i_assert(req->state == HTTP_REQUEST_STATE_NEW);
379 req->origin_url.have_ssl = ssl;
382 void http_client_request_set_urgent(struct http_client_request *req)
384 i_assert(req->state == HTTP_REQUEST_STATE_NEW);
385 req->urgent = TRUE;
388 void http_client_request_set_preserve_exact_reason(struct http_client_request *req)
390 req->preserve_exact_reason = TRUE;
393 void http_client_request_add_header(struct http_client_request *req,
396 i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
398 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE ||
399 req->state == HTTP_REQUEST_STATE_ABORTED);
408 req->have_hdr_authorization = TRUE;
412 req->have_hdr_connection = TRUE;
414 req->have_hdr_body_spec = TRUE;
418 req->have_hdr_date = TRUE;
422 req->have_hdr_expect = TRUE;
426 req->have_hdr_host = TRUE;
433 req->have_hdr_body_spec = TRUE;
437 req->have_hdr_user_agent = TRUE;
440 if (req->headers == NULL)
441 req->headers = str_new(default_pool, 256);
442 str_printfa(req->headers, "%s: %s\r\n", key, value);
445 void http_client_request_remove_header(struct http_client_request *req,
452 i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
454 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE ||
455 req->state == HTTP_REQUEST_STATE_ABORTED);
457 data = str_data(req->headers);
458 size = str_len(req->headers);
464 line_start_pos = str_len(req->headers) - size;
465 str_delete(req->headers, line_start_pos, line_len);
473 void http_client_request_set_date(struct http_client_request *req,
476 i_assert(req->state == HTTP_REQUEST_STATE_NEW);
477 req->date = date;
480 void http_client_request_set_payload(struct http_client_request *req,
485 i_assert(req->state == HTTP_REQUEST_STATE_NEW);
486 i_assert(req->payload_input == NULL);
489 req->payload_input = input;
490 if ((ret = i_stream_get_size(input, TRUE, &req->payload_size)) <= 0) {
496 req->payload_size = 0;
497 req->payload_chunked = TRUE;
499 req->payload_offset = input->v_offset;
502 if ((req->payload_chunked || req->payload_size > 0) && sync)
503 req->payload_sync = TRUE;
506 void http_client_request_set_payload_data(struct http_client_request *req,
515 payload_data = p_malloc(req->pool, size);
519 http_client_request_set_payload(req, input, FALSE);
523 void http_client_request_set_payload_empty(struct http_client_request *req)
525 req->payload_empty = TRUE;
528 void http_client_request_set_timeout_msecs(struct http_client_request *req,
531 i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
532 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
534 req->timeout_msecs = msecs;
537 void http_client_request_set_timeout(struct http_client_request *req,
540 i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
541 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
543 req->timeout_time = *time;
544 req->timeout_msecs = 0;
547 void http_client_request_set_attempt_timeout_msecs(struct http_client_request *req,
550 i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
551 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
553 req->attempt_timeout_msecs = msecs;
556 void http_client_request_set_max_attempts(struct http_client_request *req,
559 i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
560 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
562 req->max_attempts = max_attempts;
565 void http_client_request_set_auth_simple(struct http_client_request *req,
568 req->username = p_strdup(req->pool, username);
569 req->password = p_strdup(req->pool, password);
572 void http_client_request_set_proxy_url(struct http_client_request *req,
575 i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
576 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
578 req->host_url = http_url_clone_authority(req->pool, proxy_url);
579 req->host_socket = NULL;
582 void http_client_request_set_proxy_socket(struct http_client_request *req,
585 i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
586 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
588 req->host_socket = p_strdup(req->pool, proxy_socket);
589 req->host_url = NULL;
592 void http_client_request_delay_until(struct http_client_request *req,
595 req->release_time.tv_sec = time;
596 req->release_time.tv_usec = 0;
599 void http_client_request_delay(struct http_client_request *req,
602 req->release_time = ioloop_timeval;
603 req->release_time.tv_sec += seconds;
606 void http_client_request_delay_msecs(struct http_client_request *req,
609 req->release_time = ioloop_timeval;
610 timeval_add_msecs(&req->release_time, msecs);
613 int http_client_request_delay_from_response(struct http_client_request *req,
619 i_assert(req->client != NULL);
625 max = (req->client->set.max_auto_retry_delay == 0 ?
626 req->attempt_timeout_msecs / 1000 :
627 req->client->set.max_auto_retry_delay);
630 req->release_time.tv_sec = retry_after;
631 req->release_time.tv_usec = 0;
636 http_client_request_get_method(const struct http_client_request *req)
638 return req->method;
642 http_client_request_get_target(const struct http_client_request *req)
644 return req->target;
648 http_client_request_get_state(const struct http_client_request *req)
650 return req->state;
653 void http_client_request_get_stats(struct http_client_request *req,
656 struct http_client *client = req->client;
661 if (!req->submitted)
665 diff_msecs = timeval_diff_msecs(&ioloop_timeval, &req->submit_time);
669 if (req->first_sent_time.tv_sec > 0) {
670 diff_msecs = timeval_diff_msecs(&ioloop_timeval, &req->first_sent_time);
675 if (req->sent_time.tv_sec > 0) {
676 diff_msecs = timeval_diff_msecs(&ioloop_timeval, &req->sent_time);
680 if (req->conn != NULL) {
682 i_assert(ioloop_global_wait_usecs >= req->sent_global_ioloop_usecs);
684 (ioloop_global_wait_usecs - req->sent_global_ioloop_usecs + 999) / 1000;
688 wait_usecs = io_wait_timer_get_usecs(req->conn->io_wait_timer);
689 i_assert(wait_usecs >= req->sent_http_ioloop_usecs);
691 (wait_usecs - req->sent_http_ioloop_usecs + 999) / 1000;
700 i_assert(wait_usecs >= req->sent_lock_usecs);
702 (wait_usecs - req->sent_lock_usecs + 999) / 1000;
705 stats_r->attempts = req->attempts;
707 stats_r->send_attempts = req->send_attempts;
710 void http_client_request_append_stats_text(struct http_client_request *req,
715 if (!req->submitted) {
720 http_client_request_get_stats(req, &stats);
755 http_client_request_get_payload_type(struct http_client_request *req)
770 if (strcmp(req->method, "HEAD") == 0)
772 if (strcmp(req->method, "CONNECT") == 0)
777 static void http_client_request_do_submit(struct http_client_request *req)
779 struct http_client *client = req->client;
784 (req->host_socket != NULL) || (req->host_url != NULL);
787 if (req->state == HTTP_REQUEST_STATE_ABORTED)
790 i_assert(req->state == HTTP_REQUEST_STATE_NEW);
792 authority = http_url_create_authority(&req->origin_url);
793 if (req->connect_tunnel) {
799 (http_url_create_host(&req->origin_url), req->target, NULL);
804 if (req->host_socket != NULL) { /* specific socket proxy */
805 req->host_url = NULL;
806 } else if (req->host_url != NULL) { /* specific normal proxy */
807 req->host_socket = NULL;
808 } else if (req->origin_url.have_ssl &&
809 !client->set.no_ssl_tunnel && !req->connect_tunnel) {
810 req->host_url = &req->origin_url; /* tunnel to origin server */
811 req->ssl_tunnel = TRUE;
813 req->host_socket = proxy_socket_path; /* proxy on unix socket */
814 req->host_url = NULL;
816 req->host_url = proxy_url; /* normal proxy server */
817 req->host_socket = NULL;
820 req->host_url = &req->origin_url; /* origin server */
824 if (req->date == (time_t)-1)
825 req->date = ioloop_time;
828 req->authority = p_strdup(req->pool, authority);
831 req->label = p_strdup_printf(req->pool, "[Req%u: %s %s]", req->id, req->method, target);
834 if (req->connect_tunnel || have_proxy)
835 req->target = p_strdup(req->pool, target);
840 req->connect_direct = req->connect_tunnel;
841 if (req->connect_direct)
842 req->urgent = TRUE;
845 if (req->timeout_time.tv_sec == 0) {
846 if (req->timeout_msecs > 0) {
847 req->timeout_time = ioloop_timeval;
848 timeval_add_msecs(&req->timeout_time, req->timeout_msecs);
850 req->timeout_time = ioloop_timeval;
851 timeval_add_msecs(&req->timeout_time, client->set.request_absolute_timeout_msecs);
855 host = http_client_host_get(client, req->host_url);
856 req->state = HTTP_REQUEST_STATE_QUEUED;
857 req->last_status = 0;
859 http_client_host_submit_request(host, req);
862 void http_client_request_submit(struct http_client_request *req)
864 i_assert(req->client != NULL);
866 req->submit_time = ioloop_timeval;
868 http_client_request_do_submit(req);
870 req->submitted = TRUE;
871 http_client_request_add(req);
873 e_debug(req->event, "Submitted (requests left=%d)",
874 req->client->requests_count);
878 http_client_request_get_peer_addr(const struct http_client_request *req,
881 const char *host_socket = req->host_socket;
882 const struct http_url *host_url = req->host_url;
891 } else if (req->connect_direct) {
897 if (req->ssl_tunnel)
912 http_client_request_finish_payload_out(struct http_client_request *req)
914 struct http_client_connection *conn = req->conn;
919 if (req->payload_output != NULL) {
920 o_stream_unref(&req->payload_output);
921 req->payload_output = NULL;
924 i_assert(req->request_offset < conn->conn.output->offset);
925 req->bytes_out = conn->conn.output->offset - req->request_offset;
928 if (req->state != HTTP_REQUEST_STATE_ABORTED) {
929 i_assert(req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
932 req->state = HTTP_REQUEST_STATE_WAITING;
939 e_debug(req->event, "Finished sending%s payload",
940 (req->state == HTTP_REQUEST_STATE_ABORTED ? " aborted" : ""));
948 struct http_client_request *req = *_req;
949 struct http_client_connection *conn = req->conn;
950 struct http_client *client = req->client;
954 i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
955 req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
956 i_assert(req->payload_input == NULL);
960 http_client_request_ref(req);
961 req->payload_wait = TRUE;
964 req->payload_input = NULL;
965 if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT)
966 http_client_request_finish_payload_out(req);
968 req->payload_input = i_stream_create_from_data(data, size);
969 i_stream_set_name(req->payload_input, "<HTTP request payload>");
971 req->payload_size = 0;
972 req->payload_chunked = TRUE;
974 if (req->state == HTTP_REQUEST_STATE_NEW)
975 http_client_request_submit(req);
976 if (req->state == HTTP_REQUEST_STATE_ABORTED) {
978 if (req->delayed_error != NULL) {
979 struct http_client_request *tmpreq = req;
987 http_client_remove_request_error(client, req);
1000 while (req->state < HTTP_REQUEST_STATE_PAYLOAD_IN) {
1001 e_debug(req->event, "Waiting for request to finish");
1003 if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT)
1004 o_stream_set_flush_pending(req->payload_output, TRUE);
1008 if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT &&
1009 req->payload_input->eof) {
1010 i_stream_unref(&req->payload_input);
1011 req->payload_input = NULL;
1028 switch (req->state) {
1041 req->payload_wait = FALSE;
1045 if (!http_client_request_unref(&req))
1058 struct http_client_request *req = *_req;
1063 ret = http_client_request_continue_payload(&req, data, size);
1074 i_assert(req != NULL);
1081 struct http_client_request *req = *_req;
1085 ret = http_client_request_continue_payload(&req, NULL, 0);
1090 static void http_client_request_payload_input(struct http_client_request *req)
1092 struct http_client_connection *conn = req->conn;
1099 int http_client_request_send_more(struct http_client_request *req,
1102 struct http_client_connection *conn = req->conn;
1104 struct ostream *output = req->payload_output;
1109 i_assert(req->payload_input != NULL);
1110 i_assert(req->payload_output != NULL);
1115 offset = req->payload_input->v_offset;
1117 res = o_stream_send_istream(output, req->payload_input);
1120 i_assert(req->payload_input->v_offset >= offset);
1121 e_debug(req->event, "Send more (sent %"PRIuUOFF_T", buffered=%"PRIuSIZE_T")",
1122 (uoff_t)(req->payload_input->v_offset - offset),
1128 if (!req->payload_chunked &&
1129 req->payload_input->v_offset - req->payload_offset != req->payload_size) {
1132 i_stream_get_name(req->payload_input),
1133 req->payload_input->v_offset, req->payload_offset, req->payload_size);
1139 if (req->payload_wait) {
1145 if (req->client != NULL && req->client->waiting)
1146 io_loop_stop(req->client->ioloop);
1149 http_client_request_finish_payload_out(req);
1158 cctx->ioloop, req->payload_input,
1159 http_client_request_payload_input, req);
1166 e_debug(req->event, "Partially sent payload");
1172 i_stream_get_name(req->payload_input),
1173 i_stream_get_error(req->payload_input));
1177 http_client_request_error(&req,
1191 static int http_client_request_send_real(struct http_client_request *req,
1194 const struct http_client_settings *set = &req->client->set;
1195 struct http_client_connection *conn = req->conn;
1199 i_assert(!req->conn->output_locked);
1200 i_assert(req->payload_output == NULL);
1203 str_append(rtext, req->method);
1205 str_append(rtext, req->target);
1210 if (!req->have_hdr_host) {
1212 str_append(rtext, req->authority);
1215 if (!req->have_hdr_date) {
1217 str_append(rtext, http_date_create(req->date));
1220 if (!req->have_hdr_authorization &&
1221 req->username != NULL && req->password != NULL) {
1225 req->username, req->password);
1231 if (http_client_request_to_proxy(req) &&
1242 if (!req->have_hdr_user_agent && req->client->set.user_agent != NULL) {
1244 req->client->set.user_agent);
1246 if (!req->have_hdr_expect && req->payload_sync) {
1249 if (req->payload_input != NULL && req->payload_chunked) {
1251 if (!req->have_hdr_body_spec)
1253 req->payload_output =
1255 } else if (req->payload_input != NULL ||
1256 req->payload_empty ||
1257 strcasecmp(req->method, "POST") == 0 ||
1258 strcasecmp(req->method, "PUT") == 0) {
1262 i_assert(req->payload_input != NULL || req->payload_size == 0);
1263 if (!req->have_hdr_body_spec) {
1265 req->payload_size);
1267 if (req->payload_input != NULL) {
1268 req->payload_output = conn->conn.output;
1272 if (!req->have_hdr_connection &&
1273 !http_client_request_to_proxy(req)) {
1288 if (req->headers != NULL) {
1289 iov[1].iov_base = str_data(req->headers);
1290 iov[1].iov_len = str_len(req->headers);
1299 req->state = HTTP_REQUEST_STATE_PAYLOAD_OUT;
1300 req->send_attempts++;
1301 if (req->first_sent_time.tv_sec == 0)
1302 req->first_sent_time = ioloop_timeval;
1303 req->sent_time = ioloop_timeval;
1304 req->sent_lock_usecs = file_lock_wait_get_total_usecs();
1305 req->sent_global_ioloop_usecs = ioloop_global_wait_usecs;
1306 req->sent_http_ioloop_usecs =
1307 io_wait_timer_get_usecs(req->conn->io_wait_timer);
1309 req->request_offset = conn->conn.output->offset;
1315 e_debug(req->event, "Sent header");
1317 if (req->payload_output != NULL) {
1318 if (!req->payload_sync) {
1319 if (http_client_request_send_more(req, pipelined) < 0)
1322 e_debug(req->event, "Waiting for 100-continue");
1326 req->state = HTTP_REQUEST_STATE_WAITING;
1328 http_client_connection_start_request_timeout(req->conn);
1332 i_assert(req->request_offset < conn->conn.output->offset);
1333 req->bytes_out = conn->conn.output->offset - req->request_offset;
1342 int http_client_request_send(struct http_client_request *req,
1348 ret = http_client_request_send_real(req, pipelined);
1354 bool http_client_request_callback(struct http_client_request *req,
1357 http_client_request_callback_t *callback = req->callback;
1358 unsigned int orig_attempts = req->attempts;
1360 req->state = HTTP_REQUEST_STATE_GOT_RESPONSE;
1361 req->last_status = response->status;
1363 req->callback = NULL;
1367 if (req->attempts > 0 && !req->preserve_exact_reason) {
1369 timeval_diff_msecs(&ioloop_timeval, &req->submit_time);
1372 response_copy.reason, req->attempts,
1376 callback(&response_copy, req->context);
1377 if (req->attempts != orig_attempts) {
1379 req->callback = callback;
1380 http_client_request_resubmit(req);
1384 i_stream_unref(&req->payload_input);
1391 http_client_request_send_error(struct http_client_request *req,
1395 bool sending = (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
1396 unsigned int orig_attempts = req->attempts;
1398 req->state = HTTP_REQUEST_STATE_ABORTED;
1400 callback = req->callback;
1401 req->callback = NULL;
1406 (void)callback(&response, req->context);
1408 if (req->attempts != orig_attempts) {
1410 req->callback = callback;
1411 http_client_request_resubmit(req);
1415 if (!sending && req->payload_input != NULL)
1416 i_stream_unref(&req->payload_input);
1419 if (req->payload_wait) {
1420 i_assert(req->client != NULL);
1421 io_loop_stop(req->client->ioloop);
1428 struct http_client_request *req = *_req;
1429 const char *error = req->delayed_error;
1430 unsigned int status = req->delayed_error_status;
1433 i_assert(req->state == HTTP_REQUEST_STATE_ABORTED);
1436 req->delayed_error = NULL;
1437 req->delayed_error_status = 0;
1440 destroy = http_client_request_send_error(req, status, error);
1441 if (req->queue != NULL)
1442 http_client_queue_drop_request(req->queue, req);
1444 http_client_request_destroy(&req);
1450 struct http_client_request *req = *_req;
1454 i_assert(req->delayed_error_status == 0);
1455 i_assert(req->state < HTTP_REQUEST_STATE_FINISHED);
1457 req->state = HTTP_REQUEST_STATE_ABORTED;
1458 req->last_status = status;
1460 e_debug(http_client_request_result_event(req)->
1464 if (req->queue != NULL)
1465 http_client_queue_drop_request(req->queue, req);
1467 if (req->client != NULL && (!req->submitted ||
1468 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE)) {
1472 req->delayed_error = p_strdup(req->pool, error);
1473 req->delayed_error_status = status;
1474 http_client_delay_request_error(req->client, req);
1476 if (http_client_request_send_error(req, status, error))
1477 http_client_request_destroy(&req);
1483 struct http_client_request *req = *_req;
1484 bool sending = (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
1488 if (req->state >= HTTP_REQUEST_STATE_FINISHED &&
1489 req->delayed_error_status == 0)
1492 req->callback = NULL;
1493 req->state = HTTP_REQUEST_STATE_ABORTED;
1494 if (req->last_status == 0)
1495 req->last_status = HTTP_CLIENT_REQUEST_ERROR_ABORTED;
1497 if (req->state > HTTP_REQUEST_STATE_NEW &&
1498 req->delayed_error_status == 0) {
1499 e_debug(http_client_request_result_event(req)->
1505 if (!sending && req->payload_input != NULL)
1506 i_stream_unref(&req->payload_input);
1508 if (req->queue != NULL)
1509 http_client_queue_drop_request(req->queue, req);
1510 if (req->payload_wait) {
1511 i_assert(req->client != NULL);
1512 i_assert(req->client->ioloop != NULL);
1513 io_loop_stop(req->client->ioloop);
1515 http_client_request_destroy(&req);
1518 void http_client_request_finish(struct http_client_request *req)
1520 if (req->state >= HTTP_REQUEST_STATE_FINISHED)
1523 i_assert(req->refcount > 0);
1525 e_debug(http_client_request_result_event(req)->
1529 req->callback = NULL;
1530 req->state = HTTP_REQUEST_STATE_FINISHED;
1532 if (req->queue != NULL)
1533 http_client_queue_drop_request(req->queue, req);
1534 if (req->payload_wait) {
1535 i_assert(req->client != NULL);
1536 i_assert(req->client->ioloop != NULL);
1537 io_loop_stop(req->client->ioloop);
1539 http_client_request_unref(&req);
1542 void http_client_request_redirect(struct http_client_request *req,
1548 i_assert(req->client != NULL);
1549 i_assert(!req->payload_wait);
1551 req->last_status = status;
1556 http_client_request_error(&req, HTTP_CLIENT_REQUEST_ERROR_INVALID_REDIRECT,
1561 i_assert(req->redirects <= req->client->set.max_redirects);
1562 if (++req->redirects > req->client->set.max_redirects) {
1563 if (req->client->set.max_redirects > 0) {
1564 http_client_request_error(&req,
1567 req->client->set.max_redirects));
1569 http_client_request_error(&req,
1577 if (req->payload_input != NULL && req->payload_size > 0 && status != 303) {
1578 if (req->payload_input->v_offset != req->payload_offset &&
1579 !req->payload_input->seekable) {
1580 http_client_request_error(&req,
1585 i_stream_seek(req->payload_input, req->payload_offset);
1590 o_stream_unref(&req->payload_output);
1594 http_url_copy(req->pool, &req->origin_url, url);
1595 req->target = p_strdup(req->pool, target);
1597 req->host = NULL;
1599 origin_url = http_url_create(&req->origin_url);
1601 e_debug(http_client_request_result_event(req)->
1604 origin_url, target, req->redirects);
1606 req->label = p_strdup_printf(req->pool, "[%s %s%s]",
1607 req->method, origin_url, req->target);
1615 if (status == 303 && strcasecmp(req->method, "HEAD") != 0 &&
1616 strcasecmp(req->method, "GET") != 0) {
1619 req->method = p_strdup(req->pool, "GET");
1622 i_stream_unref(&req->payload_input);
1623 req->payload_size = 0;
1624 req->payload_offset = 0;
1628 req->state = HTTP_REQUEST_STATE_NEW;
1629 http_client_request_do_submit(req);
1632 void http_client_request_resubmit(struct http_client_request *req)
1634 i_assert(!req->payload_wait);
1636 e_debug(req->event, "Resubmitting request");
1639 if (req->payload_input != NULL && req->payload_size > 0) {
1640 if (req->payload_input->v_offset != req->payload_offset &&
1641 !req->payload_input->seekable) {
1642 http_client_request_error(&req,
1647 i_stream_seek(req->payload_input, req->payload_offset);
1652 o_stream_unref(&req->payload_output);
1654 req->peer = NULL;
1655 req->state = HTTP_REQUEST_STATE_QUEUED;
1656 req->redirects = 0;
1657 req->last_status = 0;
1658 http_client_host_submit_request(req->host, req);
1661 void http_client_request_retry(struct http_client_request *req,
1664 if (!http_client_request_try_retry(req))
1665 http_client_request_error(&req, status, error);
1668 bool http_client_request_try_retry(struct http_client_request *req)
1674 if (req->payload_wait &&
1675 (!req->payload_sync || req->payload_sync_continue))
1678 if (req->attempts+1 >= req->max_attempts)
1680 req->attempts++;
1682 e_debug(http_client_request_result_event(req)->
1684 "Retrying (attempts=%d)", req->attempts);
1686 if (req->callback != NULL)
1687 http_client_request_resubmit(req);
1692 void http_client_request_set_destroy_callback(struct http_client_request *req,
1696 req->destroy_callback = callback;
1697 req->destroy_context = context;
1700 void http_client_request_start_tunnel(struct http_client_request *req,
1703 struct http_client_connection *conn = req->conn;
1705 i_assert(req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);