1 | // Aseprite Network Library |
2 | // Copyright (c) 2001-2016 David Capello |
3 | // |
4 | // This file is released under the terms of the MIT license. |
5 | // Read LICENSE.txt for more information. |
6 | |
7 | #ifdef HAVE_CONFIG_H |
8 | #include "config.h" |
9 | #endif |
10 | |
11 | #include "net/http_request.h" |
12 | |
13 | #include "base/debug.h" |
14 | #include "net/http_headers.h" |
15 | #include "net/http_response.h" |
16 | |
17 | #include <curl/curl.h> |
18 | |
19 | namespace net { |
20 | |
21 | class HttpRequestImpl { |
22 | public: |
23 | HttpRequestImpl(const std::string& url) |
24 | : m_curl(curl_easy_init()) |
25 | , m_headerlist(nullptr) |
26 | , m_response(nullptr) { |
27 | curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this); |
28 | curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, &HttpRequestImpl::writeBodyCallback); |
29 | curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str()); |
30 | curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, 1); |
31 | } |
32 | |
33 | ~HttpRequestImpl() { |
34 | if (m_headerlist) |
35 | curl_slist_free_all(m_headerlist); |
36 | |
37 | curl_easy_cleanup(m_curl); |
38 | } |
39 | |
40 | void (const HttpHeaders& ) { |
41 | if (m_headerlist) { |
42 | curl_slist_free_all(m_headerlist); |
43 | m_headerlist = NULL; |
44 | } |
45 | |
46 | std::string tmp; |
47 | for (HttpHeaders::const_iterator it=headers.begin(), end=headers.end(); it!=end; ++it) { |
48 | tmp = it->first; |
49 | tmp += ": " ; |
50 | tmp += it->second; |
51 | |
52 | m_headerlist = curl_slist_append(m_headerlist, tmp.c_str()); |
53 | } |
54 | |
55 | curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_headerlist); |
56 | } |
57 | |
58 | bool send(HttpResponse& response) { |
59 | m_response = &response; |
60 | int res = curl_easy_perform(m_curl); |
61 | if (res != CURLE_OK) |
62 | return false; |
63 | |
64 | long code; |
65 | curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &code); |
66 | m_response->setStatus(code); |
67 | return true; |
68 | } |
69 | |
70 | void abort() { |
71 | curl_easy_setopt(m_curl, CURLOPT_TIMEOUT_MS, 1); |
72 | curl_easy_setopt(m_curl, CURLOPT_CONNECTTIMEOUT_MS, 1); |
73 | } |
74 | |
75 | private: |
76 | std::size_t writeBody(char* ptr, std::size_t bytes) { |
77 | ASSERT(m_response != NULL); |
78 | m_response->write(ptr, bytes); |
79 | return bytes; |
80 | } |
81 | |
82 | static std::size_t writeBodyCallback(char* ptr, std::size_t size, std::size_t nmemb, void* userdata) { |
83 | HttpRequestImpl* req = reinterpret_cast<HttpRequestImpl*>(userdata); |
84 | return req->writeBody(ptr, size*nmemb); |
85 | } |
86 | |
87 | CURL* m_curl; |
88 | curl_slist* ; |
89 | HttpResponse* m_response; |
90 | }; |
91 | |
92 | HttpRequest::HttpRequest(const std::string& url) |
93 | : m_impl(new HttpRequestImpl(url)) |
94 | { |
95 | } |
96 | |
97 | HttpRequest::~HttpRequest() |
98 | { |
99 | delete m_impl; |
100 | } |
101 | |
102 | void HttpRequest::(const HttpHeaders& ) |
103 | { |
104 | m_impl->setHeaders(headers); |
105 | } |
106 | |
107 | bool HttpRequest::send(HttpResponse& response) |
108 | { |
109 | return m_impl->send(response); |
110 | } |
111 | |
112 | void HttpRequest::abort() |
113 | { |
114 | m_impl->abort(); |
115 | } |
116 | |
117 | } // namespace net |
118 | |