• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 21100551564

17 Jan 2026 08:40PM UTC coverage: 60.504% (+0.01%) from 60.492%
21100551564

Pull #857

github

turleypol
fixed scope
Pull Request #857: ClangTidy readability-else-after-return

837 of 1874 new or added lines in 151 files covered. (44.66%)

48 existing lines in 26 files now uncovered.

44445 of 73458 relevant lines covered (60.5%)

515341.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.88
/pol-core/pol/module/httpmod.cpp
1
/** @file
2
 *
3
 * @par History
4
 */
5

6
#include "httpmod.h"
7
#include "../../bscript/berror.h"
8
#include "../../bscript/impstr.h"
9
#include "../../clib/logfacility.h"
10
#include "../../clib/network/wnsckt.h"
11
#include "../../clib/stlutil.h"
12
#include "../../plib/systemstate.h"
13
#include "../uoexec.h"
14

15
#include <module_defs/http.h>
16

17
namespace Pol
18
{
19
namespace Core
20
{
21
std::string http_decodestr( const std::string& s );
22
std::string reasonPhrase( int code );
23
}  // namespace Core
24

25
namespace Module
26
{
27
using namespace Bscript;
28

29
HttpExecutorModule::HttpExecutorModule( Bscript::Executor& exec, Clib::Socket&& isck )
18✔
30
    : Bscript::TmplExecutorModule<HttpExecutorModule, Core::PolModule>( exec ),
31
      sck_( std::move( isck ) ),
18✔
32
      continuing_offset( 0 )
36✔
33
{
34
}
18✔
35

36
HttpExecutorModule::~HttpExecutorModule()
36✔
37
{
38
  if ( sck_.connected() )
18✔
39
  {
40
    unsigned nsent;
41
    std::string line;
18✔
42

43
    // Since status line and headers are now controlled by script, check if they are sendable.
44
    if ( !cannotSendStatus )
18✔
45
    {
46
      line += "HTTP/1.1 200 OK\n";
1✔
47
    }
48
    if ( !cannotSendHeaders )
18✔
49
    {
50
      if ( !hasCustomContentType )
6✔
51
      {
52
        line += "Content-Type: text/html\n\n";
5✔
53
      }
54
      else
55
      {
56
        line += "\n";
1✔
57
      }
58

59
      if ( !line.empty() )
6✔
60
      {
61
        sck_.send_nowait( (void*)( line.c_str() ), static_cast<unsigned int>( line.length() ),
6✔
62
                          &nsent );
63
      }
64
    }
65
  }
18✔
66
}
36✔
67

68
BObjectImp* HttpExecutorModule::mf_WriteStatus()
12✔
69
{
70
  int code;
71
  const String* reason;
72

73
  if ( !sck_.connected() )
12✔
74
  {
75
    exec.seterror( true );
×
76
    return new BError( "Socket is disconnected" );
×
77
  }
78

79
  if ( getParam( 0, code ) && getStringParam( 1, reason ) )
12✔
80
  {
81
    if ( cannotSendStatus )
12✔
82
    {
83
      return new BError(
84
          "Cannot send status after WriteStatus, WriteHeader, WriteHtml, or WriteHtmlRaw" );
6✔
85
    }
86

87
    unsigned nsent;
88
    std::string line = "HTTP/1.1 " + std::to_string( code );
6✔
89
    auto& reasonString = reason->value();
6✔
90

91
    if ( reasonString.empty() )
6✔
92
    {
93
      std::string defaultReason = Core::reasonPhrase( code );
5✔
94
      if ( !defaultReason.empty() )
5✔
95
      {
96
        line += " " + defaultReason + "\n";
5✔
97
      }
98
    }
5✔
99
    else
100
    {
101
      line += " " + reasonString + "\n";
1✔
102
    }
103

104
    bool res =
105
        sck_.send_nowait( (void*)( line.c_str() + continuing_offset ),
6✔
106
                          static_cast<unsigned int>( line.length() - continuing_offset ), &nsent );
6✔
107

108
    if ( res )
6✔
109
    {
110
      cannotSendStatus = true;
6✔
111
      continuing_offset = 0;
6✔
112
      return new BLong( 1 );
6✔
113
    }
114

NEW
115
    continuing_offset += nsent;
×
NEW
116
    auto& uoex = uoexec();
×
NEW
117
    uoex.SleepForMs( 500u );
×
NEW
118
    --uoex.PC;
×
NEW
119
    return uoex.fparams[0]->impptr();
×
120
  }
6✔
121
  return new BError( "Invalid parameter type" );
×
122
}
123

124

125
BObjectImp* HttpExecutorModule::mf_WriteHeader()
14✔
126
{
127
  const String* name;
128
  const String* value;
129

130
  if ( !sck_.connected() )
14✔
131
  {
132
    exec.seterror( true );
×
133
    return new BError( "Socket is disconnected" );
×
134
  }
135

136
  if ( getStringParam( 0, name ) && getStringParam( 1, value ) )
14✔
137
  {
138
    if ( cannotSendHeaders )
14✔
139
    {
140
      return new BError( "Cannot send headers after WriteHtml or WriteHtmlRaw" );
4✔
141
    }
142

143
    if ( Clib::strlowerASCII( name->value() ) == "content-type" )
10✔
144
    {
145
      hasCustomContentType = true;
1✔
146
    }
147

148
    unsigned nsent;
149
    std::string line;
10✔
150

151
    if ( !cannotSendStatus )
10✔
152
    {
153
      line += "HTTP/1.1 200 OK\n";
6✔
154
    }
155
    line += name->value() + ": " + value->value() + "\n";
10✔
156

157
    bool res =
158
        sck_.send_nowait( (void*)( line.c_str() + continuing_offset ),
10✔
159
                          static_cast<unsigned int>( line.length() - continuing_offset ), &nsent );
10✔
160

161
    if ( res )
10✔
162
    {
163
      cannotSendStatus = true;
10✔
164
      continuing_offset = 0;
10✔
165
      return new BLong( 1 );
10✔
166
    }
167

NEW
168
    continuing_offset += nsent;
×
NEW
169
    auto& uoex = uoexec();
×
NEW
170
    uoex.SleepForMs( 500u );
×
NEW
171
    --uoex.PC;
×
NEW
172
    return uoex.fparams[0]->impptr();
×
173
  }
10✔
174
  return new BError( "Invalid parameter type" );
×
175
}
176

177
BObjectImp* HttpExecutorModule::mf_WriteHtml()
×
178
{
179
  const String* str;
180
  if ( !sck_.connected() )
×
181
  {
182
    exec.seterror( true );
×
183
    return new BError( "Socket is disconnected" );
×
184
  }
185
  if ( getStringParam( 0, str ) )
×
186
  {
187
    // TODO: some tricky stuff so if the socket blocks, the script goes to
188
    // sleep for a bit and sends the rest later
189
    unsigned nsent;
190

191
    std::string s;
×
192
    if ( !cannotSendStatus )
×
193
    {
194
      s += "HTTP/1.1 200 OK\n";
×
195
    }
196

197
    if ( !cannotSendHeaders )
×
198
    {
199
      if ( !hasCustomContentType )
×
200
      {
201
        s += "Content-Type: text/html\n";
×
202
      }
203
      s += "\n";
×
204
    }
205
    s += str->value();
×
206

207
    bool res =
208
        sck_.send_nowait( (void*)( s.c_str() + continuing_offset ),
×
209
                          static_cast<unsigned int>( s.length() - continuing_offset ), &nsent );
×
210
    if ( res )
×
211
    {
212
      cannotSendStatus = true;
×
213
      cannotSendHeaders = true;
×
214
      continuing_offset = 0;
×
215
      // we don't really care if this works or not, terribly.
216
      sck_.send_nowait( "\n", 1, &nsent );
×
217
      return new BLong( 1 );
×
218
    }
219

NEW
220
    continuing_offset += nsent;
×
NEW
221
    auto& uoex = uoexec();
×
NEW
222
    uoex.SleepForMs( 500u );
×
NEW
223
    --uoex.PC;
×
NEW
224
    return uoex.fparams[0]->impptr();
×
UNCOV
225
  }
×
226

NEW
227
  return new BError( "Invalid parameter type" );
×
228
}
229

230
BObjectImp* HttpExecutorModule::mf_WriteHtmlRaw()
12✔
231
{
232
  const String* str;
233
  if ( !sck_.connected() )
12✔
234
  {
235
    exec.seterror( true );
×
236
    return new BError( "Socket is disconnected" );
×
237
  }
238
  exec.makeString( 0 );
12✔
239
  if ( getStringParam( 0, str ) )
12✔
240
  {
241
    // TODO: some tricky stuff so if the socket blocks, the script goes to
242
    // sleep for a bit and sends the rest later
243

244
    unsigned nsent;
245
    std::string s;
12✔
246

247
    if ( !cannotSendStatus )
12✔
248
    {
249
      s += "HTTP/1.1 200 OK\n";
5✔
250
    }
251

252
    if ( !cannotSendHeaders )
12✔
253
    {
254
      if ( !hasCustomContentType )
12✔
255
      {
256
        s += "Content-Type: text/html\n";
12✔
257
      }
258
      s += "\n";
12✔
259
    }
260
    s += str->value();
12✔
261

262
    bool res =
263
        sck_.send_nowait( (void*)( s.c_str() + continuing_offset ),
12✔
264
                          static_cast<unsigned int>( s.length() - continuing_offset ), &nsent );
12✔
265
    if ( res )
12✔
266
    {
267
      cannotSendStatus = true;
12✔
268
      cannotSendHeaders = true;
12✔
269
      continuing_offset = 0;
12✔
270
      return new BLong( 1 );
12✔
271
    }
272

NEW
273
    continuing_offset += nsent;
×
NEW
274
    auto& uoex = uoexec();
×
NEW
275
    uoex.SleepForMs( 500u );
×
NEW
276
    --uoex.PC;
×
NEW
277
    return uoex.fparams[0]->impptr();
×
278
  }
12✔
279

NEW
280
  return new BError( "Invalid parameter type" );
×
281
}
282

283
#if 0
284
  BObjectImp* HttpExecutorModule::mf_WriteHtml()
285
  {
286
    const String* str;
287
    if (getStringParam( 0, str ))
288
    {
289
    // TODO: some tricky stuff so if the socket blocks, the script goes to
290
    // sleep for a bit and sends the rest later
291
    http_writeline( sck_, str->value() );
292
    return new BLong(1);
293
    }
294
    else
295
    {
296
    return new BError( "Invalid parameter type" );
297
    }
298
  }
299
#endif
300

301
BObjectImp* HttpExecutorModule::mf_QueryParam()
108✔
302
{
303
  const String* str;
304
  if ( getStringParam( 0, str ) )
108✔
305
  {
306
    QueryParamMap::iterator itr = params_.find( str->data() );
108✔
307
    if ( itr != params_.end() )
108✔
308
      return new String( ( *itr ).second );
67✔
309
    return new BLong( 0 );
41✔
310
  }
311

NEW
312
  return new BError( "Invalid parameter type" );
×
313
}
314

315
BObjectImp* HttpExecutorModule::mf_QueryIP()
×
316
{
317
  return new String( query_ip_ );
×
318
}
319

320

321
// query_string is everything after the '?'
322
void HttpExecutorModule::read_query_string( const std::string& query_string )
18✔
323
{
324
  if ( !query_string.empty() )
18✔
325
  {
326
    std::string::size_type brk;
327
    std::string::size_type start = 0;
17✔
328
    do
329
    {
330
      brk = query_string.find( '&', start );
67✔
331
      std::string param =
332
          query_string.substr( start, ( brk == std::string::npos ) ? brk : brk - start );
67✔
333

334
      std::string name, value;
67✔
335
      std::string::size_type eq = param.find( '=' );
67✔
336
      if ( eq != std::string::npos )
67✔
337
      {
338
        name = param.substr( 0, eq );
67✔
339
        value = Core::http_decodestr( param.substr( eq + 1 ) );
67✔
340
      }
341
      else
342
      {
343
        name = param;
×
344
        value = "";
×
345
      }
346
      params_[name.c_str()] = value;
67✔
347

348
      if ( Plib::systemstate.config.web_server_debug )
67✔
349
        INFO_PRINTLN( "http-param: '{}', '{}'", param, Core::http_decodestr( param ) );
×
350

351
      start = brk + 1;
67✔
352
    } while ( brk != std::string::npos );
67✔
353
  }
354
}
18✔
355

356
void HttpExecutorModule::read_query_ip()
18✔
357
{
358
  query_ip_ = sck_.getpeername();
18✔
359
}
18✔
360

361
size_t HttpExecutorModule::sizeEstimate() const
×
362
{
363
  size_t size = sizeof( *this ) + Clib::memsize( params_ );
×
364
  return size;
×
365
}
366
}  // namespace Module
367
}  // namespace Pol
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc