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

polserver / polserver / 28964407401

08 Jul 2026 05:58PM UTC coverage: 61.276% (+0.3%) from 60.927%
28964407401

push

github

web-flow
Split bobject header  (#892)

* splitted bobject header

* fixed runecl

* crashfix

* missing header

* more missing (debug build)

* runecl debug include

* renamed contiter, moved formating

* removed more unused headers

1145 of 1517 new or added lines in 23 files covered. (75.48%)

217 existing lines in 4 files now uncovered.

44972 of 73392 relevant lines covered (61.28%)

557151.3 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

8
#include "bscript/berror.h"
9
#include "bscript/blong.h"
10
#include "bscript/bstring.h"
11
#include "clib/logfacility.h"
12
#include "clib/network/wnsckt.h"
13
#include "clib/stlutil.h"
14
#include "plib/systemstate.h"
15

16
#include "../polwww.h"
17
#include "../uoexec.h"
18

19
#include <module_defs/http.h>
20

21
namespace Pol
22
{
23
namespace Module
24
{
25
using namespace Bscript;
26

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

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

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

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

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

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

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

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

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

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

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

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

122

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

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

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

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

146
    unsigned nsent;
147
    std::string line;
10✔
148

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

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

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

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

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

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

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

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

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

225
  return new BError( "Invalid parameter type" );
×
226
}
227

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

242
    unsigned nsent;
243
    std::string s;
12✔
244

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

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

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

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

278
  return new BError( "Invalid parameter type" );
×
279
}
280

281
BObjectImp* HttpExecutorModule::mf_QueryParam()
108✔
282
{
283
  const String* str;
284
  if ( getStringParam( 0, str ) )
108✔
285
  {
286
    QueryParamMap::iterator itr = params_.find( str->data() );
108✔
287
    if ( itr != params_.end() )
108✔
288
      return new String( ( *itr ).second );
67✔
289
    return new BLong( 0 );
41✔
290
  }
291

UNCOV
292
  return new BError( "Invalid parameter type" );
×
293
}
294

UNCOV
295
BObjectImp* HttpExecutorModule::mf_QueryIP()
×
296
{
UNCOV
297
  return new String( query_ip_ );
×
298
}
299

300

301
// query_string is everything after the '?'
302
void HttpExecutorModule::read_query_string( const std::string& query_string )
18✔
303
{
304
  if ( !query_string.empty() )
18✔
305
  {
306
    std::string::size_type brk;
307
    std::string::size_type start = 0;
17✔
308
    do
309
    {
310
      brk = query_string.find( '&', start );
67✔
311
      std::string param =
312
          query_string.substr( start, ( brk == std::string::npos ) ? brk : brk - start );
67✔
313

314
      std::string name, value;
67✔
315
      std::string::size_type eq = param.find( '=' );
67✔
316
      if ( eq != std::string::npos )
67✔
317
      {
318
        name = param.substr( 0, eq );
67✔
319
        value = Core::http_decodestr( param.substr( eq + 1 ) );
67✔
320
      }
321
      else
322
      {
UNCOV
323
        name = param;
×
UNCOV
324
        value = "";
×
325
      }
326
      params_[name.c_str()] = value;
67✔
327

328
      if ( Plib::systemstate.config.web_server_debug )
67✔
UNCOV
329
        INFO_PRINTLN( "http-param: '{}', '{}'", param, Core::http_decodestr( param ) );
×
330

331
      start = brk + 1;
67✔
332
    } while ( brk != std::string::npos );
67✔
333
  }
334
}
18✔
335

336
void HttpExecutorModule::read_query_ip()
18✔
337
{
338
  query_ip_ = sck_.getpeername();
18✔
339
}
18✔
340

UNCOV
341
size_t HttpExecutorModule::sizeEstimate() const
×
342
{
UNCOV
343
  size_t size = sizeof( *this ) + Clib::memsize( params_ );
×
UNCOV
344
  return size;
×
345
}
346
}  // namespace Module
347
}  // namespace Pol
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc