void HttpStack::handler_callback(evhtp_request_t* req, HttpStack::ControllerInterface* controller) { Request request(this, req); // Call into the controller to request a SAS logger that can be used to log // this request. Then actually log the request. request.set_sas_logger(controller->sas_logger(request)); SAS::TrailId trail = SAS::new_trail(0); request.sas_log_rx_http_req(trail, 0); if (_stats != NULL) { _stats->incr_http_incoming_requests(); } if ((_load_monitor == NULL) || _load_monitor->admit_request()) { // Pause the request processing (which stops it from being cancelled), as we // may process this request asynchronously. The // HttpStack::Request::send_reply method resumes. evhtp_request_pause(req); // Pass the request to the controller. LOG_VERBOSE("Process request for URL %s, args %s", req->uri->path->full, req->uri->query_raw); controller->process_request(request, trail); } else { request.sas_log_overload(trail, 503, 0); send_reply_internal(request, 503, trail); if (_stats != NULL) { _stats->incr_http_rejected_overload(); } } }
static void frontend_cb(evhtp_request_t * req, void * arg) { int * aux; int thr; aux = (int *)evthr_get_aux(req->conn->thread); thr = *aux; printf(" Received frontend request on thread %d... ", thr); /* Pause the frontend request while we run the backend requests. */ evhtp_request_pause(req); make_request(evthr_get_base(req->conn->thread), req->conn->thread, "127.0.0.1", 80, req->uri->path->full, req->headers_in, backend_cb, req); printf("Ok.\n"); }
static evhtp_res upload_headers_cb (evhtp_request_t *req, evhtp_headers_t *hdr, void *arg) { SearpcClient *rpc_client = NULL; char *token, *repo_id = NULL, *user = NULL; char *boundary = NULL; gint64 content_len; char *progress_id = NULL; char *err_msg = NULL; RecvFSM *fsm = NULL; Progress *progress = NULL; /* URL format: http://host:port/[upload|update]/<token>?X-Progress-ID=<uuid> */ token = req->uri->path->file; if (!token) { seaf_warning ("[upload] No token in url.\n"); err_msg = "Invalid URL"; goto err; } rpc_client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "seafserv-rpcserver"); if (check_access_token (rpc_client, token, &repo_id, &user) < 0) { seaf_warning ("[upload] Invalid token.\n"); err_msg = "Access denied"; goto err; } boundary = get_boundary (hdr); if (!boundary) { goto err; } if (get_progress_info (req, hdr, &content_len, &progress_id) < 0) goto err; progress = g_new0 (Progress, 1); progress->size = content_len; fsm = g_new0 (RecvFSM, 1); fsm->boundary = boundary; fsm->repo_id = repo_id; fsm->user = user; fsm->line = evbuffer_new (); fsm->form_kvs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); fsm->progress_id = progress_id; fsm->progress = progress; pthread_mutex_lock (&pg_lock); g_hash_table_insert (upload_progress, g_strdup(progress_id), progress); pthread_mutex_unlock (&pg_lock); /* Set up per-request hooks, so that we can read file data piece by piece. */ evhtp_set_hook (&req->hooks, evhtp_hook_on_read, upload_read_cb, fsm); evhtp_set_hook (&req->hooks, evhtp_hook_on_request_fini, upload_finish_cb, fsm); /* Set arg for upload_cb or update_cb. */ req->cbarg = fsm; ccnet_rpc_client_free (rpc_client); return EVHTP_RES_OK; err: /* Don't receive any data before the connection is closed. */ evhtp_request_pause (req); /* Set keepalive to 0. This will cause evhtp to close the * connection after sending the reply. */ req->keepalive = 0; if (err_msg) evbuffer_add_printf (req->buffer_out, "%s\n", err_msg); evhtp_send_reply (req, EVHTP_RES_BADREQ); if (rpc_client) ccnet_rpc_client_free (rpc_client); g_free (repo_id); g_free (user); g_free (boundary); return EVHTP_RES_OK; }
/* Example multipart form-data request content format: --AaB03x Content-Disposition: form-data; name="submit-name" Larry --AaB03x Content-Disposition: form-data; name="file"; filename="file1.txt" Content-Type: text/plain ... contents of file1.txt ... --AaB03x-- */ static evhtp_res upload_read_cb (evhtp_request_t *req, evbuf_t *buf, void *arg) { RecvFSM *fsm = arg; char *line; size_t len; gboolean no_line = FALSE; int res = EVHTP_RES_OK; if (fsm->state == RECV_ERROR) return EVHTP_RES_OK; /* Update upload progress. */ fsm->progress->uploaded += (gint64)evbuffer_get_length(buf); seaf_debug ("progress: %lld/%lld\n", fsm->progress->uploaded, fsm->progress->size); evbuffer_add_buffer (fsm->line, buf); /* Drain the buffer so that evhtp don't copy it to another buffer * after this callback returns. */ evbuffer_drain (buf, evbuffer_get_length (buf)); while (!no_line) { switch (fsm->state) { case RECV_INIT: line = evbuffer_readln (fsm->line, &len, EVBUFFER_EOL_CRLF_STRICT); if (line != NULL) { seaf_debug ("[upload] boundary line: %s.\n", line); if (!strstr (line, fsm->boundary)) { seaf_warning ("[upload] no boundary found in the first line.\n"); free (line); res = EVHTP_RES_BADREQ; goto out; } else { fsm->state = RECV_HEADERS; free (line); } } else { no_line = TRUE; } break; case RECV_HEADERS: line = evbuffer_readln (fsm->line, &len, EVBUFFER_EOL_CRLF_STRICT); if (line != NULL) { seaf_debug ("[upload] mime header line: %s.\n", line); if (len == 0) { /* Read an blank line, headers end. */ free (line); if (g_strcmp0 (fsm->input_name, "file") == 0) { if (open_temp_file (fsm) < 0) { seaf_warning ("[upload] Failed open temp file.\n"); res = EVHTP_RES_SERVERR; goto out; } } seaf_debug ("[upload] Start to recv %s.\n", fsm->input_name); fsm->state = RECV_CONTENT; } else if (parse_mime_header (line, fsm) < 0) { free (line); res = EVHTP_RES_BADREQ; goto out; } else { free (line); } } else { no_line = TRUE; } break; case RECV_CONTENT: if (g_strcmp0 (fsm->input_name, "file") == 0) res = recv_file_data (fsm, &no_line); else res = recv_form_field (fsm, &no_line); if (res != EVHTP_RES_OK) goto out; break; } } out: if (res != EVHTP_RES_OK) { /* Don't receive any data before the connection is closed. */ evhtp_request_pause (req); /* Set keepalive to 0. This will cause evhtp to close the * connection after sending the reply. */ req->keepalive = 0; fsm->state = RECV_ERROR; } if (res == EVHTP_RES_BADREQ) { evhtp_send_reply (req, EVHTP_RES_BADREQ); } else if (res == EVHTP_RES_SERVERR) { evbuffer_add_printf (req->buffer_out, "Internal server error\n"); evhtp_send_reply (req, EVHTP_RES_SERVERR); } return EVHTP_RES_OK; }