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
int dest_port = url.port ? url.port : 80; int dest_port = url.port ? url.port : 80;
/* create http request & send it */ /* create http request & send it */
i2p::http::HTTPReq req; i2p::http::HTTPReq req;
req.add_header("Host", dest_host); req.AddHeader("Host", dest_host);
req.add_header("User-Agent", "Wget/1.11.4"); req.AddHeader("User-Agent", "Wget/1.11.4");
req.add_header("Connection", "close"); req.AddHeader("Connection", "close");
if (!m_Etag.empty()) if (!m_Etag.empty())
req.add_header("If-None-Match", m_Etag); req.AddHeader("If-None-Match", m_Etag);
if (!m_LastModified.empty()) if (!m_LastModified.empty())
req.add_header("If-Modified-Since", m_LastModified); req.AddHeader("If-Modified-Since", m_LastModified);
/* convert url to relative */ /* convert url to relative */
url.schema = ""; url.schema = "";
url.host = ""; url.host = "";

77
HTTP.cpp

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

15
HTTP.h

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

65
HTTPProxy.cpp

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

6
HTTPServer.cpp

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

4
Reseed.cpp

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

Loading…
Cancel
Save