You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(52) |
Jun
(30) |
Jul
(17) |
Aug
(9) |
Sep
(4) |
Oct
(7) |
Nov
(11) |
Dec
(19) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
|
Feb
(1) |
Mar
(37) |
Apr
(28) |
May
(15) |
Jun
(28) |
Jul
(7) |
Aug
(125) |
Sep
(116) |
Oct
(85) |
Nov
(14) |
Dec
(6) |
2009 |
Jan
(11) |
Feb
(4) |
Mar
(5) |
Apr
|
May
(9) |
Jun
(5) |
Jul
(4) |
Aug
(40) |
Sep
(1) |
Oct
(19) |
Nov
(43) |
Dec
(45) |
2010 |
Jan
(76) |
Feb
(95) |
Mar
(3) |
Apr
(23) |
May
(39) |
Jun
(54) |
Jul
(6) |
Aug
(13) |
Sep
(12) |
Oct
(59) |
Nov
(53) |
Dec
(43) |
2011 |
Jan
(43) |
Feb
(44) |
Mar
(25) |
Apr
(23) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(5) |
Oct
(1) |
Nov
(2) |
Dec
|
2013 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(6) |
Oct
|
Nov
|
Dec
|
From: Dean M. B. <mik...@gm...> - 2011-03-21 14:35:56
|
On Mon, Mar 21, 2011 at 2:44 AM, Emre Türkay <emr...@gm...> wrote: > Hi Dean, > > While looking at the documentation I see that the handler is originally designed to be a function object. Yep. > That's nice, so the application developer can: > > - Provide a function if the case is a simple one, or > - If the implementation needs state information, provide a class with a function call operator overloaded. > Well, not really... > However, the call to the Handler::log() brakes that simplicity, the handler is forced to be a class. > Below are the possible solutions to this problem, with each having their own pro & cons (mostly taste related). > > 1. Provide an extra error argument to the function. This is confusing because it makes the the function handle two different things. > 2. Handler::log() assumption is fine, let's force the implementation to be a class with specific > handle_data() and handle_error() functions. Not really. The Handler::log(...) assumption is meant to be a contract between the handler and the server implementation. > 3. Provide 2 different handler functions, one for data and one for error. > This can be done without changing the way things are done as it is. > So I have provided an interface to handle all. I think being easy is nothing to do with this. > Here, the interface to the application developer is easy, and the implementation is a little > bit complicated. > Unfortunately, here's the problem with trying to support all three of the things above: 1. There's no "one way" to do it. Because of that you end up with complications that are really unnecessary especially since everything you want to do can be done with the current implementation already. 2. I don't still understand why you would want to have just a function when you still have to worry about synchronization and connection state in the handler implementation. The reason why I'm forcing the server handler to be a type/class is so that data touched by the handlers are actually encapsulated in the handler. 3. There's a way to adapt any function in a type that has the `log` function so that it can be used as a handler to the server. I can give an example when I get more time to do it. > By the way there is no need of the template argument Handler in this implementation. > Which is bad because your compiler cannot optimize the parts where the handler is being called if you just hold a boost::function to the handler. ;) I would be more interested in a service framework which would allow anyone to map things like 'GET /' or 'POST /' to actual handlers. That can be built on top of the existing interface and if this is what you're looking at doing, I can share some thoughts with you on how to do that instead. In the meantime a pull request to the 0.9-devel branch to port all Handler::log(string_type const &) to become Handler::log(boost::system::error_code const &, string_type const &) would be most appreciated to minimize the interface breakage. I also would like to see if you can find a way to remove the Handler::log requirement by making the error function handler be made part of the server constructor instead -- and maybe logic to use the Handler::log if it's defined, or use the error handler function defined in the server constructor. What do you think about that? :D Thanks and HTH > On Mar 20, 2011, at 12:04 PM, Dean Michael Berris wrote: > >> On Sat, Mar 19, 2011 at 9:22 PM, Emre Türkay <emr...@gm...> wrote: >>> Hi Dean. >>> >>> What do you say about this interface? Take a look at the various possible handlers. >>> >> >> Hmmm... I don't understand what you're trying to accomplish here. Care >> to elaborate? If it's just a matter of providing an error handler, >> that should be really *easy* and not this complicated. I appreciate >> the code, but I don't know what problem you're trying to solve here. >> >> -- >> Dean Michael Berris >> http://about.me/deanberris > > -- Dean Michael Berris http://about.me/deanberris |
From: Dean M. B. <mik...@gm...> - 2011-03-21 14:10:01
|
Hi Rick! Thanks for these, let me respond in-lined below. On Mon, Mar 21, 2011 at 12:11 AM, Rick Richardson <ric...@gm...> wrote: > Three things: > 1. Hi, I'm Rick Richardson. I just got a hold of cpp-netlib because I am > looking to make a highly scalable and runtime reconfigurable reverse proxy. > I am fairly new to boost::asio but have been doing event driven network > coding for 10 years. I still don't fully understand the netlib source so if > my approach is way off, please forgive me. > Cool, it's great to hear from you Rick! > 2. I added keepalive capabilities to the async server. I altered the > existing async server because I don't see how any self respecting server > wouldn't offer keepalive :) Cool. :) > My approach: I wrapped the chain of async functions back around to call > read_more. Specifically, in server/async_connection.hpp, in write(Range) I > register a callback to be read_more_wrapper(), which does the work of > default_error() and then calls read_more. This is to handle requests that > may be pipelined over the same connection. Since this callback is carried > through to be executed after all writes have completed. It should be safe to > handle pipelined requests in a serial fashion. > Okay, but how do you deal with the parsing? Do you reset the parser state per connection? Asynchronous server handlers can call connection.write(...) multiple times per request. The calls to connection.read(...) in the case of a handler that wants to read up data from the body of a POST/PUT request will also have to deal with the boundary issues -- granted that the HTTP/1.1 spec doesn't allow pipelining for POST/PUT requests, we'd want to be able to let the handler recover or at least deal with invalid data appropriately. Have you handled this? (Granted, I haven't looked at your patch just yet). > If there are no pending additional requests, then the async_read_some will > block indefinitely. > The second phase of the plan, then, is to register a deadline timer at start > of the new connection. Every new request that gets read will kick the > deadline timer back up to its max timeout time. When the timer does go off, > it cancels any operations that are pending on the Connection's socket. > This does two things, first and foremost, it keeps a hold of the > Connection's shared ptr, so that it is guaranteed not to be destroyed while > the keepalive is in effect. Secondly, it quite obviously will free the > async_read_some from its wait. That sounds alright, although we might have to guard for a race somehow there when the handler is actually reading from the same connection (in the case of a POST/PUT handler). Basically we have to know whether the timeout happened while the handler is waiting for a POST/PUT body or whether the timeout happened while at the boundaries of the GET requests. > I haven't bothered to fork cpp-netlib on github so I don't have a checkin to > make, but I did create a 'git diff' from boost/ I have attached it here > for your perusal. > Please let me know your preferred approach for reviewing and accepting > patches (I am assuming a pull request, which I can get around to) > You assume right that I would much rather prefer looking at diffs over at Github, so a pull request is going to be most appreciated. > 3. In attempting to benchmark my changes. I did note that yes, keepalive > works, and also that it breaks httperf. My problem is that httperf doesn't > seem to recognize a completed response unless the server closes the > connection. It claims to be a 1.1 compliant tester, and when it sends > requests it doesn't mention a connection: close in its headers, so I'm > assuming it should expect the connection to remain open. > I think you need to flush the data from the server end. I forget if TCP_NODELAY is turned on by default and whether httperf (I really don't know what that is, you have to pardon me I use Apache's ab for performance testing) actually has a short timeout setting for data transfer or whether the buffers are small enough to avoid buffer starvation. How much data are you sending from the server side during the benchmarks? > Does anyone know the correct procedure here, or why it might be thinking > that the responses have not completed? My concern here is that there is > some nuance of the HTTP 1.1 spec that I may have missed which allows servers > to delineate between responses since, with pipelining, multiple responses > may come all at once over the same connection. > As far as the spec goes, the server may send a "Connection: close" at any time to signal to the client that it will initiate a close to complete the transfer. Also if you're using Transfer-Encoding: Chunked, I think there's a special sequence to indicate the end of the response -- I need to cite that part, although an "empty" chunk usually signals the end of the message. If you just blindly keep the connection alive though, then the answer is the last request from the client side *should* have a "Connection: close" to let the server know that this is the last request in the pipeline. If it doesn't, the client may have to wait indefinitely for the server to close the connection while the server is stuck in a state where it would assume that there might be more requests that may come into the connection. It's a little complicated and this is the reason why I've been keeping this TODO in the back-burner for a while now. Although you are most welcome to send up a pull request that I can review and merge into the repo. :) > Thanks, > Rick Richardson Thank you too and I definitely hope to hear from you soon! -- Dean Michael Berris http://about.me/deanberris |
From: Rick R. <ric...@gm...> - 2011-03-20 18:57:08
|
oops.. I left out a if (error != boost::asio::error::operation_aborted) ... from the handle_timer function.. I was playing with some things and forgot to put this back in. Leads to erratic behavior when this is not present :) On Sun, Mar 20, 2011 at 12:11 PM, Rick Richardson <ric...@gm... > wrote: > Three things: > > 1. Hi, I'm Rick Richardson. I just got a hold of cpp-netlib because I am > looking to make a highly scalable and runtime reconfigurable reverse proxy. > I am fairly new to boost::asio but have been doing event driven network > coding for 10 years. I still don't fully understand the netlib source so if > my approach is way off, please forgive me. > > > 2. I added keepalive capabilities to the async server. I altered the > existing async server because I don't see how any self respecting server > wouldn't offer keepalive :) > > My approach: I wrapped the chain of async functions back around to call > read_more. Specifically, in server/async_connection.hpp, in write(Range) I > register a callback to be read_more_wrapper(), which does the work of > default_error() and then calls read_more. This is to handle requests that > may be pipelined over the same connection. Since this callback is carried > through to be executed after all writes have completed. It should be safe to > handle pipelined requests in a serial fashion. > > If there are no pending additional requests, then the async_read_some will > block indefinitely. > > The second phase of the plan, then, is to register a deadline timer at > start of the new connection. Every new request that gets read will kick the > deadline timer back up to its max timeout time. When the timer does go off, > it cancels any operations that are pending on the Connection's socket. > This does two things, first and foremost, it keeps a hold of the > Connection's shared ptr, so that it is guaranteed not to be destroyed while > the keepalive is in effect. Secondly, it quite obviously will free the > async_read_some from its wait. > > I haven't bothered to fork cpp-netlib on github so I don't have a checkin > to make, but I did create a 'git diff' from boost/ I have attached it > here for your perusal. > Please let me know your preferred approach for reviewing and accepting > patches (I am assuming a pull request, which I can get around to) > > > 3. In attempting to benchmark my changes. I did note that yes, keepalive > works, and also that it breaks httperf. My problem is that httperf doesn't > seem to recognize a completed response unless the server closes the > connection. It claims to be a 1.1 compliant tester, and when it sends > requests it doesn't mention a connection: close in its headers, so I'm > assuming it should expect the connection to remain open. > > Does anyone know the correct procedure here, or why it might be thinking > that the responses have not completed? My concern here is that there is > some nuance of the HTTP 1.1 spec that I may have missed which allows servers > to delineate between responses since, with pipelining, multiple responses > may come all at once over the same connection. > > > Thanks, > Rick Richardson > > |
From: Emre T. <emr...@gm...> - 2011-03-20 18:44:11
|
Hi Dean, While looking at the documentation I see that the handler is originally designed to be a function object. That's nice, so the application developer can: - Provide a function if the case is a simple one, or - If the implementation needs state information, provide a class with a function call operator overloaded. However, the call to the Handler::log() brakes that simplicity, the handler is forced to be a class. Below are the possible solutions to this problem, with each having their own pro & cons (mostly taste related). 1. Provide an extra error argument to the function. 2. Handler::log() assumption is fine, let's force the implementation to be a class with specific handle_data() and handle_error() functions. 3. Provide 2 different handler functions, one for data and one for error. So I have provided an interface to handle all. I think being easy is nothing to do with this. Here, the interface to the application developer is easy, and the implementation is a little bit complicated. By the way there is no need of the template argument Handler in this implementation. On Mar 20, 2011, at 12:04 PM, Dean Michael Berris wrote: > On Sat, Mar 19, 2011 at 9:22 PM, Emre Türkay <emr...@gm...> wrote: >> Hi Dean. >> >> What do you say about this interface? Take a look at the various possible handlers. >> > > Hmmm... I don't understand what you're trying to accomplish here. Care > to elaborate? If it's just a matter of providing an error handler, > that should be really *easy* and not this complicated. I appreciate > the code, but I don't know what problem you're trying to solve here. > > -- > Dean Michael Berris > http://about.me/deanberris |
From: Rick R. <ric...@gm...> - 2011-03-20 16:11:43
|
Three things: 1. Hi, I'm Rick Richardson. I just got a hold of cpp-netlib because I am looking to make a highly scalable and runtime reconfigurable reverse proxy. I am fairly new to boost::asio but have been doing event driven network coding for 10 years. I still don't fully understand the netlib source so if my approach is way off, please forgive me. 2. I added keepalive capabilities to the async server. I altered the existing async server because I don't see how any self respecting server wouldn't offer keepalive :) My approach: I wrapped the chain of async functions back around to call read_more. Specifically, in server/async_connection.hpp, in write(Range) I register a callback to be read_more_wrapper(), which does the work of default_error() and then calls read_more. This is to handle requests that may be pipelined over the same connection. Since this callback is carried through to be executed after all writes have completed. It should be safe to handle pipelined requests in a serial fashion. If there are no pending additional requests, then the async_read_some will block indefinitely. The second phase of the plan, then, is to register a deadline timer at start of the new connection. Every new request that gets read will kick the deadline timer back up to its max timeout time. When the timer does go off, it cancels any operations that are pending on the Connection's socket. This does two things, first and foremost, it keeps a hold of the Connection's shared ptr, so that it is guaranteed not to be destroyed while the keepalive is in effect. Secondly, it quite obviously will free the async_read_some from its wait. I haven't bothered to fork cpp-netlib on github so I don't have a checkin to make, but I did create a 'git diff' from boost/ I have attached it here for your perusal. Please let me know your preferred approach for reviewing and accepting patches (I am assuming a pull request, which I can get around to) 3. In attempting to benchmark my changes. I did note that yes, keepalive works, and also that it breaks httperf. My problem is that httperf doesn't seem to recognize a completed response unless the server closes the connection. It claims to be a 1.1 compliant tester, and when it sends requests it doesn't mention a connection: close in its headers, so I'm assuming it should expect the connection to remain open. Does anyone know the correct procedure here, or why it might be thinking that the responses have not completed? My concern here is that there is some nuance of the HTTP 1.1 spec that I may have missed which allows servers to delineate between responses since, with pipelining, multiple responses may come all at once over the same connection. Thanks, Rick Richardson |
From: Dean M. B. <mik...@gm...> - 2011-03-20 10:05:21
|
On Sat, Mar 19, 2011 at 9:22 PM, Emre Türkay <emr...@gm...> wrote: > Hi Dean. > > What do you say about this interface? Take a look at the various possible handlers. > Hmmm... I don't understand what you're trying to accomplish here. Care to elaborate? If it's just a matter of providing an error handler, that should be really *easy* and not this complicated. I appreciate the code, but I don't know what problem you're trying to solve here. -- Dean Michael Berris http://about.me/deanberris |
From: Emre T. <emr...@gm...> - 2011-03-19 13:22:58
|
Hi Dean. What do you say about this interface? Take a look at the various possible handlers. #include <iostream> // Fundamental meta-functions. struct my_specific_tag { }; template <typename T> struct has_a_tag { private: typedef char true_type; struct false_type { true_type _[2]; }; template <typename U> static true_type has_tag_checker(typename U::tag*); template <typename U> static false_type has_tag_checker(...); public: static const bool value = sizeof(has_tag_checker<T>(0)) == sizeof(true_type); }; template <typename T> struct has_not_a_tag { static const bool value = !has_a_tag<T>::value; }; template <bool Cond, class T = void> struct enable_if { typedef T type; }; template <class T> struct enable_if<false, T> { }; // A sample framework: #include <boost/function.hpp> #include <boost/bind.hpp> #include <string> struct data_type { data_type(const std::string& val) : value_(val) { } friend std::ostream& operator<<(std::ostream& os, const data_type& data) { return os << data.value_; } private: std::string value_; }; struct error_type { error_type(const std::string& val) : value_(val) { } friend std::ostream& operator<<(std::ostream& os, const error_type& error) { return os << error.value_; } private: std::string value_; }; struct framework { framework() : data_("No data"), error_("No error") { } template <typename T> typename enable_if<has_a_tag<T>::value>::type register_handler(T t) { priv_register_handler(t, typename T::tag()); } template <typename T> typename enable_if<has_not_a_tag<T>::value>::type register_handler(T t) { data_callback_ = boost::bind<void>(t, _1, error_); error_callback_ = boost::bind<void>(t, data_, _1); } template <typename T1, typename T2> void register_handler(T1 f1, T2 f2) { data_callback_ = f1; error_callback_ = f2; } void call(data_type data) { data_callback_(data); } void call(error_type error) { error_callback_(error); } private: template <typename T, typename U> void priv_register_handler(T t, U) { data_callback_ = boost::bind<void>(t, _1, error_); error_callback_ = boost::bind<void>(t, data_, _1); } template <typename T> void priv_register_handler(T t, my_specific_tag) { data_callback_ = boost::bind(&T::handle_data, &t, _1); error_callback_ = boost::bind(&T::handle_error, &t, _1); } private: boost::function<void(data_type)> data_callback_; boost::function<void(error_type)> error_callback_; data_type data_; error_type error_; }; // Handlers: void handler1(data_type data, error_type error) { std::cout << "handler1(" << "data: '" << data << "', " << "error: '" << error << "')" << std::endl; } struct handler2 { void operator()(data_type data, error_type error) { std::cout << "handler2(" << "data: '" << data << "', " << "error: '" << error << "')" << std::endl; } }; struct handler3 { typedef my_specific_tag tag; void handle_data(data_type data) { std::cout << "handler3(data: '" << data << "')" << std::endl; } void handle_error(error_type error) { std::cout << "handler3(error: '" << error << "')" << std::endl; } }; void handler4_data(data_type data) { std::cout << "handler4(data: '" << data << "')" << std::endl; } void handler4_error(error_type error) { std::cout << "handler4(error: '" << error << "')" << std::endl; } int main() { data_type data("data"); error_type error("error"); framework frm; frm.register_handler(handler1); frm.call(data); frm.call(error); frm.register_handler(handler2()); frm.call(data); frm.call(error); frm.register_handler(handler3()); frm.call(data); frm.call(error); frm.register_handler(handler4_data, handler4_error); frm.call(data); frm.call(error); } On Feb 24, 2011, at 10:02 AM, Dean Michael Berris wrote: > On Thu, Feb 24, 2011 at 3:55 PM, Emre Türkay <emr...@gm...> wrote: >> Hi Dean, >> >> On Feb 24, 2011, at 7:01 AM, Dean Michael Berris wrote: >> >>> Hi Emre, >>> >>> On Wed, Feb 23, 2011 at 6:22 AM, Emre Türkay <emr...@gm...> wrote: >>>> Hi folks, >>>> >>>> In file boost/network/protocol/http/server/sync_connection.http (in sync_connection::start), line 57, there is a call to Handler::log(string). >>>> 1. This conflicts with the documentation, where there is no hello_world::log() method implemented in the simple http server example. >>>> 2. Do we really need to keep it that way, i.e., we can make boost::system::system_error an extra argument to the handler function (like asio handlers). By this way, it would even be possible to implement a handler with a free standing function and pass the http::server a ptr to function instead of a functor, for simple cases. >>>> >>>> What you think? >>>> >>> >>> I like #2 -- do you have a pull request? :) >> >> No, I wanted to ask before diving in. I'm still reading the docs ;) I'll try if I can make it. >> > > Cool, no worries. :) > > I suggest looking at the cases where the log function is called -- I > think calling the handler with an extra error argument is a little > confusing. I like the approach of providing an error handling function > to the constructor of the HTTP server, and if one isn't provided a > default error handler is provided that optionally prints information > to standard error. There was a suggestion to use Boost.Log but I don't > see how this could be done with Boost.Log not yet being in the > releases (last I checked). > > This should be easy to do and I would really appreciate it if you can > give that a shot -- as I have very limited time at the moment to be > able to work on the library. > > Have a good one and I look forward to your pull requests! > > -- > Dean Michael Berris > about.me/deanberris |
From: Dean M. B. <mik...@gm...> - 2011-03-16 01:28:01
|
Hmmm... I thought I responded to this email. Anyway, please see details below: On Sat, Feb 26, 2011 at 4:48 AM, Severin Pappadeux <pap...@gm...> wrote: > Hi, All > below is echo server source code - Do Not Work. Could I extract headers from > request? >From the server handler, you can use the `request.headers` member -- that's a vector of http::request_header<Tag> types, which have a `name` and `value` member in turn. > Looking from three miles down to design decision, made in cpp-netlib, > it would be nice to have uniform methods, applicable to both request and > response. > There are, of course, some differences to be handled in a different way, but > for both > headers(request|response) shall return pointer/reference to headers, and > preferable of the same type, > body(request|response) shall return pointer/reference to headers, and > preferable of the same type > and so on and so forth. After all, they're very similar and both based upon > basic_message building block That's already done in 0.9. HTH -- Dean Michael Berris http://about.me/deanberris |
From: Hochhaus, A. <aho...@sa...> - 2011-03-14 01:14:48
|
Hi Dean, Thanks! On Sun, Mar 13, 2011 at 7:17 PM, Dean Michael Berris <mik...@gm...> wrote: > I remember having to look for bare > calls to 'throw' and replacing them with BOOST_THROW -- with the > intention that BOOST_NO_EXCEPTIONS would require users to provide > their own exception handler function. Right. As you say, my understanding is that replacing the "bare throw" calls with boost::throw_exception() allows for a user supplied alternative definition in the event that BOOST_NO_EXCEPTIONS is supplied. http://www.boost.org/doc/libs/1_46_1/libs/exception/doc/throw_exception.html > I hoped that these would be > sufficient, although I'm not sure whether you're looking for anything > more specific with regards to BOOST_NO_EXCEPTIONS. The only other thing that I can think of is to "#ifndef BOOST_NO_EXCEPTIONS" comment out all "try {" clauses and "} catch { ... }" blocks in cpp-netlib. This should be a safe assumption as the user supplied throw_exception is never allowed to return (so no need to handle error conditions). An example of commenting out the "try ... catch" stuff can be seen in this patch to the thread library. https://svn.boost.org/trac/boost/attachment/ticket/2100/boost_thread_BOOST_NO_EXCEPTIONS_20110306.diff With those two changes, I believe that compilation should succeed with -fno-exceptions. Thanks for your work on this amazing library. -Andy |
From: Dean M. B. <mik...@gm...> - 2011-03-14 00:17:42
|
On Mon, Mar 14, 2011 at 4:17 AM, Hochhaus, Andrew <aho...@sa...> wrote: > Hello, > > As cpp-netlib is being written for potential future inclusion in boost > it might be worth allowing complication without exceptions when > BOOST_NO_EXCEPTIONS is specified. That way projects which disallow > exceptions can compile with -fno-exceptions. Looking at the cpp-netlib > code it seems that very few sites utilize exceptions so it would > likely be a minimally invasive patch. > Thanks for the suggestion Andy. I remember having to look for bare calls to 'throw' and replacing them with BOOST_THROW -- with the intention that BOOST_NO_EXCEPTIONS would require users to provide their own exception handler function. I hoped that these would be sufficient, although I'm not sure whether you're looking for anything more specific with regards to BOOST_NO_EXCEPTIONS. HTH -- Dean Michael Berris http://about.me/deanberris |
From: Hochhaus, A. <aho...@sa...> - 2011-03-13 20:42:33
|
Hello, As cpp-netlib is being written for potential future inclusion in boost it might be worth allowing complication without exceptions when BOOST_NO_EXCEPTIONS is specified. That way projects which disallow exceptions can compile with -fno-exceptions. Looking at the cpp-netlib code it seems that very few sites utilize exceptions so it would likely be a minimally invasive patch. Thanks for consideration, Andy |
From: Dean M. B. <mik...@gm...> - 2011-03-07 06:22:26
|
Hi Everyone, I just recently finished a consulting project that tied me up good the past three months. Now that I'm pretty much free again to work on cpp-netlib, I went for the things that have been brought up most recently on the list (and the Boost developers mailing list): 1. The server tests that used a different port each, configurable at the command-line with a default. This is already in 0.9-devel. 2. An option to turn off the required external library to be linked with a macro (BOOST_NETWORK_NO_LIB). With this macro defined before any cpp-netlib headers are included (or on the command line) the functions that were made extern or just free functions at namespace level are marked 'inline' and have their definitions pulled in accordingly in each translation unit. This addresses Jeff Garland's and others' concern of the need for an external library when using cpp-netlib when it's always been header-only until 0.9. I'm still wrestling with the thought of making the header-only behavior a default, but I'm not married to the "external library as default" decision either. 3. A consistent look/view between server-side request/response objects and client-side request/response objects. Now they can be dealt with using the same directives and modifiers. 4. Starting to change the library name to Boost.Network (after the suggestions). #2 is still undocumented, but I am going to be including a Doxygen-Sphinx bridge that would allow us to write documentation in-line on the types and have Doxygen invoked when the Sphinx documentation is built. I found a Sphinx extension to do that and it looks like it can be bundled with cpp-netlib as well (because it's under a BSD license) -- it's called "breathe" and can be found here: http://michaeljones.github.com/breathe/ #3 has been in the branch for a while already and it should be doable to back-port some of the things to the 0.8 line. #4 is largely a documentation matter. I have decided that in order for the development of the network library to scale, that I would spear-head a mini-community effort that would be called "The C++ Network Library Project" taking in a diplomatic and consensus-building approach. This way those willing to contribute to the effort can help with setting the direction of the library, the design decisions, etc. with me starting as the "benevolent dictator" and letting more people jump into the fray and becoming co-maintainers and regular contributors. There are already a couple of people (Oleg Malashenko and Emre Turkay) who have recently contributing to the project that I would like to thank, and also give the chance to get a bigger role in the development of the library going forward. So for now the focus is still to get a review-ready library for inclusion in Boost that would be called Boost.Network. I think 0.9 will be ready in a couple of days and will be a the pre-1.0 snapshot that will be submitted for review, getting all the required documentation in place. At this time I'm still looking for able and willing review managers. Feedback would be most definitely appreciated. -- Dean Michael Berris http://about.me/deanberris |
From: Severin P. <pap...@gm...> - 2011-02-25 20:48:27
|
Hi, All below is echo server source code - Do Not Work. Could I extract headers from request? Looking from three miles down to design decision, made in cpp-netlib, it would be nice to have uniform methods, applicable to both *request* and*response. * There are, of course, some differences to be handled in a different way, but for both headers(request|response) shall return pointer/reference to headers, and preferable of the same type, body(request|response) shall return pointer/reference to headers, and preferable of the same type and so on and so forth. After all, they're very similar and both based upon basic_message building block sincerely Sever PS BOOST 1.46 gcc 4.4, Ubuntu 10.10 x64 ------------------------------------------------------------- cut here --------------------------------------------------------------------- // // "echo" server // simple test server, should just print source/body/headers of the request and copy into response // #include <boost/network/protocol/http/server.hpp> #include <boost/function_output_iterator.hpp> #include <string> #include <iostream> struct headerPrinter { std::ostream& _os; headerPrinter(std::ostream & os): _os(os) { } headerPrinter(const headerPrinter& hp): _os(hp._os) { } template <class Pair> void operator()(const Pair& p) { _os << p.first << ": " << p.second << std::endl; } }; struct theHandler { #pragma region Data std::ostream* _log; #pragma endregion #pragma region Ctor/Dtor theHandler(std::ostream* log = 0): _log(log) { } theHandler(const theHandler& thH): _log(thH._log) { } theHandler& operator=(const theHandler& thH) { if (this != &thH) { _log = thH._log; } return *this; } ~theHandler() { } #pragma endregion #pragma region Handler void operator() (const boost::network::http::server<theHandler>::request& request, boost::network::http::server<theHandler>::response& response) { using namespace boost::network; /* std::copy(headers_.begin(), headers_.end(), boost::make_function_output_iterator(header_printer(cout))); cout << endl; */ std::ostringstream data; // ok, printing source http::server<theHandler>::string_type src = source(request); data << "Hello, " << src << "!" << std::endl; // now printing body http::server<theHandler>::string_type body = body(request); data << body << std::endl; // try to print headers // DNW! // headers_range<http::server<theHandler>::request>::type _headers = request.headers(); // DNW either headers_range<http::server<theHandler>::request>::type _headers = headers(request); std::copy(_headers.begin(), _headers.end(), boost::make_function_output_iterator(headerPrinter(data))); data << std::endl; response = http::server<theHandler>::response::stock_reply(http::server<theHandler>::response::ok, data.str()); } #pragma endregion #pragma region Logger void log(...) { if (_log) { (*_log) << "LOG: " << std::endl; } } #pragma endregion }; int main(int argc, char * argv[]) { using namespace boost::network; if (argc != 3) { std::cerr << "Usage: " << argv[0] << " address" << " port" << std::endl; return EXIT_FAILURE; } try { // Creates the request handler theHandler handler; // Creates the server http::server<theHandler> server_(argv[1], argv[2], handler); // Runs the server server_.run(); } catch (std::exception &e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } |
From: Oleg M. <ole...@gm...> - 2011-02-25 07:27:31
|
On 25.02.2011 14:52, Severin Pappadeux wrote: > I've tried to copy printing body/header code from client to server (with > appropriate changes), > but it didn't compile. Any advices? We have issues with printing response body. Dean seems to be very busy to address this problem. Please take a look at that message and let me know if described workaround works for you. http://www.mail-archive.com/cpp...@li.../msg00689.html -- Best regards, Oleg Malashenko. |
From: Dean M. B. <mik...@gm...> - 2011-02-25 06:28:32
|
Hi Sever, Next time, please don't top-post. See my response in-lined below: On Fri, Feb 25, 2011 at 12:52 PM, Severin Pappadeux <pap...@gm...> wrote: > > Hi again > well,what would be nice to have is to print incoming requests > on server side, both header and body. Something like it is done in > one of the client examples. Would be nice to have it for > general use - for debugging and verbose logging That should be easy to do. > I've tried to copy printing body/header code from client to server (with appropriate changes), > but it didn't compile. Any advices? Can you show us the code? I can't help you without seeing the code you have and the errors you're encountering. -- Dean Michael Berris about.me/deanberris |
From: Severin P. <pap...@gm...> - 2011-02-25 04:52:53
|
Hi again well,what would be nice to have is to print incoming requests on server side, both header and body. Something like it is done in one of the client examples. Would be nice to have it for general use - for debugging and verbose logging I've tried to copy printing body/header code from client to server (with appropriate changes), but it didn't compile. Any advices? regards Sever On Wed, Feb 23, 2011 at 11:52 PM, Dean Michael Berris < mik...@gm...> wrote: > Hi Sever, > > On Thu, Feb 24, 2011 at 9:50 AM, Severin Pappadeux <pap...@gm...> > wrote: > > Hi, All > > Ubuntu 10.10 64bit, gcc-4.4 > > Build BOOST 1.46, and on top of it cpp-netlib 0.8.1. > > The only thing I did was to declare to use BOOST_FILESYSTEM version 2, > got > > one issue: > > some tests didn't do good, but when I tried them manually, seems to work > > (well, except MIME parser). > > Yeah, the MIME stuff is currently un-maintained but last I checked is > practically functional. > > > Now question: > > could I use the code to push files forth and back? Fielserver.cpp seems > to > > be good point to start to get data back, but could I push it > > from client to server to store data? > > You can definitely use the HTTP client(s) in cpp-netlib to push data > via PUT/POST -- you just have to craft the appropriate requests. At > the moment the way to do it is terribly inefficient, and I hope to be > able to address those issues soon. > > Having said that, the fileserver example can be extended to support > PUT/POST, but it wouldn't be a simple example anymore if I do that. ;) > > > thank you > > Thanks for trying it out. In case you have any more questions please > feel free to ask on the list again and we'll try to help you out as > soon as we can. :D > > -- > Dean Michael Berris > about.me/deanberris > |
From: Emre T. <emr...@gm...> - 2011-02-24 11:39:22
|
Hi Dean, We can provide various methods to register callback, actually maybe all of them. Using boost::function (with or without a system::error argument) + a class with log() function + two different handlers for data & error. But, to provide this flexibility we will need to have a "virtual" overhead somewhere deep in the implementation. I'll give it a try for this, after that we can think about it further. Take care, emre On Feb 24, 2011, at 10:02 AM, Dean Michael Berris wrote: > On Thu, Feb 24, 2011 at 3:55 PM, Emre Türkay <emr...@gm...> wrote: >> Hi Dean, >> >> On Feb 24, 2011, at 7:01 AM, Dean Michael Berris wrote: >> >>> Hi Emre, >>> >>> On Wed, Feb 23, 2011 at 6:22 AM, Emre Türkay <emr...@gm...> wrote: >>>> Hi folks, >>>> >>>> In file boost/network/protocol/http/server/sync_connection.http (in sync_connection::start), line 57, there is a call to Handler::log(string). >>>> 1. This conflicts with the documentation, where there is no hello_world::log() method implemented in the simple http server example. >>>> 2. Do we really need to keep it that way, i.e., we can make boost::system::system_error an extra argument to the handler function (like asio handlers). By this way, it would even be possible to implement a handler with a free standing function and pass the http::server a ptr to function instead of a functor, for simple cases. >>>> >>>> What you think? >>>> >>> >>> I like #2 -- do you have a pull request? :) >> >> No, I wanted to ask before diving in. I'm still reading the docs ;) I'll try if I can make it. >> > > Cool, no worries. :) > > I suggest looking at the cases where the log function is called -- I > think calling the handler with an extra error argument is a little > confusing. I like the approach of providing an error handling function > to the constructor of the HTTP server, and if one isn't provided a > default error handler is provided that optionally prints information > to standard error. There was a suggestion to use Boost.Log but I don't > see how this could be done with Boost.Log not yet being in the > releases (last I checked). > > This should be easy to do and I would really appreciate it if you can > give that a shot -- as I have very limited time at the moment to be > able to work on the library. > > Have a good one and I look forward to your pull requests! > > -- > Dean Michael Berris > about.me/deanberris |
From: Dean M. B. <mik...@gm...> - 2011-02-24 08:03:12
|
On Thu, Feb 24, 2011 at 3:55 PM, Emre Türkay <emr...@gm...> wrote: > Hi Dean, > > On Feb 24, 2011, at 7:01 AM, Dean Michael Berris wrote: > >> Hi Emre, >> >> On Wed, Feb 23, 2011 at 6:22 AM, Emre Türkay <emr...@gm...> wrote: >>> Hi folks, >>> >>> In file boost/network/protocol/http/server/sync_connection.http (in sync_connection::start), line 57, there is a call to Handler::log(string). >>> 1. This conflicts with the documentation, where there is no hello_world::log() method implemented in the simple http server example. >>> 2. Do we really need to keep it that way, i.e., we can make boost::system::system_error an extra argument to the handler function (like asio handlers). By this way, it would even be possible to implement a handler with a free standing function and pass the http::server a ptr to function instead of a functor, for simple cases. >>> >>> What you think? >>> >> >> I like #2 -- do you have a pull request? :) > > No, I wanted to ask before diving in. I'm still reading the docs ;) I'll try if I can make it. > Cool, no worries. :) I suggest looking at the cases where the log function is called -- I think calling the handler with an extra error argument is a little confusing. I like the approach of providing an error handling function to the constructor of the HTTP server, and if one isn't provided a default error handler is provided that optionally prints information to standard error. There was a suggestion to use Boost.Log but I don't see how this could be done with Boost.Log not yet being in the releases (last I checked). This should be easy to do and I would really appreciate it if you can give that a shot -- as I have very limited time at the moment to be able to work on the library. Have a good one and I look forward to your pull requests! -- Dean Michael Berris about.me/deanberris |
From: Emre T. <emr...@gm...> - 2011-02-24 07:55:35
|
Hi Dean, On Feb 24, 2011, at 7:01 AM, Dean Michael Berris wrote: > Hi Emre, > > On Wed, Feb 23, 2011 at 6:22 AM, Emre Türkay <emr...@gm...> wrote: >> Hi folks, >> >> In file boost/network/protocol/http/server/sync_connection.http (in sync_connection::start), line 57, there is a call to Handler::log(string). >> 1. This conflicts with the documentation, where there is no hello_world::log() method implemented in the simple http server example. >> 2. Do we really need to keep it that way, i.e., we can make boost::system::system_error an extra argument to the handler function (like asio handlers). By this way, it would even be possible to implement a handler with a free standing function and pass the http::server a ptr to function instead of a functor, for simple cases. >> >> What you think? >> > > I like #2 -- do you have a pull request? :) No, I wanted to ask before diving in. I'm still reading the docs ;) I'll try if I can make it. > > -- > Dean Michael Berris > about.me/deanberris |
From: Dean M. B. <mik...@gm...> - 2011-02-24 05:02:01
|
Hi Emre, On Wed, Feb 23, 2011 at 6:22 AM, Emre Türkay <emr...@gm...> wrote: > Hi folks, > > In file boost/network/protocol/http/server/sync_connection.http (in sync_connection::start), line 57, there is a call to Handler::log(string). > 1. This conflicts with the documentation, where there is no hello_world::log() method implemented in the simple http server example. > 2. Do we really need to keep it that way, i.e., we can make boost::system::system_error an extra argument to the handler function (like asio handlers). By this way, it would even be possible to implement a handler with a free standing function and pass the http::server a ptr to function instead of a functor, for simple cases. > > What you think? > I like #2 -- do you have a pull request? :) -- Dean Michael Berris about.me/deanberris |
From: Dean M. B. <mik...@gm...> - 2011-02-24 04:58:02
|
Hi Sebastien, On Thu, Feb 24, 2011 at 2:40 AM, Sébastien Taylor <me...@st...> wrote: > I am unable to build with the latest boost and netlib. Including > network.hpp causes errors in boost::spirit. This is using Visual > Studio 2010, x86 unicode build. > > #include <boost/network.hpp> > int main(int argc, char** argv) { return 0; } > > Produces this output on compile (trimmed for message size): > > > 1>------ Build started: Project: netlib-test, Configuration: Debug Win32 ------ > 1>Build started 2/23/2011 10:35:27 AM. > 1>InitializeBuildStatus: > 1> Touching "Debug\netlib-test.unsuccessfulbuild". > 1>ClCompile: > 1> netlib-test.cpp > 1>c:\libraries\boost\include\boost-1_46\boost\spirit\home\qi\nonterminal\rule.hpp(266): > error C2664: 'boost::spirit::qi::transform_attribute<Exposed,Transformed>::pre' > : cannot convert parameter 1 from 'boost::optional<T>' to > 'boost::spirit::qi::optional<Subject> &' [snip] This looks like a Spirit bug. Can you try building with Boost's SVN Trunk and see if it's still an issue? I remember submitting a test to the Spirit developers about this particular problem and I think they're looking at getting this addressed soon. BTW, have you tried building the tests that come with cpp-netlib? And can you say which version you're using? Thanks and I look forward to hearing from you again soon. -- Dean Michael Berris about.me/deanberris |
From: Dean M. B. <mik...@gm...> - 2011-02-24 04:53:09
|
Hi Sever, On Thu, Feb 24, 2011 at 9:50 AM, Severin Pappadeux <pap...@gm...> wrote: > Hi, All > Ubuntu 10.10 64bit, gcc-4.4 > Build BOOST 1.46, and on top of it cpp-netlib 0.8.1. > The only thing I did was to declare to use BOOST_FILESYSTEM version 2, got > one issue: > some tests didn't do good, but when I tried them manually, seems to work > (well, except MIME parser). Yeah, the MIME stuff is currently un-maintained but last I checked is practically functional. > Now question: > could I use the code to push files forth and back? Fielserver.cpp seems to > be good point to start to get data back, but could I push it > from client to server to store data? You can definitely use the HTTP client(s) in cpp-netlib to push data via PUT/POST -- you just have to craft the appropriate requests. At the moment the way to do it is terribly inefficient, and I hope to be able to address those issues soon. Having said that, the fileserver example can be extended to support PUT/POST, but it wouldn't be a simple example anymore if I do that. ;) > thank you Thanks for trying it out. In case you have any more questions please feel free to ask on the list again and we'll try to help you out as soon as we can. :D -- Dean Michael Berris about.me/deanberris |
From: Severin P. <pap...@gm...> - 2011-02-24 01:51:05
|
Hi, All Ubuntu 10.10 64bit, gcc-4.4 Build BOOST 1.46, and on top of it cpp-netlib 0.8.1. The only thing I did was to declare to use BOOST_FILESYSTEM version 2, got one issue: some tests didn't do good, but when I tried them manually, seems to work (well, except MIME parser). Now question: could I use the code to push files forth and back? Fielserver.cpp seems to be good point to start to get data back, but could I push it from client to server to store data? thank you Sever |
From: Sébastien T. <me...@st...> - 2011-02-23 18:51:40
|
I am unable to build with the latest boost and netlib. Including network.hpp causes errors in boost::spirit. This is using Visual Studio 2010, x86 unicode build. #include <boost/network.hpp> int main(int argc, char** argv) { return 0; } Produces this output on compile (trimmed for message size): 1>------ Build started: Project: netlib-test, Configuration: Debug Win32 ------ 1>Build started 2/23/2011 10:35:27 AM. 1>InitializeBuildStatus: 1> Touching "Debug\netlib-test.unsuccessfulbuild". 1>ClCompile: 1> netlib-test.cpp 1>c:\libraries\boost\include\boost-1_46\boost\spirit\home\qi\nonterminal\rule.hpp(266): error C2664: 'boost::spirit::qi::transform_attribute<Exposed,Transformed>::pre' : cannot convert parameter 1 from 'boost::optional<T>' to 'boost::spirit::qi::optional<Subject> &' 1> with 1> [ 1> Exposed=boost::optional<std::basic_string<char,std::char_traits<char>,std::allocator<char>>>, 1> Transformed=std::basic_string<char,std::char_traits<char>,std::allocator<char>> 1> ] 1> and 1> [ 1> T=std::basic_string<char,std::char_traits<char>,std::allocator<char>> 1> ] 1> and 1> [ 1> Subject=std::basic_string<char,std::char_traits<char>,std::allocator<char>> 1> ] 1> c:\libraries\boost\include\boost-1_46\boost\spirit\home\qi\reference.hpp(43) : see reference to function template instantiation 'bool boost::spirit::qi::rule<Iterator,T1>::parse<Context,Skipper,Attribute>(Iterator &,const Iterator &,Context &,const Skipper &,Attribute &) const' being compiled 1> with 1> [ 1> Iterator=iterator, 1> T1=std::basic_string<char,std::char_traits<char>,std::allocator<char>> (void), 1> |
From: Emre T. <emr...@gm...> - 2011-02-22 22:23:03
|
Hi folks, In file boost/network/protocol/http/server/sync_connection.http (in sync_connection::start), line 57, there is a call to Handler::log(string). 1. This conflicts with the documentation, where there is no hello_world::log() method implemented in the simple http server example. 2. Do we really need to keep it that way, i.e., we can make boost::system::system_error an extra argument to the handler function (like asio handlers). By this way, it would even be possible to implement a handler with a free standing function and pass the http::server a ptr to function instead of a functor, for simple cases. What you think? emre |