LCOV - code coverage report
Current view: top level - xenolith/resources/network - XLNetworkRequest.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 46 101 45.5 %
Date: 2024-05-12 00:16:13 Functions: 10 20 50.0 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #include "XLNetworkController.h"
      24             : #include "SPNetworkContext.h"
      25             : #include "XLNetworkRequest.h"
      26             : 
      27             : namespace STAPPLER_VERSIONIZED stappler::xenolith::network {
      28             : 
      29           0 : bool Handle::init(StringView url) {
      30           0 :         return NetworkHandle::init(Method::Get, url);
      31             : }
      32             : 
      33           0 : bool Handle::init(StringView url, FilePath fileName) {
      34           0 :     if (!init(Method::Get, url)) {
      35           0 :         return false;
      36             :     }
      37             : 
      38           0 :     if (!fileName.get().empty()) {
      39           0 :         setReceiveFile(fileName.get(), false);
      40             :     }
      41           0 :     return true;
      42             : }
      43             : 
      44          21 : bool Handle::init(Method method, StringView url) {
      45          21 :         return NetworkHandle::init(method, url);
      46             : }
      47             : 
      48          21 : bool Handle::prepare(Context *ctx) {
      49          21 :         if (_mtime > 0) {
      50           0 :                 auto httpTime = Time::microseconds(_mtime).toHttp<Interface>();
      51           0 :                 ctx->headers = curl_slist_append(ctx->headers, toString("If-Modified-Since: ", httpTime).data());
      52           0 :         }
      53             : 
      54          21 :         if (!_etag.empty()) {
      55           0 :                 ctx->headers = curl_slist_append(ctx->headers, toString("If-None-Match: ", _etag).data());
      56             :         }
      57             : 
      58          21 :         if (!_sharegroup.empty() && ctx->share) {
      59           0 :                 setCookieFile(filesystem::writablePath<Interface>(toString("network.", _controller->getName(), ".", _sharegroup, ".cookies")));
      60             :         }
      61             : 
      62          21 :         if (!_controller->getApplication()->getInfo().userAgent.empty()) {
      63          21 :                 setUserAgent(_controller->getApplication()->getInfo().userAgent);
      64             :         }
      65             : 
      66          21 :         return true;
      67             : }
      68             : 
      69          21 : bool Handle::finalize(Context *ctx, bool ret) {
      70          21 :         _success = ctx->success;
      71             : 
      72          21 :         if (getResponseCode() < 300) {
      73          21 :                 auto httpTime = getReceivedHeaderString("Last-Modified");
      74          21 :                 auto eTag = getReceivedHeaderString("ETag");
      75             : 
      76          21 :                 _mtime = Time::fromHttp(httpTime).toMicroseconds();
      77          21 :                 _etag = eTag.str<Interface>();
      78             :         } else {
      79           0 :                 auto &f = getReceiveDataSource();
      80           0 :                 if (auto str = std::get_if<String>(&f)) {
      81           0 :                         filesystem::remove(*str);
      82             :                 }
      83             :         }
      84             : 
      85          21 :         return ret;
      86             : }
      87             : 
      88          42 : Request::~Request() { }
      89             : 
      90          21 : bool Request::init(const Callback<bool(Handle &)> &setupCallback, Rc<Ref> &&ref) {
      91          21 :         _owner = move(ref);
      92          21 :         return setupCallback(_handle);
      93             : }
      94             : 
      95           0 : void Request::perform(Application *app, CompleteCallback &&cb) {
      96           0 :         auto c = app->getExtension<Controller>();
      97           0 :         if (!c) {
      98           0 :                 return;
      99             :         }
     100             : 
     101           0 :         perform(c, move(cb));
     102             : }
     103             : 
     104          21 : void Request::perform(Controller *c, CompleteCallback &&cb) {
     105          21 :         if (cb) {
     106          21 :                 _onComplete = move(cb);
     107             :         }
     108             : 
     109          21 :         _handle._request = this;
     110          21 :         _handle._controller = c;
     111             : 
     112          21 :         _uploadProgress = pair(0, 0);
     113          21 :         _downloadProgress = pair(0, 0);
     114             : 
     115          21 :         auto &source = _handle.getReceiveDataSource();
     116          21 :         if (std::holds_alternative<std::monostate>(source)) {
     117           0 :                 if (!_ignoreResponseData) {
     118           0 :                         _targetHeaderCallback = _handle.getHeaderCallback();
     119             : 
     120           0 :                         _handle.setHeaderCallback([this] (StringView key, StringView value) {
     121           0 :                                 handleHeader(key, value);
     122           0 :                         });
     123             : 
     124           0 :                         _handle.setReceiveCallback([this] (char *buf, size_t size) -> size_t {
     125           0 :                                 return handleReceive(buf, size);
     126             :                         });
     127           0 :                         _handle.setVerifyTls(false);
     128             :                 }
     129             :         }
     130          21 :         c->run(this);
     131          21 : }
     132             : 
     133           0 : void Request::setIgnoreResponseData(bool value) {
     134           0 :         if (!_running) {
     135           0 :                 _ignoreResponseData = value;
     136             :         }
     137           0 : }
     138             : 
     139           0 : void Request::setUploadProgress(ProgressCallback &&cb) {
     140           0 :         _onUploadProgress = move(cb);
     141           0 : }
     142             : 
     143          21 : void Request::setDownloadProgress(ProgressCallback &&cb) {
     144          21 :         _onDownloadProgress = move(cb);
     145          21 : }
     146             : 
     147           0 : void Request::handleHeader(StringView key, StringView value) {
     148           0 :         if (!_ignoreResponseData) {
     149           0 :                 if (key == "content-length") {
     150           0 :                         auto length = value.readInteger(10).get(0);
     151           0 :                         _data.resize(size_t(length));
     152             :                 }
     153             :         }
     154           0 :         if (_targetHeaderCallback) {
     155           0 :                 _targetHeaderCallback(key, value);
     156             :         }
     157           0 : }
     158             : 
     159           0 : size_t Request::handleReceive(char *buf, size_t nbytes) {
     160           0 :         if (_data.size() < (nbytes + _nbytes)) {
     161           0 :                 _data.resize(nbytes + _nbytes);
     162             :         }
     163           0 :         memcpy(_data.data() + _nbytes, buf, nbytes);
     164           0 :         _nbytes += nbytes;
     165           0 :         return nbytes;
     166             : }
     167             : 
     168          21 : void Request::notifyOnComplete(bool success) {
     169          21 :         if (_onComplete) {
     170          21 :                 _onComplete(*this, success);
     171             :         }
     172          21 :         _running = false;
     173          21 :         _handle._request = nullptr;
     174          21 : }
     175             : 
     176           0 : void Request::notifyOnUploadProgress(int64_t total, int64_t now) {
     177           0 :         _uploadProgress = pair(total, std::max(now, _uploadProgress.second)); // prevent out-of-order updates
     178           0 :         if (_onUploadProgress && _uploadProgress.second == now) {
     179           0 :                 _onUploadProgress(*this, total, now);
     180             :         }
     181           0 : }
     182             : 
     183          21 : void Request::notifyOnDownloadProgress(int64_t total, int64_t now) {
     184          21 :         _downloadProgress = pair(total, std::max(now, _downloadProgress.second)); // prevent out-of-order updates
     185          21 :         if (_onDownloadProgress && _downloadProgress.second == now) {
     186          21 :                 _onDownloadProgress(*this, total, now);
     187             :         }
     188          21 : }
     189             : 
     190             : }

Generated by: LCOV version 1.14