libtasks Documentation  1.6
http_sender.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014 ADTECH GmbH
3  * Licensed under MIT (https://github.com/adtechlabs/libtasks/blob/master/COPYING)
4  *
5  * Author: Andreas Pohl
6  */
7 
8 #ifndef _HTTP_SENDER_H_
9 #define _HTTP_SENDER_H_
10 
11 #include <memory>
12 #include <cassert>
13 #include <cstring>
14 
15 #include <tasks/dispatcher.h>
16 #include <tasks/worker.h>
17 #include <tasks/logging.h>
18 #include <tasks/net_io_task.h>
19 #include <tasks/net/http_request.h>
21 #include <tasks/net/socket.h>
22 
23 namespace tasks {
24 namespace net {
25 
27  public:
28  virtual bool handle_response(std::shared_ptr<http_response> response) = 0;
29 };
30 
31 template <class handler_type>
32 class http_sender : public net_io_task {
33  public:
35 
39  http_sender(std::shared_ptr<handler_type> handler)
40  : net_io_task(EV_UNDEF), m_response(new http_response()), m_handler(handler) {}
41 
44  bool success = true;
45  try {
46  if (EV_READ & events) {
47  m_response->read_data(socket());
48  if (m_response->done()) {
49  if (nullptr == m_handler) {
50  m_handler = std::make_shared<handler_type>();
51  }
52  success = m_handler->handle_response(m_response);
53  m_response->clear();
54  }
55  } else if (EV_WRITE & events) {
56  m_request->write_data(socket());
57  if (m_request->done()) {
58  // Reset the request buffer to be able to reuse the same object again
59  m_request->clear();
60  // Read the response
61  set_events(EV_READ);
62  update_watcher(worker);
63  }
64  }
65  } catch (tasks::tasks_exception& e) {
66  set_exception(e);
67  success = false;
68  }
69  return success;
70  }
71 
73  inline bool connected() const {
74  return socket().fd() != -1;
75  }
76 
79  inline void send(std::shared_ptr<http_request> request) {
80  m_request = request;
81  const std::string& host = m_request->header("Host");
82  tdbg("http_sender: Sending request to " << host << std::endl);
83  // Find the worker if keepalive is used, and this is not the first request, or the object is reused to connect
84  // to a different host.
85  tasks::worker* worker = tasks::dispatcher::instance()->get_worker_by_task(this);
86  if (connected() && m_host != host) {
87  // Stop the watcher and close an existing connection.
88  tdbg("http_sender: Closing connection to " << m_host << ":" << m_port << std::endl);
89  stop_watcher(worker);
90  socket().close();
91  }
92  m_host = host;
93  m_port = m_request->port();
94  m_request->set_header("Host", m_host);
95  set_events(EV_WRITE);
96  if (!connected()) {
97  // Connect
98  tdbg("http_sender: Connecting " << m_host << ":" << m_port << std::endl);
100  tasks::dispatcher::instance()->add_event_task(this);
101  } else {
102  update_watcher(worker);
103  }
104  }
105 
106  private:
107  std::shared_ptr<http_request> m_request;
108  std::shared_ptr<http_response> m_response;
109  std::shared_ptr<handler_type> m_handler;
110  std::string m_host;
111  int m_port = 80;
112 };
113 
114 } // net
115 } // tasks
116 
117 #endif // _HTTP_SENDER_H_
static std::shared_ptr< dispatcher > instance()
Definition: dispatcher.h:75
The HTTP response implementation.
Definition: http_response.h:19
std::shared_ptr< http_request > m_request
Definition: http_sender.h:107
virtual void close()
Definition: io_base.h:24
The net_io_task implements the base for socket based network tasks.
Definition: net_io_task.h:21
#define tdbg(m)
Definition: logging.h:54
virtual bool handle_response(std::shared_ptr< http_response > response)=0
std::shared_ptr< handler_type > m_handler
Definition: http_sender.h:109
bool connected() const
Definition: http_sender.h:73
int events() const
Return the monitored events.
Definition: io_task_base.h:38
int fd() const
Definition: io_base.h:22
Tasks execption class.
virtual void update_watcher(worker *worker)
Udate a watcher in the context of the given worker.
http_sender(std::shared_ptr< handler_type > handler)
Definition: http_sender.h:39
net::socket & socket()
Provide access to the underlying socket object.
Definition: net_io_task.h:35
bool handle_event(tasks::worker *worker, int events)
Definition: http_sender.h:43
void set_exception(tasks_exception &e)
Set an exception to report an error.
Definition: error_base.h:54
std::shared_ptr< http_response > m_response
Definition: http_sender.h:108
virtual void stop_watcher(worker *worker)
Stop a watcher in the context of the given worker.
void send(std::shared_ptr< http_request > request)
Definition: http_sender.h:79
void connect(std::string path)
Definition: socket.cpp:147
void set_events(int events)
Update the events the object monitors.