Adding arbitrary headers form the command line
This commit is contained in:
parent
558e27ac9e
commit
2266b102e3
|
@ -72,6 +72,7 @@ struct Config {
|
||||||
std::string certfile;
|
std::string certfile;
|
||||||
std::string keyfile;
|
std::string keyfile;
|
||||||
int window_bits;
|
int window_bits;
|
||||||
|
std::map<std::string,std::string> headers;
|
||||||
Config():null_out(false), remote_name(false), verbose(false),
|
Config():null_out(false), remote_name(false), verbose(false),
|
||||||
get_assets(false), stat(false),
|
get_assets(false), stat(false),
|
||||||
spdy_version(-1), timeout(-1), window_bits(-1)
|
spdy_version(-1), timeout(-1), window_bits(-1)
|
||||||
|
@ -223,11 +224,11 @@ struct SpdySession {
|
||||||
Config config;
|
Config config;
|
||||||
extern bool ssl_debug;
|
extern bool ssl_debug;
|
||||||
|
|
||||||
void submit_request(Spdylay& sc, const std::string& hostport, Request* req)
|
void submit_request(Spdylay& sc, const std::string& hostport, const std::map<std::string,std::string> &headers, Request* req)
|
||||||
{
|
{
|
||||||
uri::UriStruct& us = req->us;
|
uri::UriStruct& us = req->us;
|
||||||
std::string path = us.dir+us.file+us.query;
|
std::string path = us.dir+us.file+us.query;
|
||||||
int r = sc.submit_request(hostport, path, 3, req);
|
int r = sc.submit_request(hostport, path, headers, 3, req);
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +247,7 @@ void update_html_parser(SpdySession *spdySession, Request *req,
|
||||||
req->us.protocol == us.protocol && req->us.host == us.host &&
|
req->us.protocol == us.protocol && req->us.host == us.host &&
|
||||||
req->us.port == us.port) {
|
req->us.port == us.port) {
|
||||||
spdySession->add_request(us, req->level+1);
|
spdySession->add_request(us, req->level+1);
|
||||||
submit_request(*spdySession->sc, spdySession->hostport,
|
submit_request(*spdySession->sc, spdySession->hostport, config.headers,
|
||||||
spdySession->reqvec.back());
|
spdySession->reqvec.back());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,7 +512,7 @@ int communicate(const std::string& host, uint16_t port,
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
}
|
}
|
||||||
for(int i = 0, n = spdySession.reqvec.size(); i < n; ++i) {
|
for(int i = 0, n = spdySession.reqvec.size(); i < n; ++i) {
|
||||||
submit_request(sc, spdySession.hostport, spdySession.reqvec[i]);
|
submit_request(sc, spdySession.hostport, config.headers, spdySession.reqvec[i]);
|
||||||
}
|
}
|
||||||
pollfds[0].fd = fd;
|
pollfds[0].fd = fd;
|
||||||
ctl_poll(pollfds, &sc);
|
ctl_poll(pollfds, &sc);
|
||||||
|
@ -645,6 +646,7 @@ void print_help(std::ostream& out)
|
||||||
<< " same with the linking resource will be\n"
|
<< " same with the linking resource will be\n"
|
||||||
<< " downloaded.\n"
|
<< " downloaded.\n"
|
||||||
<< " -s, --stat Print statistics.\n"
|
<< " -s, --stat Print statistics.\n"
|
||||||
|
<< " -H, --header Add a header to the requests.\n"
|
||||||
<< " --cert=<CERT> Use the specified client certificate file.\n"
|
<< " --cert=<CERT> Use the specified client certificate file.\n"
|
||||||
<< " The file must be in PEM format.\n"
|
<< " The file must be in PEM format.\n"
|
||||||
<< " --key=<KEY> Use the client private key file. The file\n"
|
<< " --key=<KEY> Use the client private key file. The file\n"
|
||||||
|
@ -669,10 +671,11 @@ int main(int argc, char **argv)
|
||||||
{"cert", required_argument, &flag, 1 },
|
{"cert", required_argument, &flag, 1 },
|
||||||
{"key", required_argument, &flag, 2 },
|
{"key", required_argument, &flag, 2 },
|
||||||
{"help", no_argument, 0, 'h' },
|
{"help", no_argument, 0, 'h' },
|
||||||
|
{"header", required_argument, 0, 'H' },
|
||||||
{0, 0, 0, 0 }
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
int c = getopt_long(argc, argv, "Oanhv23st:w:", long_options,
|
int c = getopt_long(argc, argv, "OanhH:v23st:w:", long_options,
|
||||||
&option_index);
|
&option_index);
|
||||||
if(c == -1) {
|
if(c == -1) {
|
||||||
break;
|
break;
|
||||||
|
@ -711,6 +714,27 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'H': {
|
||||||
|
char *header = optarg;
|
||||||
|
char *value = strchr( optarg, ':' );
|
||||||
|
if ( ! value ) {
|
||||||
|
std::cerr << "-H: invalid header: " << optarg
|
||||||
|
<< std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
*value = 0;
|
||||||
|
value++;
|
||||||
|
while( isspace( *value ) ) { value++; }
|
||||||
|
if ( *value == 0 ) {
|
||||||
|
// This could also be a valid case for suppressing a header similar to curl
|
||||||
|
std::cerr << "-H: invalid header - value missing: " << optarg
|
||||||
|
<< std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// Note that there is no processing currently to handle multiple message-header
|
||||||
|
// fields with the same field name
|
||||||
|
config.headers.insert( std::pair<std::string,std::string>( header, value ) );
|
||||||
|
}
|
||||||
case 'a':
|
case 'a':
|
||||||
#ifdef HAVE_LIBXML2
|
#ifdef HAVE_LIBXML2
|
||||||
config.get_assets = true;
|
config.get_assets = true;
|
||||||
|
|
|
@ -122,20 +122,71 @@ void* Spdylay::user_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
int Spdylay::submit_request(const std::string& hostport,
|
int Spdylay::submit_request(const std::string& hostport,
|
||||||
const std::string& path, uint8_t pri,
|
const std::string& path,
|
||||||
|
const std::map<std::string,std::string> &headers,
|
||||||
|
uint8_t pri,
|
||||||
void *stream_user_data)
|
void *stream_user_data)
|
||||||
{
|
{
|
||||||
const char *nv[] = {
|
enum eStaticHeaderPosition
|
||||||
|
{
|
||||||
|
POS_METHOD = 0,
|
||||||
|
POS_PATH,
|
||||||
|
POS_VERSION,
|
||||||
|
POS_SCHEME,
|
||||||
|
POS_HOST,
|
||||||
|
POS_ACCEPT,
|
||||||
|
POS_USERAGENT
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *static_nv[] = {
|
||||||
":method", "GET",
|
":method", "GET",
|
||||||
":path", path.c_str(),
|
":path", path.c_str(),
|
||||||
":version", "HTTP/1.1",
|
":version", "HTTP/1.1",
|
||||||
":scheme", "https",
|
":scheme", "https",
|
||||||
":host", hostport.c_str(),
|
":host", hostport.c_str(),
|
||||||
"accept", "*/*",
|
"accept", "*/*",
|
||||||
"user-agent", "spdylay/" SPDYLAY_VERSION,
|
"user-agent", "spdylay/" SPDYLAY_VERSION
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
return spdylay_submit_request(session_, pri, nv, NULL, stream_user_data);
|
|
||||||
|
int hardcoded_entry_count = sizeof(static_nv) / sizeof(*static_nv);
|
||||||
|
int header_count = headers.size();
|
||||||
|
int total_entry_count = hardcoded_entry_count + header_count * 2;
|
||||||
|
|
||||||
|
const char **nv = new const char*[total_entry_count + 1];
|
||||||
|
|
||||||
|
memcpy(nv, static_nv, hardcoded_entry_count * sizeof(*static_nv));
|
||||||
|
|
||||||
|
std::map<std::string,std::string>::const_iterator i = headers.begin();
|
||||||
|
std::map<std::string,std::string>::const_iterator end = headers.end();
|
||||||
|
|
||||||
|
int pos = hardcoded_entry_count;
|
||||||
|
|
||||||
|
while( i != end ) {
|
||||||
|
const char *key = (*i).first.c_str();
|
||||||
|
const char *value = (*i).second.c_str();
|
||||||
|
if ( strcasecmp( key, "accept" ) == 0 ) {
|
||||||
|
nv[POS_ACCEPT*2+1] = value;
|
||||||
|
}
|
||||||
|
else if ( strcasecmp( key, "user-agent" ) == 0 ) {
|
||||||
|
nv[POS_USERAGENT*2+1] = value;
|
||||||
|
}
|
||||||
|
else if ( strcasecmp( key, "host" ) == 0 ) {
|
||||||
|
nv[POS_HOST*2+1] = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nv[pos] = key;
|
||||||
|
nv[pos+1] = value;
|
||||||
|
pos += 2;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
nv[pos] = NULL;
|
||||||
|
|
||||||
|
int r = spdylay_submit_request(session_, pri, nv, NULL, stream_user_data);
|
||||||
|
|
||||||
|
delete [] nv;
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Spdylay::submit_settings(int flags, spdylay_settings_entry *iv, size_t niv)
|
int Spdylay::submit_settings(int flags, spdylay_settings_entry *iv, size_t niv)
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
@ -54,7 +55,7 @@ public:
|
||||||
bool want_write();
|
bool want_write();
|
||||||
bool finish();
|
bool finish();
|
||||||
int fd() const;
|
int fd() const;
|
||||||
int submit_request(const std::string& hostport, const std::string& path,
|
int submit_request(const std::string& hostport, const std::string& path, const std::map<std::string,std::string>& headers,
|
||||||
uint8_t pri, void *stream_user_data);
|
uint8_t pri, void *stream_user_data);
|
||||||
int submit_settings(int flags, spdylay_settings_entry *iv, size_t niv);
|
int submit_settings(int flags, spdylay_settings_entry *iv, size_t niv);
|
||||||
bool would_block(int r);
|
bool would_block(int r);
|
||||||
|
|
Loading…
Reference in New Issue