const char * ghttp_get_header(ghttp_request *a_request, const char *a_hdr) { return http_hdr_get_value(a_request->resp->headers, a_hdr); }
int http_req_prepare(http_req *a_req) { int l_return = 0; char l_buf[30]; if (!a_req) return -1; memset(l_buf, 0, 30); /* set the host header */ http_hdr_set_value(a_req->headers, http_hdr_Host, a_req->host); /* check to see if we have an entity body */ if ((a_req->type == http_req_type_post) || (a_req->type == http_req_type_put) || (a_req->type == http_req_type_trace)) { sprintf(l_buf, "%d", a_req->body_len); http_hdr_set_value(a_req->headers, http_hdr_Content_Length, l_buf); } /* if the user agent isn't set then set a default */ if (http_hdr_get_value(a_req->headers, http_hdr_User_Agent) == NULL) http_hdr_set_value(a_req->headers, http_hdr_User_Agent, "libghttp/1.0"); return l_return; }
int http_hdr_set_value(http_hdr_list *a_list, const char *a_name, const char *a_val) { int i = 0; char *l_temp_value = NULL; int l_return = 0; if ((a_list == NULL) || (a_name == NULL) || (a_val == NULL)) goto ec; l_temp_value = http_hdr_get_value(a_list, a_name); if (l_temp_value == NULL) { for (i = 0; i < HTTP_HDRS_MAX; i++) { if (a_list->header[i] == NULL) { /* I promise not to mess with this value. */ l_temp_value = (char *)http_hdr_is_known(a_name); if (l_temp_value) { a_list->header[i] = l_temp_value; /* dont free this later... */ } else a_list->header[i] = strdup(a_name); a_list->value[i] = strdup(a_val); l_return = 1; break; } } } else { for (i = 0; i < HTTP_HDRS_MAX; i++) { if (a_list->value[i] == l_temp_value) { free(a_list->value[i]); a_list->value[i] = strdup(a_val); l_return = 1; break; } } } ec: return l_return; }
int http_req_send(http_req *a_req, http_trans_conn *a_conn) { char *l_request = NULL; int l_request_len = 0; int i = 0; int l_len = 0; int l_headers_len = 0; int l_rv = 0; char *l_content = NULL; /* see if we need to jump into the function somewhere */ if (a_conn->sync == HTTP_TRANS_ASYNC) { if (a_req->state == http_req_state_sending_request) goto http_req_state_sending_request_jump; if (a_req->state == http_req_state_sending_headers) goto http_req_state_sending_headers_jump; if (a_req->state == http_req_state_sending_body) goto http_req_state_sending_body_jump; } /* enough for the request and the other little headers */ l_request = malloc(30 + strlen(a_req->resource) + (a_conn->proxy_host ? (strlen(a_req->host) + 20) : 0)); memset(l_request, 0, 30 + strlen(a_req->resource) + (a_conn->proxy_host ? (strlen(a_req->host) + 20) : 0)); /* copy it into the buffer */ if (a_conn->proxy_host) { l_request_len = sprintf(l_request, "%s %s HTTP/%01.1f\r\n", http_req_type_char[a_req->type], a_req->full_uri, a_req->http_ver); } else { l_request_len = sprintf(l_request, "%s %s HTTP/%01.1f\r\n", http_req_type_char[a_req->type], a_req->resource, a_req->http_ver); } /* set the request in the connection buffer */ http_trans_append_data_to_buf(a_conn, l_request, l_request_len); /* free up the request - we don't need it anymore */ free(l_request); l_request = NULL; /* set the state */ a_req->state = http_req_state_sending_request; http_req_state_sending_request_jump: /* send the request */ do { l_rv = http_trans_write_buf(a_conn); if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE)) return HTTP_TRANS_NOT_DONE; if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0)) return HTTP_TRANS_ERR; } while (l_rv == HTTP_TRANS_NOT_DONE); /* reset the buffer */ http_trans_buf_reset(a_conn); /* set up all of the headers */ for (i = 0; i < HTTP_HDRS_MAX; i++) { l_len = 0; if (a_req->headers->header[i]) { l_len = strlen(a_req->headers->header[i]); if (l_len > 0) { http_trans_append_data_to_buf(a_conn, a_req->headers->header[i], l_len); l_headers_len += l_len; http_trans_append_data_to_buf(a_conn, ": ", 2); l_headers_len += 2; /* note, it's ok to have no value for a request */ if ((l_len = strlen(a_req->headers->value[i])) > 0) { http_trans_append_data_to_buf(a_conn, a_req->headers->value[i], l_len); l_headers_len += l_len; } http_trans_append_data_to_buf(a_conn, "\r\n", 2); l_headers_len += 2; } } } http_trans_append_data_to_buf(a_conn, "\r\n", 2); l_headers_len += 2; /* set the state */ a_req->state = http_req_state_sending_headers; http_req_state_sending_headers_jump: /* blast that out to the network */ do { l_rv = http_trans_write_buf(a_conn); if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE)) return HTTP_TRANS_NOT_DONE; if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0)) return HTTP_TRANS_ERR; } while (l_rv == HTTP_TRANS_NOT_DONE); /* reset the buffer */ http_trans_buf_reset(a_conn); l_content = http_hdr_get_value(a_req->headers, http_hdr_Content_Length); if (l_content) { /* append the information to the buffer */ http_trans_append_data_to_buf(a_conn, a_req->body, a_req->body_len); a_req->state = http_req_state_sending_body; http_req_state_sending_body_jump: do { l_rv = http_trans_write_buf(a_conn); if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE)) return HTTP_TRANS_NOT_DONE; if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0)) return HTTP_TRANS_ERR; } while (l_rv == HTTP_TRANS_NOT_DONE); /* reset the buffer */ http_trans_buf_reset(a_conn); } return HTTP_TRANS_DONE; }
int http_resp_read_body(http_resp *a_resp, http_req *a_req, http_trans_conn *a_conn) { int l_return = 0; char *l_content_length = NULL; char *l_transfer_encoding = NULL; char *l_connection = NULL; if ((!a_resp) || (!a_conn)) return -1; a_conn->io_buf_flush_en = 1; ghttpDebug("a_req->type: %d \n", a_req->type); /* check to see if we have to jump in anywhere. */ if (a_conn->sync == HTTP_TRANS_ASYNC) { ghttpDebug("body_state: %d \n", a_resp->body_state); if (a_resp->body_state == http_resp_body_read_content_length) goto http_resp_body_read_content_length_jump; if (a_resp->body_state == http_resp_body_read_chunked) goto http_resp_body_read_chunked_jump; if (a_resp->body_state == http_resp_body_read_standard) goto http_resp_body_read_standard_jump; } /* check to see if there should be an entity body. */ /* check to see if there's a content length */ l_content_length = http_hdr_get_value(a_resp->headers, http_hdr_Content_Length); /* check to see if there's a transfer encoding */ l_transfer_encoding = http_hdr_get_value(a_resp->headers, http_hdr_Transfer_Encoding); /* check to see if the connection header is set */ l_connection = http_hdr_get_value(a_resp->headers, http_hdr_Connection); ghttpDebug("content_length: %s \n", l_content_length ? l_content_length : "null"); ghttpDebug("transfer_encoding: %s \n", l_transfer_encoding ? l_transfer_encoding : "null"); ghttpDebug("connection: %s \n", l_connection ? l_connection : "null"); /* if there's a content length, do your stuff */ if (l_content_length && (a_req->type != http_req_type_head)) { if (string_is_number(l_content_length) == 0) { a_conn->errstr = "Content length in http response was not a number"; return -1; } a_resp->content_length = atoi(l_content_length); /* set the state */ a_resp->body_state = http_resp_body_read_content_length; http_resp_body_read_content_length_jump: ghttpDebug("read_body_content_length ... \n"); l_return = read_body_content_length(a_resp, a_req, a_conn); } else if (l_content_length) { /* this happens in a head request with content length. */ return HTTP_TRANS_DONE; } else if (l_transfer_encoding) { /* check to see if it's using chunked transfer encoding */ if (!strcasecmp(l_transfer_encoding, "chunked")) { /* set the state */ a_resp->body_state = http_resp_body_read_chunked; http_resp_body_read_chunked_jump: ghttpDebug("read_body_chunked ... \n"); l_return = read_body_chunked(a_resp, a_req, a_conn); ghttpDebug("l_return: %d \n", l_return); } else { /* what kind of encoding? */ a_conn->errstr = "Unknown encoding type in http response"; return -1; } } else { a_resp->body_state = http_resp_body_read_standard; /* set the state */ http_resp_body_read_standard_jump: ghttpDebug("read_body_standard ... \n"); l_return = read_body_standard(a_resp, a_req, a_conn); /* after that the connection gets closed */ if (l_return == HTTP_TRANS_DONE) { ghttpDebug("close connection \n"); close(a_conn->sock); a_conn->sock = -1; } } /* check to see if the connection should be closed */ if (l_connection && (l_return != HTTP_TRANS_NOT_DONE)) { if (!strcasecmp(l_connection, "close")) { ghttpDebug("close connection \n"); close (a_conn->sock); a_conn->sock = -1; } } if (l_return == HTTP_TRANS_DONE) a_resp->body_state = http_resp_body_start; return l_return; }