Browse Source

send http headers in original order

pull/797/head
orignal 8 years ago
parent
commit
66f3bd186f
  1. 10
      AddressBook.cpp
  2. 77
      HTTP.cpp
  3. 15
      HTTP.h
  4. 65
      HTTPProxy.cpp
  5. 6
      HTTPServer.cpp
  6. 4
      Reseed.cpp

10
AddressBook.cpp

@ -703,13 +703,13 @@ namespace client @@ -703,13 +703,13 @@ namespace client
int dest_port = url.port ? url.port : 80;
/* create http request & send it */
i2p::http::HTTPReq req;
req.add_header("Host", dest_host);
req.add_header("User-Agent", "Wget/1.11.4");
req.add_header("Connection", "close");
req.AddHeader("Host", dest_host);
req.AddHeader("User-Agent", "Wget/1.11.4");
req.AddHeader("Connection", "close");
if (!m_Etag.empty())
req.add_header("If-None-Match", m_Etag);
req.AddHeader("If-None-Match", m_Etag);
if (!m_LastModified.empty())
req.add_header("If-Modified-Since", m_LastModified);
req.AddHeader("If-Modified-Since", m_LastModified);
/* convert url to relative */
url.schema = "";
url.host = "";

77
HTTP.cpp

@ -1,14 +1,15 @@ @@ -1,14 +1,15 @@
/*
* Copyright (c) 2013-2016, The PurpleI2P Project
* Copyright (c) 2013-2017, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <algorithm>
#include <utility>
#include "util.h"
#include "HTTP.h"
#include <algorithm>
#include <ctime>
namespace i2p {
@ -43,18 +44,16 @@ namespace http { @@ -43,18 +44,16 @@ namespace http {
}
}
bool parse_header_line(const std::string & line, std::map<std::string, std::string> & headers) {
static std::pair<std::string, std::string> parse_header_line(const std::string& line)
{
std::size_t pos = 0;
std::size_t len = 2; /* strlen(": ") */
std::size_t max = line.length();
if ((pos = line.find(": ", pos)) == std::string::npos)
return false;
return std::make_pair("", "");
while ((pos + len) < max && isspace(line.at(pos + len)))
len++;
std::string name = line.substr(0, pos);
std::string value = line.substr(pos + len);
headers[name] = value;
return true;
return std::make_pair(line.substr(0, pos), line.substr(pos + len));
}
void gen_rfc1123_date(std::string & out) {
@ -247,10 +246,15 @@ namespace http { @@ -247,10 +246,15 @@ namespace http {
uri = tokens[1];
version = tokens[2];
expect = HEADER_LINE;
} else {
}
else
{
std::string line = str.substr(pos, eol - pos);
if (!parse_header_line(line, headers))
return -1;
auto p = parse_header_line(line);
if (p.first.length () > 0)
headers.push_back (p);
else
return -1;
}
pos = eol + strlen(CRLF);
if (pos >= eoh)
@ -259,12 +263,12 @@ namespace http { @@ -259,12 +263,12 @@ namespace http {
return eoh + strlen(HTTP_EOH);
}
void HTTPReq::write(std::ostream & o) {
o << method << " " << uri << " " << version << CRLF;
for (auto & h : headers) {
o << h.first << ": " << h.second << CRLF;
}
o << CRLF;
void HTTPReq::write(std::ostream & o)
{
o << method << " " << uri << " " << version << CRLF;
for (auto & h : headers)
o << h.first << ": " << h.second << CRLF;
o << CRLF;
}
std::string HTTPReq::to_string()
@ -274,6 +278,40 @@ namespace http { @@ -274,6 +278,40 @@ namespace http {
return ss.str();
}
void HTTPReq::AddHeader (const std::string& name, const std::string& value)
{
headers.push_back (std::make_pair(name, value));
}
void HTTPReq::UpdateHeader (const std::string& name, const std::string& value)
{
for (auto& it : headers)
if (it.first == name)
{
it.second = value;
break;
}
}
void HTTPReq::RemoveHeader (const std::string& name)
{
for (auto it = headers.begin (); it != headers.end ();)
{
if (!it->first.compare(0, name.length (), name))
it = headers.erase (it);
else
it++;
}
}
std::string HTTPReq::GetHeader (const std::string& name) const
{
for (auto& it : headers)
if (it.first == name)
return it.second;
return "";
}
bool HTTPRes::is_chunked() {
auto it = headers.find("Transfer-Encoding");
if (it == headers.end())
@ -335,7 +373,10 @@ namespace http { @@ -335,7 +373,10 @@ namespace http {
expect = HEADER_LINE;
} else {
std::string line = str.substr(pos, eol - pos);
if (!parse_header_line(line, headers))
auto p = parse_header_line(line);
if (p.first.length () > 0)
headers.insert (p);
else
return -1;
}
pos = eol + strlen(CRLF);

15
HTTP.h

@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
#include <cstring>
#include <map>
#include <list>
#include <sstream>
#include <string>
#include <vector>
@ -54,7 +55,8 @@ namespace http { @@ -54,7 +55,8 @@ namespace http {
std::string to_string ();
};
struct HTTPMsg {
struct HTTPMsg
{
std::map<std::string, std::string> headers;
void add_header(const char *name, std::string & value, bool replace = false);
@ -65,7 +67,9 @@ namespace http { @@ -65,7 +67,9 @@ namespace http {
long int content_length();
};
struct HTTPReq : HTTPMsg {
struct HTTPReq
{
std::list<std::pair<std::string, std::string> > headers;
std::string version;
std::string method;
std::string uri;
@ -82,9 +86,12 @@ namespace http { @@ -82,9 +86,12 @@ namespace http {
/** @brief Serialize HTTP request to string */
std::string to_string();
void write(std::ostream & o);
void write(std::ostream & o);
void AddHeader (const std::string& name, const std::string& value);
void UpdateHeader (const std::string& name, const std::string& value);
void RemoveHeader (const std::string& name);
std::string GetHeader (const std::string& name) const;
};
struct HTTPRes : HTTPMsg {

65
HTTPProxy.cpp

@ -200,26 +200,16 @@ namespace proxy { @@ -200,26 +200,16 @@ namespace proxy {
void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq & req)
{
/* drop common headers */
req.del_header("Referer");
req.del_header("Via");
req.del_header("Forwarded");
req.RemoveHeader ("Referer");
req.RemoveHeader("Via");
req.RemoveHeader("Forwarded");
/* drop proxy-disclosing headers */
std::vector<std::string> toErase;
for (const auto& it : req.headers) {
if (it.first.compare(0, 12, "X-Forwarded-") == 0) {
toErase.push_back(it.first);
} else if (it.first.compare(0, 6, "Proxy-") == 0) {
toErase.push_back(it.first);
} else {
/* allow */
}
}
for (const auto& header : toErase) {
req.headers.erase(header);
}
req.RemoveHeader("X-Forwarded");
req.RemoveHeader("Proxy-");
/* replace headers */
req.add_header("Connection", "close", true); /* keep-alive conns not supported yet */
req.add_header("User-Agent", "MYOB/6.66 (AN/ON)", true); /* privacy */
req.UpdateHeader("User-Agent", "MYOB/6.66 (AN/ON)");
/* add headers */
req.AddHeader("Connection", "close"); /* keep-alive conns not supported yet */
}
/**
@ -263,28 +253,35 @@ namespace proxy { @@ -263,28 +253,35 @@ namespace proxy {
std::string dest_host = m_RequestURL.host;
uint16_t dest_port = m_RequestURL.port;
/* always set port, even if missing in request */
if (!dest_port) {
if (!dest_port)
dest_port = (m_RequestURL.schema == "https") ? 443 : 80;
}
/* detect dest_host, set proper 'Host' header in upstream request */
auto h = m_ClientRequest.headers.find("Host");
if (dest_host != "") {
if (dest_host != "")
{
/* absolute url, replace 'Host' header */
std::string h = dest_host;
if (dest_port != 0 && dest_port != 80)
h += ":" + std::to_string(dest_port);
m_ClientRequest.add_header("Host", h, true);
} else if (h != m_ClientRequest.headers.end()) {
/* relative url and 'Host' header provided. transparent proxy mode? */
i2p::http::URL u;
std::string t = "http://" + h->second;
u.parse(t);
dest_host = u.host;
dest_port = u.port;
} else {
/* relative url and missing 'Host' header */
GenericProxyError("Invalid request", "Can't detect destination host from request");
return true;
m_ClientRequest.UpdateHeader("Host", h);
}
else
{
auto h = m_ClientRequest.GetHeader ("Host");
if (h.length () > 0)
{
/* relative url and 'Host' header provided. transparent proxy mode? */
i2p::http::URL u;
std::string t = "http://" + h;
u.parse(t);
dest_host = u.host;
dest_port = u.port;
}
else
{
/* relative url and missing 'Host' header */
GenericProxyError("Invalid request", "Can't detect destination host from request");
return true;
}
}
/* check dest_host really exists and inside I2P network */

6
HTTPServer.cpp

@ -714,9 +714,11 @@ namespace http { @@ -714,9 +714,11 @@ namespace http {
return true;
}
/* method #2: 'Authorization' header sent */
if (req.headers.count("Authorization") > 0) {
auto provided = req.GetHeader ("Authorization");
if (provided.length () > 0)
{
bool result = false;
std::string provided = req.headers.find("Authorization")->second;
std::string expected = user + ":" + pass;
size_t b64_sz = i2p::data::Base64EncodingBufferSize(expected.length()) + 1;
char * b64_creds = new char[b64_sz];

4
Reseed.cpp

@ -517,8 +517,8 @@ namespace data @@ -517,8 +517,8 @@ namespace data
LogPrint (eLogDebug, "Reseed: Connected to ", url.host, ":", url.port);
i2p::http::HTTPReq req;
req.uri = url.to_string();
req.add_header("User-Agent", "Wget/1.11.4");
req.add_header("Connection", "close");
req.AddHeader("User-Agent", "Wget/1.11.4");
req.AddHeader("Connection", "close");
s.write_some (boost::asio::buffer (req.to_string()));
// read response
std::stringstream rs;

Loading…
Cancel
Save