void http_request_pop_header(HttpRequest* request) { if (request->num_headers > 0) { http_header_free(&request->headers[request->num_headers-1]); request->num_headers -= 1; } }
/* See section 4.2 of RFC 2616 for header format. */ int http_parse_header(struct http_header **result, const char *header) { const char *p, *q; size_t value_len, value_offset; struct http_header *node, **prev; *result = NULL; prev = result; p = header; while (*p != '\0' && !is_crlf(p)) { /* Get the field name. */ q = p; while (*q != '\0' && is_token_char(*q)) q++; if (*q != ':') { http_header_free(*result); return 400; } node = (struct http_header *) safe_malloc(sizeof(*node)); node->name = mkstr(p, q); node->value = NULL; node->next = NULL; value_len = 0; value_offset = 0; /* Copy the header field value until we hit a CRLF. */ p = q + 1; p = skip_lws(p); for (;;) { q = p; while (*q != '\0' && !is_space_char(*q) && !is_crlf(q)) { /* Section 2.2 of RFC 2616 disallows control characters. */ if (iscntrl((int) (unsigned char) *q)) { http_header_node_free(node); return 400; } q++; } strbuf_append(&node->value, &value_len, &value_offset, p, q - p); p = skip_lws(q); if (is_crlf(p)) break; /* Replace LWS with a single space. */ strbuf_append_str(&node->value, &value_len, &value_offset, " "); } *prev = node; prev = &node->next; p = skip_crlf(p); } return 0; }
void http_request_free(HttpRequest* request) { if(request->headers) { for(size_t i=0; i<request->num_headers; ++i) { http_header_free(&request->headers[i]); } free(request->headers); } if(request->uri) free(request->uri); if(request->body) free(request->body); if(request->error) free(request->error); http_request_init(request); }
void http_response_free(struct http_response *response) { free(response->phrase); http_header_free(response->header); }
void http_request_free(struct http_request *request) { free(request->method); uri_free(&request->uri); http_header_free(request->header); }
/* Return a usable socket descriptor after proxy negotiation, or -1 on any error. If any bytes are received through the proxy after negotiation, they are written to stdout. */ static int do_proxy_http(void) { struct socket_buffer sockbuf; char *request; char *status_line, *header; char *remainder; size_t len; int sd, code; int n; sd = do_connect(SOCK_STREAM); if (sd == -1) { loguser("Proxy connection failed: %s.\n", socket_strerror(socket_errno())); return -1; } status_line = NULL; header = NULL; /* First try a request with no authentication. */ request = http_connect_request(&httpconnect, &n); if (send(sd, request, n, 0) < 0) { loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno())); free(request); return -1; } free(request); socket_buffer_init(&sockbuf, sd); if (http_read_status_line(&sockbuf, &status_line) != 0) { loguser("Error reading proxy response Status-Line.\n"); goto bail; } code = http_parse_status_line_code(status_line); logdebug("Proxy returned status code %d.\n", code); free(status_line); status_line = NULL; if (http_read_header(&sockbuf, &header) != 0) { loguser("Error reading proxy response header.\n"); goto bail; } if (code == 407 && o.proxy_auth != NULL) { struct http_header *h; struct http_challenge challenge; close(sd); sd = -1; if (http_parse_header(&h, header) != 0) { loguser("Error parsing proxy response header.\n"); goto bail; } free(header); header = NULL; if (http_header_get_proxy_challenge(h, &challenge) == NULL) { loguser("Error getting Proxy-Authenticate challenge.\n"); http_header_free(h); goto bail; } http_header_free(h); sd = do_connect(SOCK_STREAM); if (sd == -1) { loguser("Proxy reconnection failed: %s.\n", socket_strerror(socket_errno())); goto bail; } request = http_connect_request_auth(&httpconnect, &n, &challenge); if (request == NULL) { loguser("Error building Proxy-Authorization header.\n"); http_challenge_free(&challenge); goto bail; } logdebug("Reconnection header:\n%s", request); if (send(sd, request, n, 0) < 0) { loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno())); free(request); http_challenge_free(&challenge); goto bail; } free(request); http_challenge_free(&challenge); socket_buffer_init(&sockbuf, sd); if (http_read_status_line(&sockbuf, &status_line) != 0) { loguser("Error reading proxy response Status-Line.\n"); goto bail; } code = http_parse_status_line_code(status_line); logdebug("Proxy returned status code %d.\n", code); free(status_line); status_line = NULL; if (http_read_header(&sockbuf, &header) != 0) { loguser("Error reading proxy response header.\n"); goto bail; } } free(header); header = NULL; if (code != 200) { loguser("Proxy returned status code %d.\n", code); return -1; } remainder = socket_buffer_remainder(&sockbuf, &len); Write(STDOUT_FILENO, remainder, len); return sd; bail: if (sd != -1) close(sd); if (status_line != NULL) free(status_line); if (header != NULL) free(header); return -1; }
int http_get(char *urlstr, http_req_func_t func, void *farg) { url_t url; struct sockaddr_in iaddr; sockaddrlen_t addrlen; int i, err=-1; sock_t sock; int url_parsed=0; char buf[16384], buf1[1024]; size_t len=0; http_header_t http; http_req_t req; int got_header = 0; http_req_error_t req_err = 0; do { memset(&req, 0, sizeof(req)); req.req_url = &url; req.reply_hdr = &http; req_err = HTTP_REQ_ERROR_BAD_URL; i = url_parse(&url, urlstr); assertb(i==0); url_parsed = 1; if( strcasecmp(url.proto, "file") == 0 ) { struct stat st; FILE *f=0; req_err = HTTP_REQ_ERROR_FILE_NOT_FOUND; do { i = stat(url.path, &st); assertb(i==0); http.content_len = st.st_size; req.req_state = HTTP_REQ_BODY; f = fopen(url.path, "r"); assertb(f); while(1) { len = fread(buf, 1, sizeof(buf), f); if( len < 0 ) { req_err = HTTP_REQ_ERROR_INCOMPLETE; break; } if( len <= 0 ) break; err = func(&req, buf, len, farg); if( err ) break; } req_err = 0; err = 0; } while(0); if( f ) { fclose(f); } break; } req_err = HTTP_REQ_ERROR_BAD_URL; assertb( strcasecmp(url.proto, "http") == 0 ); req_err = HTTP_REQ_ERROR_CONNECT; sock = socket(AF_INET, SOCK_STREAM, 0); assertb_sockerr(sock>=0); req.req_state = HTTP_REQ_RESOLVE; i = snprintf(buf, sizeof(buf), "resolving host %s\n", url.host); err = func(&req, buf, i, farg); if( err != 0 ) break; addrlen = iaddr_pack(&iaddr, inet_resolve(url.host), url.port); req.req_state = HTTP_REQ_CONNECT; i = snprintf(buf, sizeof(buf), "connecting to host %s at %s\n" ,url.host ,iaddr_fmt(&iaddr, buf1, sizeof(buf1)) ); err = func(&req, buf, i, farg); if( err != 0 ) break; i = connect(sock, (struct sockaddr*)&iaddr, addrlen); assertb_sockerr(i==0); i = snprintf(buf, sizeof(buf), "GET %s HTTP/1.0\r\n" "Host: %s\r\n" "\r\n" ,url.path_args ,url.host ); req.req_state = HTTP_REQ_SEND; err = func(&req, buf, i, farg); if( err != 0 ) break; i = sock_send_timeout(sock, buf, i, 5000); assertb(i>=0); len = 0; got_header = 0; while(1) { assertb( len < sizeof(buf) ); i = recv(sock, buf+len, sizeof(buf)-len, 0); if( i < 0 ) { warn_sockerr(sock); req_err = HTTP_REQ_ERROR_INCOMPLETE; break; } if( i == 0 ) { req.req_state = HTTP_REQ_EOF; err = func(&req, 0, 0, farg); break; } len += i; if( !got_header ) { http_header_init(&http, 0); i = http_header_parse(&http, buf, len); if( i < 0 ) { req_err = HTTP_REQ_ERROR_BAD_RESPONSE; break; } if( i == 0 ) { continue; } got_header = 1; req.reply_max = http.content_len; req.req_state = HTTP_REQ_HEAD; err = func(&req, buf, http.header_len, farg); if( err != 0 ) { break; } len -= http.header_len; if( len > 0 ) { memmove(buf, buf+http.header_len, len); } } if( got_header ) { req.reply_len += len; req.req_state = HTTP_REQ_BODY; err = func(&req, buf, len, farg); len = 0; if( err ) { break; } } } req_err = 0; } while(0); if( got_header && http.response_code != 200 ) { req_err = HTTP_REQ_ERROR_FILE_NOT_FOUND; } if( req_err ) { req.req_state = HTTP_REQ_ERROR; req.req_error = req_err; err = func(&req, buf, len, farg); } if( url_parsed ) { url_free(&url); } if( got_header ) { http_header_free(&http); } return err; }
void http_request_free(struct http_request *request) { if (request->uri) free(request->uri); if (request->headers) http_header_free(request->headers); free( request ); }
void http_request_free (http_request_t *req) { http_header_free(req->headers); free(req->parser_); free(req); }