void HTTPRequest::addDefaultHTTPHeaders() { addHeader(HTTPHeader("Host", url.getHost())); if(method != HTTP_METHOD_POST) { return; } if(!headers.contains("content-type")) { if(getFormEncoding() == HTTP_FORM_MULTIPART) { addHeader(HTTPHeader("Content-Type", "multipart/form-data; boundary=\"" +getBoundary() +"\"")); } else if(getFormEncoding() == HTTP_FORM_URL_ENCODED) { addHeader(HTTPHeader("Content-Type", "application/x-www-form-urlencoded")); } } }
// create the request string bool HTTPRequest::toString(std::string& result) { // create the content string std::string http_body; if(!createBody(http_body)) { RX_ERROR("Cannot create request body"); return false; } // create the headers. addDefaultHTTPHeaders(); addHeader(HTTPHeader("Content-Length", http_body.size())); // construct the request result = getHTTPString() +"\r\n"; result += headers.join(); result += "\r\n"; #if 1 printf("%s", result.c_str()); for(size_t i = 0; i < http_body.size(); ++i) { if(i > 40) { break; } printf("%c", http_body[i]); } printf("\n"); for(size_t i = 0; i < http_body.size(); ++i) { if(i > 40) { break; } printf("%02X ", (unsigned char)http_body[i]); } printf("\n"); #endif result += http_body; #if 0 std::ofstream ofs(rx_to_data_path("out.raw").c_str(), std::ios::binary | std::ios::out); if(!ofs.is_open()) { RX_ERROR("Cannot open output file"); } else { ofs.write(result.c_str(), result.size()); ofs.close(); } #endif return true; }
void OAuth::addAuthorizationHeadersToRequest(HTTPRequest& r) { std::string signature = createSignature(r); HTTPParameters params = collectParameters(r); params.add(HTTPParameter("oauth_signature", signature)); params.percentEncode(); std::string header = "OAuth "; OAUTH_CONCAT_HEADER(header, "oauth_callback", true); OAUTH_CONCAT_HEADER(header, "oauth_consumer_key", true); OAUTH_CONCAT_HEADER(header, "oauth_nonce", true); OAUTH_CONCAT_HEADER(header, "oauth_signature", true); OAUTH_CONCAT_HEADER(header, "oauth_signature_method", true); OAUTH_CONCAT_HEADER(header, "oauth_timestamp", true); OAUTH_CONCAT_HEADER(header, "oauth_token", true); OAUTH_CONCAT_HEADER(header, "oauth_version", false); r.addHeader(HTTPHeader("Authorization", header)); }
void HTTPMessage::parse( String& startLine, Array<HTTPHeader>& headers, Uint32& contentLength) const { startLine.clear(); headers.clear(); contentLength = 0; char* data = (char*)message.getData(); Uint32 size = message.size(); char* line = data; char* sep; Boolean firstTime = true; while ((sep = findSeparator(line, (Uint32)(size - (line - data))))) { // Look for double separator which terminates the header? if (line == sep) { // Establish pointer to content (account for "\n" and "\r\n"). char* content = line + ((*sep == '\r') ? 2 : 1); // Determine length of content: contentLength = (Uint32)(message.size() - (content - data)); break; } Uint32 lineLength = (Uint32)(sep - line); if (firstTime) startLine.assign(line, lineLength); else { // Find the colon: char* colon = 0; for (Uint32 i = 0; i < lineLength; i++) { if (line[i] == ':') { colon = &line[i]; break; } } // This should always be true: if (colon) { // Get the name part: char* end; for (end = colon - 1; end > line && isspace(*end); end--) ; end++; String name(line, (Uint32)(end - line)); // Get the value part: char* start; for (start = colon + 1; start < sep && isspace(*start); start++) ; String value(start, (Uint32)(sep - start)); // From the HTTP/1.1 specification (RFC 2616) section 4.2 // Message Headers: // // Multiple message-header fields with the same field-name // MAY be present in a message if and only if the entire // field-value for that header field is defined as a // comma-separated list [i.e., #(values)]. It MUST be // possible to combine the multiple header fields into one // "field-name: field-value" pair, without changing the // semantics of the message, by appending each subsequent // field-value to the first, each separated by a comma. The // order in which header fields with the same field-name are // received is therefore significant to the interpretation // of the combined field value, and thus a proxy MUST NOT // change the order of these field values when a message is // forwarded. // This implementation concatenates duplicate header values, // with a comma separator. If the resulting value is invalid, // that should be detected when the value is used. Uint32 headerIndex = 0; for (; headerIndex < headers.size(); headerIndex++) { if (headers[headerIndex].first == name) { break; } } if (headerIndex == headers.size()) { headers.append(HTTPHeader(name, value)); } else { headers[headerIndex].second.append(", ").append(value); } } } line = sep + ((*sep == '\r') ? 2 : 1); firstTime = false; } }
int httpconnection_on_header_value(http_parser* p, const char* at, size_t len) { HTTPConnection* c = static_cast<HTTPConnection*>(p->data); std::string header_value(at, len); c->headers.add(HTTPHeader(c->last_header, header_value)); return 0; }