20 #ifndef URL_H_9DAEGSMV
21 #define URL_H_9DAEGSMV
26 #define DOWNLOAD_IF_NECESSARY if (!_isDownloaded) { download(true); }
34 #include <condition_variable>
35 #include <curl/curl.h>
36 #include <uriparser/Uri.h>
38 #define USCXML_URI_STRING(obj, field) std::string(obj.field.first, obj.field.afterLast - obj.field.first)
46 virtual void downloadStarted(
const URL& url) {};
47 virtual void downloadCompleted(
const URL& url) {};
48 virtual void downloadFailed(
const URL& url,
int errorCode) {};
49 virtual void headerChunkReceived(
const URL& url,
const std::string& headerChunk) {};
50 virtual void contentChunkReceived(
const URL& url,
const std::string& contentChunk) {};
58 class USCXML_API
URLImpl :
public std::enable_shared_from_this<URLImpl> {
60 URLImpl(
const std::string& url);
63 bool isAbsolute()
const {
65 return _uri.absolutePath || ((_uri.hostText.first !=
nullptr) && (_uri.pathHead !=
nullptr));
68 std::string scheme()
const {
69 return USCXML_URI_STRING(_uri, scheme);
72 std::string userInfo()
const {
73 return USCXML_URI_STRING(_uri, userInfo);
76 std::string host()
const {
77 return USCXML_URI_STRING(_uri, hostText);
80 std::string port()
const {
81 return USCXML_URI_STRING(_uri, portText);
84 std::string fragment()
const {
85 return USCXML_URI_STRING(_uri, fragment);
88 std::map<std::string, std::string> query()
const;
89 std::string path()
const;
90 std::list<std::string> pathComponents()
const;
95 static URL resolveWithCWD(
URLImpl* relativeURL);
99 _monitors.insert(monitor);
102 _monitors.erase(monitor);
106 void addOutHeader(
const std::string& key,
const std::string& value) {
107 _outHeader[key] = value;
109 void setOutContent(
const std::string& content) {
110 _outContent = content;
111 _requestType = URLRequestType::POST;
113 void setRequestType(URLRequestType requestType) {
114 _requestType = requestType;
118 const std::map<std::string, std::string> getInHeaderFields() {
119 DOWNLOAD_IF_NECESSARY
123 const std::string getInHeaderField(
const std::string& key) {
124 DOWNLOAD_IF_NECESSARY
125 if (_inHeaders.find(key) != _inHeaders.end()) {
126 return _inHeaders[key];
131 const std::string getStatusCode()
const {
136 const std::string getStatusMessage()
const {
141 const std::string getInContent(
bool forceReload =
false) {
143 _isDownloaded =
false;
144 DOWNLOAD_IF_NECESSARY
145 return _rawInContent.str();
148 const void download(
bool blocking =
false);
150 operator Data()
const;
151 operator std::string()
const;
158 CURL* getCurlHandle();
159 static size_t writeHandler(
void *ptr,
size_t size,
size_t nmemb,
void *userdata);
160 static size_t headerHandler(
void *ptr,
size_t size,
size_t nmemb,
void *userdata);
162 void downloadStarted();
163 void downloadCompleted();
164 void downloadFailed(CURLcode errorCode);
166 static void prepareException(
ErrorEvent& exception,
int errorCode,
const std::string& origUri, UriParserStateA* parser);
169 std::stringstream _rawInContent;
170 std::stringstream _rawInHeader;
171 std::map<std::string, std::string> _inHeaders;
173 std::string _outContent;
174 std::map<std::string, std::string> _outHeader;
175 URLRequestType _requestType;
177 std::string _statusCode;
178 std::string _statusMsg;
183 std::condition_variable_any _condVar;
184 std::recursive_mutex _mutex;
186 std::set<URLMonitor*> _monitors;
195 URL(
const std::string url) : _impl(
new URLImpl(url)) {}
198 return _impl->isAbsolute();
201 std::string scheme() {
202 return _impl->scheme();
205 std::string userInfo() {
206 return _impl->userInfo();
210 return _impl->host();
214 return _impl->port();
217 std::string fragment() {
218 return _impl->fragment();
221 std::map<std::string, std::string> query() {
222 return _impl->query();
226 return _impl->path();
229 std::list<std::string> pathComponents() {
230 return _impl->pathComponents();
234 return _impl->normalize();
237 static URL resolve(
URL relativeURL,
URL absoluteURL) {
238 return URLImpl::resolve(relativeURL._impl.get(), absoluteURL._impl.get());
241 static URL resolveWithCWD(
URL relativeURL) {
242 return URLImpl::resolveWithCWD(relativeURL._impl.get());
245 static URL refer(
URL absoluteSource,
URL absoluteBase) {
246 return URLImpl::refer(absoluteSource._impl.get(), absoluteBase._impl.get());
249 void addOutHeader(
const std::string& key,
const std::string& value) {
250 return _impl->addOutHeader(key, value);
253 void setOutContent(
const std::string& content) {
254 return _impl->setOutContent(content);
256 void setRequestType(URLRequestType requestType) {
257 return _impl->setRequestType(requestType);
260 const std::map<std::string, std::string> getInHeaderFields() {
261 return _impl->getInHeaderFields();
264 const std::string getInHeaderField(
const std::string& key) {
265 return _impl->getInHeaderField(key);
268 const std::string getStatusCode()
const {
269 return _impl->getStatusCode();
272 const std::string getStatusMessage()
const {
273 return _impl->getStatusMessage();
276 const std::string getInContent(
bool forceReload =
false) {
277 return _impl->getInContent(forceReload);
280 const void download(
bool blocking =
false)
const {
281 return _impl->download(blocking);
285 return _impl->addMonitor(monitor);
288 return _impl->removeMonitor(monitor);
291 operator Data()
const {
292 return _impl->operator
Data();
295 operator std::string() {
296 return (*_impl.get());
300 std::shared_ptr<URLImpl> _impl;
306 static void fetchURL(
URL& url);
307 static void breakURL(
URL& url);
319 static void run(
void* instance);
322 std::thread* _thread;
323 std::condition_variable_any _condVar;
324 std::recursive_mutex _mutex;
327 std::map<CURL*, URL> _handlesToURLs;
Definition: InterpreterIssue.cpp:33
#define PIMPL_OPERATORS(type)
The usual operators as required for the PIMPL pattern.
Definition: Common.h:60