evdispatch 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/ext/revdispatch/libdispatch-0.1/src/ev_dispatch.h +4 -0
- data/ext/revdispatch/libdispatch-0.1/src/ev_http.cc +38 -1
- data/ext/revdispatch/libdispatch-0.1/src/ev_http.h +8 -0
- data/ext/revdispatch/libdispatch-0.1/test/opt_test.cc +6 -0
- data/ext/revdispatch/revdispatch.cc +37 -5
- data/ext/revdispatch/stest.rb +6 -1
- data/lib/evdispatch/version.rb +1 -1
- data/website/index.html +1 -1
- metadata +2 -2
data/History.txt
CHANGED
@@ -11,6 +11,9 @@
|
|
11
11
|
#include <queue>
|
12
12
|
#include <map>
|
13
13
|
|
14
|
+
// declare ahead of time
|
15
|
+
struct curl_slist;
|
16
|
+
|
14
17
|
namespace EVD {
|
15
18
|
|
16
19
|
// unique id to represent a request
|
@@ -42,6 +45,7 @@ namespace EVD {
|
|
42
45
|
|
43
46
|
// by default this does nothing, each real request object can do as it pleases with this feature
|
44
47
|
virtual void set_opt( const std::string &key, const std::string &value ){}
|
48
|
+
virtual void set_opt( const std::string &key, struct curl_slist *slist ){}
|
45
49
|
|
46
50
|
virtual void set_key( request_t key ){ this->key = key; }
|
47
51
|
|
@@ -287,6 +287,10 @@ HttpRequest::HttpRequest( Dispatch &dispatch, const std::string &url, int fd )
|
|
287
287
|
m_client(dispatch.getHttpClient())
|
288
288
|
{
|
289
289
|
assert(m_client);
|
290
|
+
// prevent libcurl from sending signals or installing signal handles
|
291
|
+
curl_easy_setopt(m_handle,CURLOPT_NOSIGNAL,1);
|
292
|
+
// we won't be sending progress
|
293
|
+
curl_easy_setopt(m_handle,CURLOPT_NOPROGRESS,1);
|
290
294
|
init_curl();
|
291
295
|
}
|
292
296
|
|
@@ -346,6 +350,28 @@ void HttpRequest::set_key( request_t key )
|
|
346
350
|
m_response->id = key;
|
347
351
|
}
|
348
352
|
|
353
|
+
void HttpRequest::set_opt( const std::string &key, struct curl_slist *slist )
|
354
|
+
{
|
355
|
+
Request::set_opt(key,slist);
|
356
|
+
std::map<std::string,CURLoption> key_loopup;
|
357
|
+
key_loopup["headers"] = CURLOPT_HTTPHEADER;
|
358
|
+
std::map<std::string,CURLoption>::iterator loc = key_loopup.find(key);
|
359
|
+
if( loc != key_loopup.end() ) {
|
360
|
+
CURLoption val_type = loc->second;
|
361
|
+
if( key == "headers" ) {
|
362
|
+
// construct a slist of headers
|
363
|
+
curl_easy_setopt( m_handle, val_type, slist );
|
364
|
+
if( slist ) {
|
365
|
+
// we need to keep a reference to the options slist so we can cleanup after the request completes
|
366
|
+
this->m_response->add_to_free_list( slist );
|
367
|
+
}
|
368
|
+
}
|
369
|
+
}
|
370
|
+
else {
|
371
|
+
printf("invalid option: %s", key.c_str() );
|
372
|
+
}
|
373
|
+
}
|
374
|
+
|
349
375
|
void HttpRequest::set_opt( const std::string &key, const std::string &value )
|
350
376
|
{
|
351
377
|
Request::set_opt(key,value);
|
@@ -367,7 +393,7 @@ void HttpRequest::set_opt( const std::string &key, const std::string &value )
|
|
367
393
|
key_loopup["post"] = CURLOPT_POSTFIELDS;
|
368
394
|
|
369
395
|
std::map<std::string,CURLoption>::iterator loc = key_loopup.find(key);
|
370
|
-
if( loc != key_loopup.end() ){
|
396
|
+
if( loc != key_loopup.end() ) {
|
371
397
|
CURLoption val_type = loc->second;
|
372
398
|
if( val_type >= CURLOPTTYPE_LONG && val_type < CURLOPTTYPE_OBJECTPOINT ) {
|
373
399
|
long val = atoi(value.c_str());
|
@@ -391,6 +417,9 @@ void HttpRequest::set_opt( const std::string &key, const std::string &value )
|
|
391
417
|
}
|
392
418
|
}
|
393
419
|
}
|
420
|
+
else {
|
421
|
+
printf("invalid option: %s", key.c_str() );
|
422
|
+
}
|
394
423
|
}
|
395
424
|
|
396
425
|
HttpResponse::HttpResponse( const std::string &url )
|
@@ -401,6 +430,14 @@ HttpResponse::HttpResponse( const std::string &url, int fd )
|
|
401
430
|
: Response(url), m_fd(fd)
|
402
431
|
{
|
403
432
|
}
|
433
|
+
HttpResponse::~HttpResponse()
|
434
|
+
{
|
435
|
+
for( std::set<struct curl_slist*>::iterator it = m_request_opts.begin();
|
436
|
+
it != m_request_opts.end(); ++it ) {
|
437
|
+
curl_slist_free_all( *it );
|
438
|
+
}
|
439
|
+
m_request_opts.clear();
|
440
|
+
}
|
404
441
|
void HttpResponse::write( void *ptr, size_t realsize, size_t size, size_t nmemb )
|
405
442
|
{
|
406
443
|
// printf( " write: %s, %d\n", this->name.c_str(), realsize );
|
@@ -4,6 +4,7 @@
|
|
4
4
|
#include "config.h"
|
5
5
|
#include "ev_dispatch.h"
|
6
6
|
#include <curl/curl.h>
|
7
|
+
#include <set>
|
7
8
|
|
8
9
|
namespace EVD {
|
9
10
|
|
@@ -57,6 +58,7 @@ namespace EVD {
|
|
57
58
|
|
58
59
|
virtual void set_key( request_t key );
|
59
60
|
virtual void set_opt( const std::string &key, const std::string &value );
|
61
|
+
virtual void set_opt( const std::string &key, struct curl_slist *slist );
|
60
62
|
|
61
63
|
static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *data);
|
62
64
|
static size_t header_write_cb(void *ptr, size_t size, size_t nmemb, void *data);
|
@@ -74,13 +76,19 @@ namespace EVD {
|
|
74
76
|
struct HttpResponse : public Response {
|
75
77
|
HttpResponse( const std::string &url );
|
76
78
|
HttpResponse( const std::string &url, int fd );
|
79
|
+
virtual ~HttpResponse();
|
77
80
|
|
78
81
|
void write( void *ptr, size_t realsize, size_t size, size_t nmemb );
|
79
82
|
void write_header( void *ptr, size_t realsize, size_t size, size_t nmemb );
|
80
83
|
void finish( HttpClient *client, CURLcode rc );
|
84
|
+
|
85
|
+
void add_to_free_list( struct curl_slist *opts ){ m_request_opts.insert(opts); }
|
81
86
|
|
82
87
|
int m_fd;
|
83
88
|
std::string m_header;
|
89
|
+
private:
|
90
|
+
// keep these around to free, everytime someone calls set_opt("header", slist) we store the pointer here
|
91
|
+
std::set<struct curl_slist*> m_request_opts;
|
84
92
|
};
|
85
93
|
|
86
94
|
}
|
@@ -25,6 +25,12 @@ static void run_tests( Dispatch &dispatcher, int count )
|
|
25
25
|
req->set_opt("useragent", "users are us");
|
26
26
|
req->set_opt("cookie", "name1=content1; name2=content2;");
|
27
27
|
|
28
|
+
// set some arbitry headers
|
29
|
+
struct curl_slist *slist = NULL;
|
30
|
+
slist = curl_slist_append(slist, "x-my-header1: hi");
|
31
|
+
slist = curl_slist_append(slist, "x-my-header2: hello");
|
32
|
+
req->set_opt("headers", slist );
|
33
|
+
|
28
34
|
request_t id = dispatcher.request( req );
|
29
35
|
|
30
36
|
while( dispatcher.wait_for_response_by_id( id, Timer(1,5) ) ) {
|
@@ -1,5 +1,6 @@
|
|
1
1
|
#include "util.h"
|
2
2
|
#include "rhttp.h"
|
3
|
+
#include <st.h>
|
3
4
|
|
4
5
|
|
5
6
|
/*
|
@@ -93,8 +94,35 @@ VALUE Loop_request_http( VALUE self, VALUE url )
|
|
93
94
|
req->set_opt(name, RSTRING_PTR(obj));\
|
94
95
|
}\
|
95
96
|
}
|
97
|
+
|
98
|
+
static int
|
99
|
+
build_header_list(VALUE key, VALUE value, struct curl_slist **slist )
|
100
|
+
{
|
101
|
+
if (key == Qundef) return ST_CONTINUE;
|
102
|
+
VALUE str = rb_str_new(RSTRING_PTR(key),RSTRING_LEN(key));
|
103
|
+
str = rb_str_cat2(str,":");
|
104
|
+
*slist = curl_slist_append(*slist, RSTRING_PTR(rb_str_append(str,value)) );
|
105
|
+
return ST_CONTINUE;
|
106
|
+
}
|
107
|
+
|
108
|
+
static struct curl_slist *build_headers( VALUE hash )
|
109
|
+
{
|
110
|
+
struct curl_slist *slist = NULL;
|
111
|
+
rb_hash_foreach( hash, (int (*)(...))build_header_list, (VALUE)&slist );
|
112
|
+
return slist;
|
113
|
+
}
|
114
|
+
|
115
|
+
static void set_headers( VALUE options, EVD::HttpRequest *req )
|
116
|
+
{
|
117
|
+
VALUE hash = rb_hash_aref( options, ID2SYM(rb_intern("headers")) );
|
118
|
+
if( !NIL_P(hash) && TYPE(hash) == T_HASH ) {
|
119
|
+
struct curl_slist *headers = build_headers( hash );
|
120
|
+
req->set_opt( "headers", headers );
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
96
124
|
// set options
|
97
|
-
#define SET_REQ_OPTS \
|
125
|
+
#define SET_REQ_OPTS(options,req) \
|
98
126
|
SET_LONG_VAL("port"); \
|
99
127
|
SET_STR_VAL("autoreferer"); \
|
100
128
|
SET_LONG_VAL("followlocation"); \
|
@@ -102,7 +130,9 @@ VALUE Loop_request_http( VALUE self, VALUE url )
|
|
102
130
|
SET_STR_VAL("referer"); \
|
103
131
|
SET_STR_VAL("useragent"); \
|
104
132
|
SET_STR_VAL("cookie"); \
|
105
|
-
SET_STR_VAL("post");
|
133
|
+
SET_STR_VAL("post"); \
|
134
|
+
set_headers(options, req)
|
135
|
+
|
106
136
|
|
107
137
|
/**
|
108
138
|
* call-seq:
|
@@ -123,6 +153,7 @@ VALUE Loop_request_http( VALUE self, VALUE url )
|
|
123
153
|
* If you need to set multiple cookies, you need to set them all using a single option and thus you need to concatenate them all in one single string. Set multiple cookies in one string like this: "name1=content1; name2=content2;" etc.
|
124
154
|
* Note that this option sets the cookie header explictly in the outgoing request(s). If multiple requests are done due to authentication, followed redirections or similar, they will all get this cookie passed on.
|
125
155
|
* Using this option multiple times will only make the latest string override the previous ones.
|
156
|
+
* :headers: (Hash) An arbitrary list of HTTP Headers. Set any HTTP header or override the defaults. see libcurl's documentation for more details.
|
126
157
|
*
|
127
158
|
* :post: (String) Pass a string and sets CURLOPT_POST, CURLOPT_POSTFIELDSIZE, and CURLOPT_COPYPOSTFIELDS
|
128
159
|
*
|
@@ -158,8 +189,8 @@ VALUE Loop_request( int argc, VALUE *argv, VALUE self )
|
|
158
189
|
|
159
190
|
EVD::HttpRequest *req = new EVD::HttpRequest( *d, RSTRING_PTR(url), res->m_pipe[1] );
|
160
191
|
|
161
|
-
SET_REQ_OPTS
|
162
|
-
|
192
|
+
SET_REQ_OPTS(options,req);
|
193
|
+
|
163
194
|
res->m_response = req->m_response;
|
164
195
|
|
165
196
|
d->request(req);
|
@@ -167,7 +198,8 @@ VALUE Loop_request( int argc, VALUE *argv, VALUE self )
|
|
167
198
|
}
|
168
199
|
else {
|
169
200
|
EVD::HttpRequest *req = new EVD::HttpRequest( *d, RSTRING_PTR(url) );
|
170
|
-
|
201
|
+
|
202
|
+
SET_REQ_OPTS(options,req);
|
171
203
|
|
172
204
|
return rb_int_new( d->request(req) );
|
173
205
|
}
|
data/ext/revdispatch/stest.rb
CHANGED
@@ -30,7 +30,12 @@ class TestRequests < Test::Unit::TestCase
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def test_options_request
|
33
|
-
id = loop.request("http://127.0.0.1:4044/redir/1",
|
33
|
+
id = loop.request("http://127.0.0.1:4044/redir/1",
|
34
|
+
:followlocation => 1,
|
35
|
+
:referer => 'pizza',
|
36
|
+
:headers => {
|
37
|
+
'Simple' => 'Thoughts'
|
38
|
+
})
|
34
39
|
response = loop.response( id )
|
35
40
|
assert_not_nil( response )
|
36
41
|
assert_match(/ 302 Moved Temporarily/,response[:header])
|
data/lib/evdispatch/version.rb
CHANGED
data/website/index.html
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
<h1>evdispatch</h1>
|
19
19
|
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/evdispatch"; return false'>
|
20
20
|
<p>Get Version</p>
|
21
|
-
<a href="http://rubyforge.org/projects/evdispatch" class="numbers">0.3.
|
21
|
+
<a href="http://rubyforge.org/projects/evdispatch" class="numbers">0.3.1</a>
|
22
22
|
</div>
|
23
23
|
<h4 style="float:right;padding-right:10px;">→ ‘evdispatch’</h4>
|
24
24
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: evdispatch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Todd A. Fisher
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-04-
|
12
|
+
date: 2008-04-23 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|